⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/7255902957035323450 「ovO」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

技术的演变都是为了解决问题的,这也是技术演变吸引人的一点。

Redis分布式锁

分布式锁顾名思义 就是在分布式场景下 多台机器竞争一项资源去加锁

最简单的版本

首先就是最简单的版本,可以通过Redis的setnx命令(set if not exist)

setnx key value

这个命令会使Redis中如果不存在key就会创建值为value的key,存在的话就返回0

过期时间

如果获取锁的机器服务挂了呢?

其他机器:奶奶滴 怎么还不释放锁?

所以 有个兜底策略:设置过期时间(挂了之后过段时间锁自动过期释放了)

此时可以用一个Redis自带的原子性的操作命令:

setnx key value nx ex 100

时间单位是秒

万一释放错锁了怎么办?

看这么一个场景:

涉及到两个问题:

  • 任务还没处理完锁就过期释放了
  • 释放掉了别人的锁

对应的解决办法:

  • 锁的续约(根据业务加长时间,并且每过一段时间访问锁,如果存在就续约,增加时间)
  • 给每个锁区分一下,这是谁加的锁(锁的value可以设置UUID等唯一确定的值)

优化过后的:

lua实现原子性

上面的一步删除的时候会发生什么错误?

当然 这个问题上面已经解决了,就是UUID+线程id作为key,已经不会被其他线程删掉了,但是这么看来这种错误也是挺危险的,作为一个兜底方案,我们可以用lua脚本实现原子性

lua脚本可以这么写

最后的防御

分布式系统NPC

“

https://www.cnblogs.com/huilei/p/15916861.html

分布式系统最大的敌人可能就是NPC了,在这里它是Network Delay, Process Pause, Clock Drift的首字母缩写。我们先看看具体的NPC问题是什么:

  • Network Delay,网络延迟。虽然网络在多数情况下工作的还可以,虽然TCP保证传输顺序和不会丢失,但它无法消除网络延迟问题。
  • Process Pause,进程暂停。有很多种原因可以导致进程暂停:比如编程语言中的GC(垃圾回收机制)会暂停所有正在运行的线程;再比如,我们有时会暂停云服务器,从而可以在不重启的情况下将云服务器从一台主机迁移到另一台主机。我们无法确定性预测进程暂停的时长,你以为持续几百毫秒已经很长了,但实际上持续数分钟之久进程暂停并不罕见。
  • Clock Drift,时钟漂移。现实生活中我们通常认为时间是平稳流逝,单调递增的,但在计算机中不是。计算机使用时钟硬件计时,通常是石英钟,计时精度有限,同时受机器温度影响。为了在一定程度上同步网络上多个机器之间的时间,通常使用NTP协议将本地设备的时间与专门的时间服务器对齐,这样做的一个直接结果是设备的本地时间可能会突然向前或向后跳跃。

详见这篇文章:

“

https://zhuanlan.zhihu.com/p/341630692

NPC三个问题都是客观存在且无法消除的,没有完全安全的分布式锁(所以大家还是要根据业务来)

上面的场景中,主节点挂了咋办?

因为Redis是AP架构的,也就是说不能保证高一致性,主节点里的锁也许并没有同步到从节点里

这里可以用Redis官方的Red Lock 保证当前hash算法选择的节点的主从都有key了才会返回true

这种做法也有点“重”了,有些时候,杀鸡焉用牛刀

文章目录
  1. 1. Redis分布式锁
    1. 1.1. 最简单的版本
    2. 1.2. 过期时间
    3. 1.3. 万一释放错锁了怎么办?
    4. 1.4. lua实现原子性
    5. 1.5. 最后的防御