从构建分布式秒杀系统聊聊分布式锁

2018 年 8 月 7 日 开源中国

#扫描上方二维码报名成都源创会#


作者:小柒2012

链接:

https://my.oschina.net/52love/blog/1921097

如需转载请联系授权


前言


最近懒成一坨屎,学不动系列一波接一波,大多还都是底层原理相关的。上周末抽时间重读了周志明大湿的 JVM 高效并发部分,每读一遍都有不同的感悟。路漫漫,借此,把前段时间搞着玩的秒杀案例中的分布式锁深入了解一下。


案例介绍


在尝试了解分布式锁之前,大家可以想象一下,什么场景下会使用分布式锁?



单机应用架构中,秒杀案例使用ReentrantLcok或者synchronized来达到秒杀商品互斥的目的。然而在分布式系统中,会存在多台机器并行去实现同一个功能。也就是说,在多进程中,如果还使用以上JDK提供的进程锁,来并发访问数据库资源就可能会出现商品超卖的情况。因此,需要我们来实现自己的分布式锁。


实现一个分布式锁应该具备的特性:


  • 高可用、高性能的获取锁与释放锁

  • 在分布式系统环境下,一个方法或者变量同一时间只能被一个线程操作

  • 具备锁失效机制,网络中断或宕机无法释放锁时,锁必须被删除,防止死锁

  • 具备阻塞锁特性,即没有获取到锁,则继续等待获取锁

  • 具备非阻塞锁特性,即没有获取到锁,则直接返回获取锁失败

  • 具备可重入特性,一个线程中可以多次获取同一把锁,比如一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法,而无需重新获得锁


在之前的秒杀案例中,我们曾介绍过关于分布式锁几种实现方式:


  • 基于数据库实现分布式锁

  • 基于 Redis 实现分布式锁

  • 基于 Zookeeper 实现分布式锁


前两种对于分布式生产环境来说并不是特别推荐,高并发下数据库锁性能太差,Redis在锁时间限制和缓存一致性存在一定问题。这里我们重点介绍一下 Zookeeper 如何实现分布式锁。


实现原理


ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能存在唯一文件名。



数据模型


  • PERSISTENT 持久化节点,节点创建后,不会因为会话失效而消失

  • EPHEMERAL 临时节点, 客户端session超时此类节点就会被自动删除

  • EPHEMERAL_SEQUENTIAL 临时自动编号节点

  • PERSISTENT_SEQUENTIAL 顺序自动编号持久化节点,这种节点会根据当前已存在的节点数自动加 1


监视器(watcher)


当创建一个节点时,可以注册一个该节点的监视器,当节点状态发生改变时,watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知,因为watch只能被触发一次。


根据zookeeper的这些特性,我们来看看如何利用这些特性来实现分布式锁:


  • 创建一个锁目录lock

  • 线程A获取锁会在lock目录下,创建临时顺序节点

  • 获取锁目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁

  • 线程B创建临时节点并获取所有兄弟节点,判断自己不是最小节点,设置监听(watcher)比自己次小的节点(只关注比自己次小的节点是为了防止发生“羊群效应”)

  • 线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是最小的节点,获得锁


代码分析


尽管ZooKeeper已经封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。但是如果让一个普通开发者去手撸一个分布式锁还是比较困难的,在秒杀案例中我们直接使用 Apache 开源的curator 开实现 Zookeeper 分布式锁。


这里我们使用以下版本,截止目前最新版4.0.1:



首先,我们看下InterProcessLock接口中的几个方法:



获取锁:



Zookeeper获取锁实现:




释放锁:



测试案例


为了更好的理解其原理和代码分析中获取锁的过程,这里我们实现一个简单的Demo:



这里我们开启5个线程,每个线程获取锁的最大等待时间为5秒,为了模拟具体业务场景,方法中设置4秒等待时间。开始执行main方法,通过ZooInspector监控/curator/lock下的节点如下图:



对,没错,设置4秒的业务处理时长就是为了观察生成了几个顺序节点。果然如案例中所述,每个线程都会生成一个节点并且还是有序的。


