分布式架构中 经常遇到多线程共享数据的场景,这就会出现正常的代码逻辑下不能保证数据一致性的问题,分布式锁 应运而生。常见的分布式锁redis zk去实现
1、redis中setnx 指定常用于分布式锁 setnx 完整翻译是 (set if not exist) 意思就是如果不存在就set 否则 就不做处理
setnx 成功就返回1 失败就返回0
加锁代码
Boolean res = stringRedisTemplate.opsForValue().setIfAbsent("lock","100");
多线程情况下 加锁的目的就是 将并行的请求进来后 串行的去执行 保证了数据一致性。所以加锁 执行业务逻辑 释放锁。
释放锁代码
stringRedisTemplate.delete("lock");
执行业务逻辑时如果当前服务宕机 则其他线程则永远拿不到锁,于是修改加锁代码
Boolean res = stringRedisTemplate.opsForValue().setIfAbsent("lock","100",10,TimeUnit.SECONDS);
失效时间不能精确定义 因为你也判断不了业务逻辑具体的执行时间 会导致其他线程将另一个线程所加的锁删掉 那就会造成没加锁 一样的情况
Redisson锁 可以解决此类问题
Redisson是Redis官方推荐的Java版的Redis客户端
大致原理为: 线程1加锁 线程2就循环一致尝试加锁(等待线程1释放锁) 线程1中 如果加锁成功 在后台开启分线程 定时任务 执行检查主线程的锁是否还在 如果还在就自动给主线程延长其失效时间 假设主线程设置时间为锁的有效时间为30秒 分线程的定时任务执行间隔就为主线程的有效时间的3/1 为10秒执行一次
其底层原理就是 lua脚本 将操作作为原子性指令去完成的
redis 如何解决双写不一致的情况 ?
redisson 实现了 读写锁, 可使用读写锁 保证数据的一致性,区分读写锁(读的场景用读锁,写的场景用写锁) 又提高了并发的性能
锁的 原理也是将其改为原子性的指令然后实现的