当前位置: 首页 > news >正文

环境设计案例网站深圳网站关键词

环境设计案例网站,深圳网站关键词,保定网站建设优化,龙岩今天刚刚最新新闻事件一、基本原理和实现方式对比 分布式锁#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁#xff0c;只要大家使用的是同一把锁#xff0c;那么我们就能锁住线程#xff0c;不让线程进行#xff0c;让程序串行…一、基本原理和实现方式对比 分布式锁满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁只要大家使用的是同一把锁那么我们就能锁住线程不让线程进行让程序串行执行这就是分布式锁的核心思路 那么分布式锁他应该满足一些什么样的条件呢 可见性多个线程都能看到相同的结果注意这个地方说的可见性并不是并发编程中指的内存可见性只是说多个进程之间都能感知到变化的意思 互斥互斥是分布式锁的最基本的条件使得程序串行执行 高可用程序不易崩溃时时刻刻都保证较高的可用性 高性能由于加锁本身就让性能降低所有对于分布式锁本身需要他就较高的加锁性能和释放锁性能 安全性安全也是程序中必不可少的一环 常见的分布式锁有三种 Mysqlmysql本身就带有锁机制但是由于mysql性能本身一般所以采用分布式锁的情况下其实使用mysql作为分布式锁比较少见 Redisredis作为分布式锁是非常常见的一种使用方式现在企业级开发中基本都使用redis或者zookeeper作为分布式锁利用setnx这个方法如果插入key成功则表示获得到了锁如果有人插入成功其他人插入失败则表示无法获得到锁利用这套逻辑来实现分布式锁 Zookeeperzookeeper也是企业级开发中较好的一个实现分布式锁的方案由于本套视频并不讲解zookeeper的原理和分布式锁的实现所以不过多阐述 二、Redis分布式锁的实现核心思路 实现分布式锁时需要实现的两个基本方法 获取锁 互斥确保只能有一个线程获取锁 非阻塞尝试一次成功返回true失败返回false 释放锁 手动释放 超时释放获取锁时添加一个超时时间 为了防止添加锁成功后添加锁过期时间的过程中服务器宕机可以采取下面的做法 核心思路 我们利用redis 的setNx 方法当有多个线程进入时我们就利用该方法第一个线程进入时redis 中就有这个key 了返回了1如果结果是1则表示他抢到了锁那么他去执行业务然后再删除锁退出锁逻辑没有抢到锁的哥们等待一定时间后重试即可 三、实现分布式锁版本一 加锁逻辑 锁的基本接口 SimpleRedisLock 利用setnx方法进行加锁同时增加过期时间防止死锁此方法可以保证加锁和增加过期时间具有原子性 private static final String KEY_PREFIXlock: Override public boolean tryLock(long timeoutSec) {// 获取线程标示String threadId Thread.currentThread().getId()// 获取锁Boolean success stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX name, threadId , timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success); } 释放锁逻辑 SimpleRedisLock 释放锁防止删除别人的锁 public void unlock() {//通过del删除锁stringRedisTemplate.delete(KEY_PREFIX name); } 修改业务代码 Overridepublic Result seckillVoucher(Long voucherId) {// 1.查询优惠券SeckillVoucher voucher seckillVoucherService.getById(voucherId);// 2.判断秒杀是否开始if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {// 尚未开始return Result.fail(秒杀尚未开始);}// 3.判断秒杀是否已经结束if (voucher.getEndTime().isBefore(LocalDateTime.now())) {// 尚未开始return Result.fail(秒杀已经结束);}// 4.判断库存是否充足if (voucher.getStock() 1) {// 库存不足return Result.fail(库存不足);}Long userId UserHolder.getUser().getId();//创建锁对象(新增代码)SimpleRedisLock lock new SimpleRedisLock(order: userId, stringRedisTemplate);//获取锁对象boolean isLock lock.tryLock(1200);//加锁失败if (!isLock) {return Result.fail(不允许重复下单);}try {//获取代理对象(事务)IVoucherOrderService proxy (IVoucherOrderService) AopContext.currentProxy();return proxy.createVoucherOrder(voucherId);} finally {//释放锁lock.unlock();}} 四、Redis分布式锁误删情况说明 逻辑说明 持有锁的线程在锁的内部出现了阻塞导致他的锁自动释放这时其他线程线程2来尝试获得锁就拿到了这把锁然后线程2在持有锁执行过程中线程1反应过来继续执行而线程1执行过程中走到了删除锁逻辑此时就会把本应该属于线程2的锁进行删除这就是误删别人锁的情况说明 解决方案解决方案就是在每个线程释放锁的时候去判断一下当前这把锁是否属于自己如果属于自己则不进行锁的删除假设还是上边的情况线程1卡顿锁自动释放线程2进入到锁的内部执行逻辑此时线程1反应过来然后删除锁但是线程1一看当前这把锁不是属于自己于是不进行删除锁逻辑当线程2走到删除锁逻辑时如果没有卡过自动释放锁的时间点则判断当前这把锁是属于自己的于是删除这把锁。 因此业务流程可优化为如下  五、解决Redis分布式锁误删问题 需求修改之前的分布式锁实现满足在获取锁时存入线程标示可以用UUID表示 在释放锁时先获取锁中的线程标示判断是否与当前线程标示一致 如果一致则释放锁 如果不一致则不释放锁 核心逻辑在存入锁时放入自己线程的标识在删除锁时判断当前这把锁的标识是不是自己存入的如果是则进行删除如果不是则不进行删除。 具体代码如下加锁 private static final String ID_PREFIX UUID.randomUUID().toString(true) -; Override public boolean tryLock(long timeoutSec) {// 获取线程标示String threadId ID_PREFIX Thread.currentThread().getId();// 获取锁Boolean success stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX name, threadId, timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success); } 释放锁 public void unlock() {// 获取线程标示String threadId ID_PREFIX Thread.currentThread().getId();// 获取锁中的标示String id stringRedisTemplate.opsForValue().get(KEY_PREFIX name);// 判断标示是否一致if(threadId.equals(id)) {// 释放锁stringRedisTemplate.delete(KEY_PREFIX name);} } 有关代码实操说明 在我们修改完此处代码后我们重启工程然后启动两个线程第一个线程持有锁后手动释放锁第二个线程 此时进入到锁内部再放行第一个线程此时第一个线程由于锁的value值并非是自己所以不能释放锁也就无法删除别人的锁此时第二个线程能够正确释放锁通过这个案例初步说明我们解决了锁误删的问题。 下面内容了解即可 bilibili p61-p63 六、分布式锁的原子性问题了解 更为极端的误删逻辑说明 线程1现在持有锁之后在执行业务逻辑过程中他正准备删除锁而且已经走到了条件判断的过程中比如他已经拿到了当前这把锁确实是属于他自己的正准备删除锁但是此时他的锁到期了那么此时线程2进来但是线程1他会接着往后执行当他卡顿结束后他直接就会执行删除锁那行代码相当于条件判断并没有起到作用这就是删锁时的原子性问题之所以有这个问题是因为线程1的拿锁比锁删锁实际上并不是原子性的我们要防止刚才的情况发生 七、Lua脚本解决多条命令原子性问题了解 Redis提供了Lua脚本功能在一个脚本中编写多条Redis命令确保多条命令执行时的原子性。Lua是一种编程语言它的基本语法大家可以参考网站Lua 教程 | 菜鸟教程这里重点介绍Redis提供的调用函数我们可以使用lua去操作redis又能保证他的原子性这样就可以实现拿锁比锁删锁是一个原子性动作了作为Java程序员这一块并不作一个简单要求并不需要大家过于精通只需要知道他有什么作用即可。 这里重点介绍Redis提供的调用函数语法如下 redis.call(命令名称, key, 其它参数, ...) 例如我们要执行set name jack则脚本是这样 # 执行 set name jack redis.call(set, name, jack) 例如我们要先执行set name Rose再执行get name则脚本如下 # 先执行 set name jack redis.call(set, name, Rose) # 再执行 get name local name redis.call(get, name) # 返回 return name 写好脚本以后需要用Redis命令来调用脚本调用脚本的常见命令如下 例如我们要执行 redis.call(set, name, jack) 这个脚本语法如下 如果脚本中的key、value不想写死可以作为参数传递。key类型参数会放入KEYS数组其它参数会放入ARGV数组在脚本中可以从KEYS和ARGV数组获取这些参数 接下来我们来回一下我们释放锁的逻辑 释放锁的业务流程是这样的 1、获取锁中的线程标示 2、判断是否与指定的标示当前线程标示一致 3、如果一致则释放锁删除 4、如果不一致则什么都不做 如果用Lua脚本来表示则是这样的 最终我们操作redis的拿锁比锁删锁的lua脚本就会变成这样 -- 这里的 KEYS[1] 就是锁的key这里的ARGV[1] 就是当前线程标示 -- 获取锁中的标示判断是否与当前线程标示一致 if (redis.call(GET, KEYS[1]) ARGV[1]) then-- 一致则删除锁return redis.call(DEL, KEYS[1]) end -- 不一致则直接返回 return 0 八、利用Java代码调用Lua脚本改造分布式锁了解 lua脚本本身并不需要大家花费太多时间去研究只需要知道如何调用大致是什么意思即可所以在笔记中并不会详细的去解释这些lua表达式的含义。 我们的RedisTemplate中可以利用execute方法去执行lua脚本参数对应关系就如下图股 Java代码 private static final DefaultRedisScriptLong UNLOCK_SCRIPT;static {UNLOCK_SCRIPT new DefaultRedisScript();UNLOCK_SCRIPT.setLocation(new ClassPathResource(unlock.lua));UNLOCK_SCRIPT.setResultType(Long.class);}public void unlock() {// 调用lua脚本stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX name),ID_PREFIX Thread.currentThread().getId()); } 经过以上代码改造后我们就能够实现 拿锁比锁删锁的原子性动作了~ 小总结 基于Redis的分布式锁实现思路 利用set nx ex获取锁并设置过期时间保存线程标示 释放锁时先判断线程标示是否与自己一致一致则删除锁 特性 利用set nx满足互斥性 利用set ex保证故障时锁依然能释放避免死锁提高安全性 利用Redis集群保证高可用和高并发特性 笔者总结我们一路走来利用添加过期时间防止死锁问题的发生但是有了过期时间之后可能出现误删别人锁的问题这个问题我们开始是利用删之前 通过拿锁比锁删锁这个逻辑来解决的也就是删之前判断一下当前这把锁是否是属于自己的但是现在还有原子性问题也就是我们没法保证拿锁比锁删锁是一个原子性的动作最后通过lua表达式来解决这个问题 但是目前还剩下一个问题锁不住什么是锁不住呢你想一想如果当过期时间到了之后我们可以给他续期一下比如续个30s就好像是网吧上网 网费到了之后然后说来网管再给我来10块的是不是后边的问题都不会发生了那么续期问题怎么解决呢可以依赖于我们接下来要学习redission啦 测试逻辑 第一个线程进来得到了锁手动删除锁模拟锁超时了其他线程会执行lua来抢锁当第一天线程利用lua删除锁时lua能保证他不能删除他的锁第二个线程删除锁时利用lua同样可以保证不会删除别人的锁同时还能保证原子性。
http://www.hkea.cn/news/14395742/