观察控制台,我们会发现只有两个线程获取锁成功,另外三个线程超时获取锁失败会自动删除节点。线程执行完毕我们刷新一下/curator/lock节点,发现刚才创建的五个子节点已经不存在了。


小结


通过分析第三方开源工具实现的分布式锁方式,收获还是满满的。学习本身就是一个由浅入深的过程,从如何调用API,到理解其代码逻辑实现,想要更深入可以去挖掘Zookeeper的核心算法ZAB协议。


最后为了方便大家学习,总结了学习过程中遇到的几个关键词:重入锁、自旋锁、有序节点、阻塞、非阻塞、监听,希望对大家有所帮助。


秒杀案例:


  • https://gitee.com/52itstyle/spring-boot-seckill


参考


  • https://yq.aliyun.com/articles/60663

  • http://www.hollischuang.com/archives/1716

  • http://www.cnblogs.com/sunddenly/p/4033574.html

  • http://ifeve.com/zookeeper-lock/

开源中国征稿开始啦!


开源中国 www.oschina.net 是目前备受关注、具有强大影响力的开源技术社区,拥有超过 200 万的开源技术精英。我们传播开源的理念,推广开源项目,为 IT 开发者提供一个发现、使用、并交流开源技术的平台。


现在我们开始对外征稿啦!如果你有优秀的技术文章想要分享,热点的行业资讯需要报道等等,欢迎联系开源中国进行投稿。投稿详情及联系方式请参见:我要投稿





推荐阅读

微软按月收费桌面计划,Win 10 将变成 Win 365?

由浅入深,聊聊权限设计

Istio 1.0 正式版发布,可用于生产环境!

福布斯:谷歌的 Flutter 和 Fuchsia 将成下一代新兴技术

网站 HTTP 升级 HTTPS 完全配置手册

点击“阅读原文”查看更多精彩内容

登录查看更多
0

相关内容

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。
【硬核书】可扩展机器学习:并行分布式方法
专知会员服务
82+阅读 · 2020年5月23日
Python分布式计算,171页pdf,Distributed Computing with Python
专知会员服务
106+阅读 · 2020年5月3日
【SIGMOD2020-腾讯】Web规模本体可扩展构建
专知会员服务
29+阅读 · 2020年4月12日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
知识图谱本体结构构建论文合集
专知会员服务
106+阅读 · 2019年10月9日
分布式智能计算系统前沿
中国计算机学会
19+阅读 · 2019年10月8日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
工行基于MySQL构建分布式架构的转型之路
炼数成金订阅号
15+阅读 · 2019年5月16日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
使用 Canal 实现数据异构
性能与架构
20+阅读 · 2019年3月4日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
可能是讲分布式系统最到位的一篇文章
InfoQ
8+阅读 · 2018年11月19日
浅显易懂的分布式TensorFlow入门教程
专知
7+阅读 · 2018年6月22日
大数据分析研究组开源Easy Machine Learning系统
中国科学院网络数据重点实验室
15+阅读 · 2017年6月13日
Arxiv
92+阅读 · 2020年2月28日
Arxiv
35+阅读 · 2019年11月7日
Efficiently Embedding Dynamic Knowledge Graphs
Arxiv
14+阅读 · 2019年10月15日
Arxiv
53+阅读 · 2018年12月11日
Arxiv
5+阅读 · 2018年5月1日
VIP会员
相关资讯
分布式智能计算系统前沿
中国计算机学会
19+阅读 · 2019年10月8日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
工行基于MySQL构建分布式架构的转型之路
炼数成金订阅号
15+阅读 · 2019年5月16日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
使用 Canal 实现数据异构
性能与架构
20+阅读 · 2019年3月4日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
可能是讲分布式系统最到位的一篇文章
InfoQ
8+阅读 · 2018年11月19日
浅显易懂的分布式TensorFlow入门教程
专知
7+阅读 · 2018年6月22日
大数据分析研究组开源Easy Machine Learning系统
中国科学院网络数据重点实验室
15+阅读 · 2017年6月13日
相关论文
Top
微信扫码咨询专知VIP会员