分布式锁是指分布式环境下,系统部署在多个机器中,实现多进程分布式互斥的一种锁。实现分布式锁有三种主流方式,接下来一一盘点。
数据库实现的锁表完全不推荐。
Redis分布式锁性能优于ZooKeeper,因为不需要反复创建节点。
实现的简单程度和可靠性ZooKeeper更好,因为其封装好的框架几乎能应对所有的分布式锁问题。
实际上就是开一个表。当我们要锁住某个资源时,就在该表中增加一条记录,想要释放锁的时候就删除这条记录。但数据库表要磁盘io,所以效率很低。并且一旦这个数据库寄了,那系统崩了。数据库锁没有失效时间,未获得锁的进程只能一直等待已获得锁的进程主动释放锁。倘若已获得共享资源访问权限的进程突然挂掉、或者解锁操作失败,使得锁记录一直存在数据库中,无法被删除,而其他进程也无法获得锁,从而产生死锁现象。
就是说把数据存放在计算机内存中,不需要写入磁盘,减少了IO读写,实现时候是维护一个队列来维持进程访问共享资源的顺序的。
Redis的setnx和delete方法就支持这一方式。
也存在缺陷,因为进程没法主动释放锁,假设ABC三个进程来,A完事了到B,B进程对应的服务器坏了,那C就得等B超时自动释放才能访问共享资源。通过超时时间来控制锁的失效时间,并不是十分靠谱,因为一个进程执行时间可能比较长,或受系统进程做内存回收等影响,导致时间超时,从而不正确地释放了锁。
ZooKeeper基于树形数据存储结构实现分布式锁,ZooKeeper的树形数据存储结构主要由4种节点构成:
ZooKeeper是根据临时顺序节点来实现的分布式锁。以电商售卖吹风机的场景为例。假设用户A、B、C同时在11月11日的零点整提交了购买吹风机的请求,ZooKeeper会为每个进程分配一个临时顺序节点。每个节点都有一个监听器监听当前自己是不是序号最小的**(理论上要监听共享资源上的所有节点,实际上只要监听自己上一个节点的状态就行)**,是就去访问共享资源,不是就判断: