浅谈分布式锁

背景

微服务的兴起,使得应用分布式部署遍地开花。分布式部署确实能带来性能和效率上的提升,但在分布式环境中,分布式场景中的数据一致性问题一直是一个比较重要的话题。

分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)可用性(Availability)分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。有的时候,我们需要保证一个方法在同一时间内只能被同一个线程执行。在单机环境中,Java中其实提供了很多并发处理相关的关键字和API,比如synchronized关键字和ReentrantLock可重入锁,但是这些关键字和API在分布式场景中就无能为力了。也就是说单纯的Java API并不能提供分布式锁的能力。所以针对分布式锁的实现目前有多种方案。

分布式锁

分布式出现的场景

有段时间Redis之父和英国剑桥大学的分布式系统研究员MK(Martin Klepppmann)就RedLock是否安全的激烈的争论在互联网中也是一石激起千层浪,也引起我们吃瓜群众的站队支持(emmmm…站队到Redis)。Martin认为,一般情况下,我们使用到了分布式锁有两个重要的场景:

  • 效率:使用分布式锁可以避免不同节点重复相同的工作,这些工作会浪费资源。比如用户付了钱之后有可能不同节点会发出多封短信。
  • 正确性:加分布式锁同样可以避免破坏正确性的发生,如果两个节点在同一条数据上面操作,比如多个节点机器对同一个订单操作不同的流程有可能导致该笔订单状态出现错误,造成损失。

分布式锁的特点

纯洁的微笑(强哥)总结的分布式锁的特点如下:

  • 互斥性:和我们本地锁一样互斥性是最基本,但是分布式锁需要保证在不同的节点的不同线程的互斥。
  • 可重入性:同一个节点上的同一个线程如果获取了锁之后那么也可以在未释放之前再次获取到这个锁。
  • 锁超时:和本地锁一样支持锁超时,防止死锁。
  • 高效,高可用:加锁和解锁需要高效,同时也需要保证高可用,防止分布式锁失效,可以增加降级。
  • 支持阻塞和非阻塞:和ReentrantLock一样支持lock()和tryLock()以及tryLock(long timeout)。
  • 支持公平锁和非公平锁(可选):公平锁的意思是按照请求加锁的顺序获得锁,非公平锁就是相反无序的。

常见的分布式锁

  • 基于数据库实现分布式锁
  • 基于缓存(Redis,memcached,tair)实现分布式锁
  • 基于Zookeeper/Etcd实现分布式锁
  • 自研分布式锁:如谷歌的Chubby

基于MySQL的分布式锁

基于Redis的分布式锁

基于Zookeeper的分布式锁

参考文章

文章中的部分内容或者代码直接来源于参考中的文章,感谢他们的分享。本人只是作为个人学习笔记,copy部分自认为写的好的内容,做了实践以及归纳整理。
1.聊聊分布式锁 作者:纯洁的微笑(强哥)
2.分布式锁的几种实现方式 作者:HollisChuang
3.从构建分布式秒杀系统聊聊分布式锁 作者:小柒

点击量:14

发表评论