左耳听风
陈皓
网名“左耳朵耗子”,资深技术专家,骨灰级程序员
立即订阅
40357 人已学习
课程目录
已完结 108 讲
0/6登录后,你可以任选6讲全文学习。
开篇词 | 洞悉技术的本质,享受科技的乐趣
免费
01 | 程序员如何用技术变现(上)
02 | 程序员如何用技术变现(下)
03 | Equifax信息泄露始末
04 | 从Equifax信息泄露看数据安全
05 | 何为技术领导力?
06 | 如何才能拥有技术领导力?
07 | 推荐阅读:每个程序员都该知道的知识
08 | Go语言,Docker和新技术
09 | 答疑解惑:渴望、热情和选择
10 | 如何成为一个大家愿意追随的Leader?
11 | 程序中的错误处理:错误返回码和异常捕捉
12 | 程序中的错误处理:异步编程以及我的最佳实践
13 | 魔数 0x5f3759df
14 | 推荐阅读:机器学习101
15 | 时间管理:同扭曲时间的事儿抗争
16 | 时间管理:如何利用好自己的时间?
17 | 故障处理最佳实践:应对故障
18 | 故障处理最佳实践:故障改进
19 | 答疑解惑:我们应该能够识别的表象和本质
20 | Git协同工作流,你该怎么选?
21 | 分布式系统架构的冰与火
22 | 从亚马逊的实践,谈分布式系统的难点
23 | 分布式系统的技术栈
24 | 分布式系统关键技术:全栈监控
25 | 分布式系统关键技术:服务调度
26 | 分布式系统关键技术:流量与数据调度
27 | 洞悉PaaS平台的本质
28 | 推荐阅读:分布式系统架构经典资料
29 | 推荐阅读:分布式数据调度相关论文
30 | 编程范式游记(1)- 起源
31 | 编程范式游记(2)- 泛型编程
32 | 编程范式游记(3) - 类型系统和泛型的本质
33 | 编程范式游记(4)- 函数式编程
34 | 编程范式游记(5)- 修饰器模式
35 | 编程范式游记(6)- 面向对象编程
36 | 编程范式游记(7)- 基于原型的编程范式
37 | 编程范式游记(8)- Go 语言的委托模式
38 | 编程范式游记(9)- 编程的本质
39 | 编程范式游记(10)- 逻辑编程范式
40 | 编程范式游记(11)- 程序世界里的编程范式
41 | 弹力设计篇之“认识故障和弹力设计”
42 | 弹力设计篇之“隔离设计”
43 | 弹力设计篇之“异步通讯设计”
44 | 弹力设计篇之“幂等性设计”
45 | 弹力设计篇之“服务的状态”
46 | 弹力设计篇之“补偿事务”
47 | 弹力设计篇之“重试设计”
48 | 弹力设计篇之“熔断设计”
49 | 弹力设计篇之“限流设计”
50 | 弹力设计篇之“降级设计”
51 | 弹力设计篇之“弹力设计总结”
52 | 管理设计篇之“分布式锁”
53 | 管理设计篇之“配置中心”
54 | 管理设计篇之“边车模式”
55 | 管理设计篇之“服务网格”
56 | 管理设计篇之“网关模式”
57 | 管理设计篇之“部署升级策略”
58 | 性能设计篇之“缓存”
59 | 性能设计篇之“异步处理”
60 | 性能设计篇之“数据库扩展”
61 | 性能设计篇之“秒杀”
62 | 性能设计篇之“边缘计算”
63 | 区块链技术的本质
64 | 区块链技术细节:哈希算法
65 | 区块链技术细节:加密和挖矿
66 | 区块链技术细节:去中心化的共识机制
67 | 区块链技术细节:智能合约
68 | 区块链技术 - 传统金融和虚拟货币
69 | 程序员练级攻略:开篇词
70 | 程序员练级攻略:零基础启蒙
71 | 程序员练级攻略:正式入门
72 | 程序员练级攻略:程序员修养
73 | 程序员练级攻略:编程语言
74 | 程序员练级攻略:理论学科
75 | 程序员练级攻略:系统知识
76 | 程序员练级攻略:软件设计
77 | 程序员练级攻略:Linux系统、内存和网络
78 | 程序员练级攻略:异步I/O模型和Lock-Free编程
79 | 程序员练级攻略:Java底层知识
80 | 程序员练级攻略:数据库
81 | 程序员练级攻略:分布式架构入门
82 | 程序员练级攻略:分布式架构经典图书和论文
83 | 程序员练级攻略:分布式架构工程设计
84 | 程序员练级攻略:微服务
85 | 程序员练级攻略:容器化和自动化运维
86 | 程序员练级攻略:机器学习和人工智能
87 | 程序员练级攻略:前端基础和底层原理
88 | 程序员练级攻略:前端性能优化和框架
89 | 程序员练级攻略:UI/UX设计
90 | 程序员练级攻略:技术资源集散地
91 | 程序员面试攻略:面试前的准备
92 | 程序员面试攻略:面试中的技巧
93 | 程序员面试攻略:面试风格
94 | 程序员面试攻略:实力才是王中王
95 | 高效学习:端正学习态度
96 | 高效学习:源头、原理和知识地图
97 | 高效学习:深度,归纳和坚持实践
98 | 高效学习:如何学习和阅读代码
99 | 高效学习:面对枯燥和量大的知识
左耳听风
登录|注册

52 | 管理设计篇之“分布式锁”

