写在前面

本文隶属于专栏《100个问题搞定大数据理论体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和文献引用请见100个问题搞定大数据理论体系

解答

在分布式环境下,为了保证数据的一致性,需要利用分布式锁技术来保证同一时刻只有固定数量的进程对数据进行修改:只有获取锁的客户端才能对数据进行修改,其余客户端只能暂时等待。

实现方式:
1.数据库的唯一索引
2.Redis的SETNX指令
3.Redis的RedLock算法
4.ZooKeeper的临时顺序节点

在这里插入图片描述

补充

阻塞锁通常使用互斥量来实现:
互斥量为0表示有其它进程在使用锁,此时处于锁定状态互斥量为1表示未锁定状态。
1和0可以用一个整型值表示,也可以用某个数据是否存在表示。

数据库的唯一索引

获得锁时向表中插入一条记录,释放锁时删除这条记录。
唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否处于锁定状态。

存在以下几个问题

  1. 锁没有失效时间,解锁失败的话其它进程无法再获得该锁;
  2. 只能是非阻塞锁,插入失败直接就报错了,无法重试;
  3. 不可重入,已经获得锁的进程也必须重新获取锁。

Redis的SETNX指令

  1. 使用SETNX(set if not exist)指令插入一个键值对,如果Key已经存在,那么会返回False,否则插入成功并返回True。
  2. SETNX指令和数据库的唯一索引类似,保证了只存在一个Key的键值对,那么可以用一个Key的键值对是否存在来判断是否存于锁定状态。
  3. EXPIRE指令可以为一个键值对设置一个过期时间,从而避免了数据库唯一索引实现方式中释放锁失败的问题。

Redis的RedLock算法

  1. 使用了多个 Redis实例来实现分布式锁,这是为了保证在发生单点故障时仍然可用尝试从N个互相独立 Redis实例获取锁;
  2. 计算获取锁消耗的时间,只有时间小于锁的过期时间,并且从大多数(N/2+1)实例上获取了锁,才认为获取锁成功
  3. 如果获取锁失败,就到每个实例上释放锁。

ZooKeeper的临时顺序节点

详情可以参考我的这篇博客——如何用 ZooKeeper 实现分布式锁?

上一篇 下一篇