相关文章:

  • 网站换空间 site网站中文名称注册
  • 网站开发的网站解释seo网站推广
  • 拼多多网站策划书客户软件管理系统
  • 网站制作长春中文域名价格
  • 担路网做网站多少钱建设租房信息网站
  • 西安网站制作顶尖如何配置iis网站
  • 网站获取qq号码 原理企业网站开发合同
  • 一个手机网站wordpress 即时通迅
  • 做恒生指数看什么网站专业网店推广
  • 家装设计网站排行榜前十名建设网站能赚钱吗
  • 做网站在什么地方找广州定制网站建设方案书
  • 常德网站建公司体系建设的意义
  • 织梦做的网站打开不是seo策略有哪些
  • 手机网站大全免费网站建设招标提问
  • 旅游网站栏目建设网站设计与制作专业
  • 网站建设公司找客户wordpress手机站如何做
  • 长春微建站是哪个平台的网站设计与网页配色实例精讲
  • 企业网站营销的典型案例宁波网站建设公司立找亿企邦
  • 安平县外贸网站建设成都旅游学院简介
  • 西安咪豆网站建设公司轻骑铃木摩托车官网
  • 校园网站建设网重庆网站seo分析
  • 企业网站建设方案书怎么写谷歌商店下载官方
  • 河南省建设厅网站公示公告买域名去哪个网站
  • 石家庄外贸网站建设公司做网站一个程序员够吗
  • 创意广告设计网站在猪八戒做网站有保障吗
  • 同仁微网站建设工作室做跨境的网站
  • 网站建设 食品php+mysql网站开发全程实例pdf
  • 网站建设研究方法wordpress和e
  • 3g 手机网站建网站的软件优帮云
  • 网站上怎么做推广比较好呢奉贤网页设计