陈皓 2018-03-29
我们知道,在多线程情况下访问一些共享资源需要加锁,不然就会出现数据被写乱的问题。在分布式系统下,这样的问题也是一样的。只不过,我们需要一个分布式的锁服务。对于分布式的锁服务,一般可以用数据库 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/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《左耳听风》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(29)

  • Randy
    现实生活中也有不需要更新某个数据的场景,只是为了同步或是互斥一下不同机器上的线程,这时候像 Redis 这样的分布式锁服务就有意义了
    这句没明白,如果要进行互斥或同步操作,那就是要对同一个资源进行写操作,如果只是读操作那就不需要锁保护了,那分布式锁的意义是什么?
    2018-04-19
    1
    16
  • 林子
    如果用cas方式或者叫乐观锁来修改数据库中表(共享资源),会出现脏读问题,耗子叔,这点没提到。
    2018-07-09
    7
  • 天天向上
    分布式锁 应该是 先获取锁 再进行业务操作 属于悲观锁 而用乐观锁代替 又演变为cas代替 这样合适吗? 其实悲观和乐观 核心是面对的并发度不一样,如果在大并发下用乐观锁 应该失败的几率会增大,用悲观锁避免大量失败,但是会block!麻烦耗子哥 指导指导

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

    2018-05-08
    4
  • yun
    对资源修改,用cas而不是分布式锁,我反对
    1:前提是共享资源的修改得提供cas,比如我要更新hdfs,然后再在hbase上更新meta,为了保证一致性,要用分布式锁
    2,资源一存储在hbase,支持cas,资源二redis上,二者都支持cas,服务更新数据时要更新二者,服务是多个进城并发干,为了保证一致性,得有分布式锁,单个数据库的cas不行

    cas和分布式锁是两个完全不同的东西,cas像是单机的乐观锁,能用cas的话,不用分布式式锁,那不废话吗?能单机干的,谁会上分布式
    你跨多个服务,搞一个cas,试试?

    文中的令牌和cas,他们间确实类似。但是分布式锁中带令牌,就是为了解决,客户端认为占有锁,到实际锁过期的问题,此时没必要对比cas

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

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

    2018-04-19
    3
  • 董泽润
    https://github.com/dongzerun/dlock
    这是我在用的,redis lua 实现,和耗子叔的相似
    2018-06-21
    2
  • 王磊
    皓哥,有个问题想确认下,redlock是要求各个节点独立部署,都是master,那么这样的部署方式是否就限定这N台Redis不能同时作为缓存服务器了?
    2018-06-08
    1
    2
  • ZhYB
    redis锁timeout确实是个问题,配合存储的版本控制一起做能解决数据准确问题。但是说存储上cas可以代替分布式锁,就不对了。分布式锁锁住的是计算过程和更新存储两件事,而cas只能管更新存储这一件事,也就是二者就不是一个级别的东西。再说锁住计算过程这件事在正常情况下是没有问题的,而当出现极端异常下的超时问题时,出现了同时计算,出现了冗余计算,这完全可以接受。
    2019-06-26
    1
  • 山分子
    用过redis和etcd的分布式锁,用分布式锁的场景有两个,一个是定时任务,一个是阻止客户端的重复提交。
    2019-04-18
    1
  • 小新是也
    锁还是感觉zk专业一点
    2018-11-18
    1
  • junshuaizhang
    有两个问题
    1.ABA问题文中没有介绍咋处理。
    2.对于用库存当version虽然解决了并发问题,但是对实际性能影响太大。
    2019-12-09
  • 万丈尘
    同时更新同一条数据真的合理吗,使用不使用cas都不会出错,因为数据库原子性,相反这种情况需要考虑的是执行顺序而不是抢占一个锁
    2019-09-09
  • 布小丫学编程
    支付回调返回就是使用的分布式锁来实现的,容许有一些错误的出现,但是实现起来会更简单一些。
    Redis分布式锁是可以实现大粒度的锁,不需要考虑每一个点的更新插入都满足幂等性,实现起来更加简单快捷。小并发量时使用会更快捷。
    数据库乐观锁只有在数据库操作时满足幂等性,但是其他redis、mongodb等的都是不可回滚的,所以这些场景下必须使用Redis分布式锁。可能更适合大并发量访问时候的。
    2019-08-31
  • edisonhuang
    当我们需要对资源做互斥访问时,分布式服务也像单机服务一般,需要对资源加锁。分布式锁需要保证安全性,避免死锁和容错性
    2019-07-15
  • 涛哥迷妹
    发现了一篇 好文 https://juejin.im/post/5bbb0d8df265da0abd3533a5#heading-23
    2019-06-25
  • 靠人品去赢
    分布式锁有点像并发编程
    2019-04-15
  • 格瑞图
    另外,多说一下。这种 fence token 的玩法,在数据库那边一般会用 timestamp 时间截来玩。时间戳吧?
    2018-11-16
  • 欧星星
    比方说对余额加减可以使用CAS来实现,对于那种每人只能领取一次的优惠活动就要用锁来对每个用户做同步互斥操作因为这里除了资源的修改还有业务上的判断
    2018-07-15
  • tiger
    MySQL的事务在第一个事务获取共享锁之后,再获取排他锁的过程中,其它的事务也在等待获取排他锁,于是产生了死锁,这个可以通过重入锁解决,为什么MySQL没有这么做呢?
    2018-07-10
收起评论
29
返回
顶部