| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 分布式还有这个坑 -> 正文阅读 |
|
[大数据]分布式还有这个坑 |
hi,大家好,我是康师傅,最近看到一个比较有意思的问题,关于分布式锁的,自己平时在工作中也有用到分布式锁,但是确实也没注意到一些临界值的问题,说白了就是没有进行深度思考。关于这个标题,你可能会比较诧异,锁还能怎么优雅删除?直接一个 delete 不就完了,不然还怎么删除。 首先啊,我们先简单说下为什么要分布式锁,现在基本上都是分布式系统,应该没有什么系统是部署的单节点吧,因为单节点风险比较大,如果节点宕机,那么整个应用就起不来,如果是多节点,那么好处就多多了,可以做到负载均衡,高可用,即使一个节点挂了,还有其他节点可用,服务整体依然可用。 分布式虽好,但是也带来很多问题,比如对于临界资源的保护,在分布式系统下,自然而然离不开分布式锁的使用,分布锁的实现可以用 redis、zookeeper 等,但这些不是我们今天讨论的重点。 以 redis 为例,我们可以使用 redis 的 但是啊,这里有个问题,代码的业务逻辑复杂,很多地方有
如果我们不小心在某个地方忘记了删除(解锁),那么这个锁就永远无法解开了,这就会导致线上事故了。于是我们可以对这个锁加个过期时间: 因此问题来了,如果锁时间到了,但是还没执行完逻辑,最后处理完逻辑再正常删除会导致什么问题?
这时是不是发现了问题所在,造成这个问题的根本原因就是节点 A 删错了锁,把 B 的锁给删了,那如何避免呢? 延长我们可以这样想,A 的业务逻辑还没走完,就不要放 B 进来,哪怕 A 花了很长时间,所以我们的锁可以不加过期时间,这样的话锁就不会自动消失,但是你要承担异常带来的风险:比如我们上面说到的在某个分支判断处忘了删除,或者程序还没走到解锁的时候异常退出,这些风险还是挺高的,那有什么办法让锁有过期时间,也不会在业务逻辑还没走完的时候自动失效呢?答案就是自动延长,比如起一个监听线程,这个线程干两件事:
当然这个只是个想法,真正实现起来,我觉得相对还是比较不好把握这个“度”的,比如剩余多少时间开始尝试延长,每次延长多少是个问题,如果延长的时间比较短,那么可能还要几次延长,延长的比较长可能还比较好,因为可以自己删除。 唯一我们再来看看另一个更简单的方法,我们这次不考虑延长锁的时间了,失效就失效了,只不过我们要确认要删除的锁是不是一开始我们上的那一把?那如何确认呢?我们只要在一开始上锁的时候设置一个唯一 ID 来替代呆板的“a” (setex lock 1 a),这样下次准备删除的时候我们先 check 下这个 value 是不是我们一开始设置的唯一 ID,如果是的话,说明是我们自己上的那一把,如果不是的话,那么说明锁在我们执行期间失效了,然后给别人上了,我们忽略就行,不需要删除。
看着好像没毛病,但是我们千万不要忘记原子性这个东西,我们知道 redis 本身处理命令是个单线程,单个指令不可分割,可以保证原子性,但是在此例子中,发现没有~我们先 get 判断了下值,然后再删除,这整个过程其实不是原子性的,我们看下下面的例子:
造成这个问题的根本原因,就是用户 A 在读取 lock 和删除 lock 这个时间期间被用户 B 正好插入了进来,从而造成了误删,那如何解决这个问题呢?其实也很简单,redis 提供了 lua 脚本,lua 脚本会被 redis 当成一个整体,从而保证原子性,我们只需要把 if get 和 del 用 lua 实现即可,具体 lua 怎么编写,这里就不细说了。 ok,这次要说的就这么多,现在回想起来我以前用的很多分布式锁他们的 value 都是简单的 1,既没有考虑到误删也没有考虑到原子的问题,不知道你们有没有踩过同样的坑。 最后如果你喜欢我的文章,觉得我的文章对你有帮助的话,小手一动点个赞再走~ 往期精彩: ? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 6:15:31- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |