左耳听风
陈皓
网名“左耳朵耗子”,资深技术专家
175859 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 119 讲
左耳听风
15
15
1.0x
00:00/00:00
登录|注册

52 | 管理设计:分布式锁

你好,我是陈皓,网名左耳朵耗子。
我们知道,在多线程情况下访问一些共享资源需要加锁,不然就会出现数据被写乱的问题。在分布式系统下,这样的问题也是一样的。只不过,我们需要一个分布式的锁服务。对于分布式的锁服务,一般可以用数据库 DB、Redis 和 ZooKeeper 等实现。不管怎么样,分布式的锁服务需要有以下几个特点。
安全性(Safety):在任意时刻,只有一个客户端可以获得锁(排他性)。
避免死锁:客户端最终一定可以获得锁,即使锁住某个资源的客户端在释放锁之前崩溃或者网络不可达。
容错性:只要锁服务集群中的大部分节点存活,Client 就可以进行加锁解锁操作。

Redis 的分布式锁服务

这里提一下,避免死锁的问题。下面以 Redis 的锁服务为例(参考 Redis 的官方文档 )。
我们通过以下命令对资源加锁。
SET resource_name my_random_value NX PX 30000
解释一下:
SET NX 命令只会在 key 不存在的时候给 key 赋值,PX 命令通知 Redis 保存这个 key 30000ms。
my_random_value 必须是全局唯一的值。这个随机数在释放锁时保证释放锁操作的安全性。
PX 操作后面的参数代表的是这个 key 的存活时间,称作锁过期时间。
当资源被锁定超过这个时间时,锁将自动释放。
获得锁的客户端如果没有在这个时间窗口内完成操作,就可能会有其他客户端获得锁,引起争用问题。
这里的原理是,只有在某个 key 不存在的情况下才能设置(set)成功该 key。于是,这就可以让多个进程并发去设置同一个 key,只有一个进程能设置成功。而其它的进程因为之前有人把 key 设置成功了,而导致失败(也就是获得锁失败)。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《左耳听风》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(44)

  • 最新
  • 精选
  • 天天向上
    分布式锁 应该是 先获取锁 再进行业务操作 属于悲观锁 而用乐观锁代替 又演变为cas代替 这样合适吗? 其实悲观和乐观 核心是面对的并发度不一样,如果在大并发下用乐观锁 应该失败的几率会增大,用悲观锁避免大量失败,但是会block!麻烦耗子哥 指导指导

    作者回复: 一切都是trade-off。不过实际情况下,乐观加上重试机制会好一些。

    3
    15
  • 约书亚
    皓哥,这篇文章前半段一直到cas之前基本是在说redlock,后面说到fence和cas,恰恰是redlock争论当中反方的观点---如果你想锁的资源,能提供给你cas功能,那还要分布式锁干嘛?这也是我的疑问,我觉得是悖论 在我使用consul时,我发现,如果我要锁住一个资源,理论上100%安全的必要条件是,我的资源就是那个锁本身,在consul就是那个资源只能是锁住key对应的value。consul本身也提供cas,但对客户端来说,没加锁的代码容易写 但换成其他资源,这个悖论就显现出来了。我的想法对么?

    作者回复: 这篇文章其实我是在不断地变换思路解决问题,不能说Redlock没用,其至少可以同步不同的client。而你的理解是对的,如果是有共享资源,最好是在那个资源上提供无锁实现。

    11
  • yun
    对资源修改,用cas而不是分布式锁,我反对 1:前提是共享资源的修改得提供cas,比如我要更新hdfs,然后再在hbase上更新meta,为了保证一致性,要用分布式锁 2,资源一存储在hbase,支持cas,资源二redis上,二者都支持cas,服务更新数据时要更新二者,服务是多个进城并发干,为了保证一致性,得有分布式锁,单个数据库的cas不行 cas和分布式锁是两个完全不同的东西,cas像是单机的乐观锁,能用cas的话,不用分布式式锁,那不废话吗?能单机干的,谁会上分布式 你跨多个服务,搞一个cas,试试? 文中的令牌和cas,他们间确实类似。但是分布式锁中带令牌,就是为了解决,客户端认为占有锁,到实际锁过期的问题,此时没必要对比cas
    14
    36
  • Randy
    现实生活中也有不需要更新某个数据的场景,只是为了同步或是互斥一下不同机器上的线程,这时候像 Redis 这样的分布式锁服务就有意义了 这句没明白,如果要进行互斥或同步操作,那就是要对同一个资源进行写操作,如果只是读操作那就不需要锁保护了,那分布式锁的意义是什么?
    13
    28
  • 林子
    如果用cas方式或者叫乐观锁来修改数据库中表(共享资源),会出现脏读问题,耗子叔,这点没提到。
    1
    15
  • 程序员Artist
    redis锁timeout确实是个问题,配合存储的版本控制一起做能解决数据准确问题。但是说存储上cas可以代替分布式锁,就不对了。分布式锁锁住的是计算过程和更新存储两件事,而cas只能管更新存储这一件事,也就是二者就不是一个级别的东西。再说锁住计算过程这件事在正常情况下是没有问题的,而当出现极端异常下的超时问题时,出现了同时计算,出现了冗余计算,这完全可以接受。
    6
    11
  • 黄宸
    看完本章有点疑问,对于一般性的数据库修改都是有锁的,所以不存在并发问题,没必要用cas。而文中的redis分布式锁在使用过程中使用nx,px 实现了占位和过期的操作,从而达到分布式锁的效果。其中说到如果先持到锁的服务在一次执行中时间超时,锁释放;其他发现未执行完成,服务再次抢锁,此时存在两个服务都获得同一把锁,这时如果会出现更新覆盖的问题,个人觉得不能理解为分布式锁的问题,应该是程序设计上要考虑重复执行,或者如何去规避重复执行,或者执行补偿的问题。
    1
    5
  • 董泽润
    https://github.com/dongzerun/dlock 这是我在用的,redis lua 实现,和耗子叔的相似
    4
  • 王磊
    皓哥,有个问题想确认下,redlock是要求各个节点独立部署,都是master,那么这样的部署方式是否就限定这N台Redis不能同时作为缓存服务器了?
    1
    4
  • 华烬
    数据库用timestamp的判断是否冲突是有风险的吧
    1
    4
收起评论
显示
设置
留言
44
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部