黄岛因特网站建设公司,网站运营需要,二手书网站开发的必要性,app运营Redisson 分布式锁#xff1f;在项目中哪里使用#xff1f;多久会进行释放#xff1f;如何加强一个分布式锁#xff1f;
答#xff1a;
什么时候需要使用分布式锁呢#xff1f;
在分布式的场景下#xff0c;使用 Java 的单机锁并不可以保证多个应用的同时操作共享资源…Redisson 分布式锁在项目中哪里使用多久会进行释放如何加强一个分布式锁
答
什么时候需要使用分布式锁呢
在分布式的场景下使用 Java 的单机锁并不可以保证多个应用的同时操作共享资源时的安全性需要通过分布式锁保证多个进程同步访问共享资源
举一个使用分布式锁的场景吧
在积分场景下需要使用分布式锁因为积分属于是共享资源需要保证多个应用对积分的同步访问才行那么如下图则为不添加分布式锁时如何造成了数据不安全 首先入门级别的分布式锁是通过 setnx 进行实现使用 setnx 实现有四个注意点 需要设置锁的超时时间如果不设置在释放锁时如果机器宕机会导致锁无法释放 需要设置一个唯一 ID表示这个锁是哪个用户添加的必须由添加锁的用户释放 如果不设置线程1在执行任务时可能锁的超时时间已经达到被自动释放此时线程2加锁开始执行业务但正好线程1执行完毕释放锁由于没有唯一ID表示线程1将线程2加的锁给释放掉了 需要锁续命 有可能锁的过期时间设置的太短导致业务没有执行完毕锁就被自动释放因此要使用锁续命来解决大概逻辑是使用子线程执行定时任务定时任务间隔时间要小于 key 的过期时间子线程隔一段时间判断主线程是否在执行如果在执行就重新设置一下过期时间 可重入问题setnx 实现的分布式锁不可重入这样获取锁的线程在重复进入相同锁的代码块中会造成死锁
而在 Redission 中已经帮我们实现好了分布式锁下来看一下 Redission 中的分布式锁
Redission 中获取锁逻辑
在 Redission 中加锁通过一系列调用会到达下边这个方法
他的可重入锁的原理也就是使用 hash 结构来存储锁key 表示锁是否存在如果已经存在表示需要重复访问同一把锁会将 value 1即每次重入一次 value 就加 1退出一次 value 就减 1
下列方法有三个参数分别为
KEYS[1] 锁名称ARGV[1] 锁失效时间ARGV[2] id “:” threadId; 锁的小key T RFutureT tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommandT command) {internalLockLeaseTime unit.toMillis(leaseTime);return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, command,if (redis.call(exists, KEYS[1]) 0) then redis.call(hset, KEYS[1], ARGV[2], 1); redis.call(pexpire, KEYS[1], ARGV[1]); return nil; end; if (redis.call(hexists, KEYS[1], ARGV[2]) 1) then redis.call(hincrby, KEYS[1], ARGV[2], 1); redis.call(pexpire, KEYS[1], ARGV[1]); return nil; end; return redis.call(pttl, KEYS[1]);,Collections.ObjectsingletonList(getName()), internalLockLeaseTime, getLockName(threadId));}Redission 中锁续命原理
Redission 底层有个看门狗机制加锁成功后会有一个定时任务默认锁的失效时间是 30s该定时任务每隔锁失效时间的 1/3 就会去续约锁时间也就是每隔 10s 进行锁续命
如何加强一个分布式锁
也就是如何提升一个分布式锁的性能分布式锁本质上是将并行操作改为串行那么我们可以通过使用分段锁来提升性能比如说有 1000 个库存的话读入到缓存中将分为 10 份进行存储即 product_stock_1 100, product_stock_2 100, ...给每一份都加上所那么多个线程来竞争这 10 把锁比原来竞争 1 把锁的性能提高 10 倍