分布式锁的分析与过程实现

      对于多进程多机器 为了解决 对共享变量的读写 所造成的线程不安全问题 所以需要使用分布式锁 为什么常规的sync 锁不能解决 因为sync锁是但进程的锁  他只能保证一个进程下的线程的互斥性

对于分布式锁的实现 我了解的实现有基于 redis 实现的分布式锁  与数据库实现的分布式锁

基于redis 实现的分布式锁

  首先实现分布式锁 必须要满足

         1.互斥:只能有一个进程中的一个线程拿到这把锁

          2.当任务结束时我们在释放这个锁时不能释放成别人的锁

          3.不能死锁  必须对我们持有的锁设置过期时间

          4.基于3 必须设置过期时间防止死锁 同样也引入了一个问题 就是 当我们的任务还没有执行结束完 就过期 释放掉这个锁  这样也是不行的

          5.基于4的释放锁时必须保证原子性

实现分布式锁必须满足以上条件

            redis  的setNx命令 可以满足互斥  这条命令是  当key 不存在时则放入 并返回1  当存在时返回0  我们可以通过这个命令来进行加锁   加锁的同时我们需要放入一个唯一的随机值 方便我们后续进行解锁 释放自己获得的锁 在释放锁的时候需要判断当前是否是自己的锁 所以这里其实是2个操作 第一个先判断  然后删除  这里也需要保证释放锁的原子性  所以采用lua脚本保证 原子性 只能有一个线程进来。

             注意 原子性 这个其实有2种意思 在mysql 中的原子性 与并发编程里面的原子性 是不一样的意思  mysql中的原子性是 要么全部都执行成功要么都失败  并发编程与这里的原子性是指的 只能有一个线程进来   下面来看 redis 原生实现分布式锁的代码:

 通过上面的 代码可以基本实现分布式锁  但是对于上面的第四点如果业务执行在一半的时候 锁就过期了 那么这样也是不行的  所以在reddision 框架中实现的分布式锁中 有一个锁续期的一个机制 就是当锁快过期的时候 检查当前获得锁的线程是否还在执行业务代码 如果还在 就会进行一个续期 以次解决 锁过期的一个问题   但是以上就没有任何问题了吗  一般我们redis都会是集群部署  这样就会有一个新的问题

      在主从结构中  如果主节点获得到了锁 此时还未同步到从节点就突然挂机 从节点切换成主节点 继续获得这把锁 如果此时主节点重启变为了从节点 那么主节点与从节点都同时获得了这把锁 这样是违背我们上面所说的那几个条件  所以为了解决这个问题  redission 使用了红锁去解决这个问题

 简单说一下 红锁就是在获得锁时会对所有的节点发起获得这把锁 只有当超过半数的节点获得了这把锁 那么才认为真正的获得了这个锁

redis 还可以做过期消费 比如当用户10分组后还未支付则需要取消订单 这一业务逻辑我们该怎么做

如果基于redis  可以基于redis 的过期监听 但是redis 的过期监听并不能保证当key过期后立即被监听到 而且redis 5.0之前的过期监听是基于 发布订阅做的所以他不能保证消息的持久化 也就是说并不能保证一定能处理到过期的消息

 redis的 zset 数据结构也可以做 score 使用当前的时间戳加上需要等待的时间戳 作为score 然后redis 获取第最后一个 的score 值与当前时间戳进行比较 如果小于了当前时间戳则可以进行关单处理 但是这一方法也会有一些问题比如 会有重复消费的问题 可以在处理时做好幂等即可

redisson 为我们提供了一个延迟队列

首先来看结果

 

 首先定义一个阻塞队列  然后定义一个延迟队列  使用延迟队列对消息进行延迟处理并发送给队列 然后一直消费阻塞队列即可

 

 

redis 中还有geo 下期再说

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值