CN112667409A - 一种可重入的分布式排它锁实现方法 - Google Patents
一种可重入的分布式排它锁实现方法 Download PDFInfo
- Publication number
- CN112667409A CN112667409A CN202011337950.5A CN202011337950A CN112667409A CN 112667409 A CN112667409 A CN 112667409A CN 202011337950 A CN202011337950 A CN 202011337950A CN 112667409 A CN112667409 A CN 112667409A
- Authority
- CN
- China
- Prior art keywords
- lock
- node
- thread
- temporary
- acquired
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Landscapes
- Information Retrieval, Db Structures And Fs Structures Therefor (AREA)
Abstract
本发明提供了一种可重入的分布式排它锁实现方法,包括:定义锁;通过zookeeper定义锁,将zookeeper上的其中一个数据节点定义为一个锁;获取锁:获取排他锁时,客户端首先判断是否存在数据节点,如果不存在,则创建,并且在该锁节点下创建带有线程id和lock标识的有序临时节点;如果存在,则直接在该锁节点下创建有序临时节点;然后各个客户端判断本线程创建的临时节点的序列号是否是最小的,如果是最小的则获取锁,如果不是则需要进一步判断是否本线程占用的锁,如果是,则可以获取锁,如果不是则等待锁。本发明所述的可重入的分布式排它锁实现方法,具有可重入性,保证互斥锁的可重入性。
Description
技术领域
本发明属于互联网技术领域,尤其是涉及一种可重入的分布式排它锁实现方法。
背景技术
在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。然而在很多场景中,我们需要保证一个方法在同一时间内只能被同一个线程执行,这就需要用到分布式锁。分布式锁是控制分布式系统之间同步访问共享资源的一种方式,如果不同的系统或者同一个系统的不同的主机或服务之间共享一个或一组资源,那么访问这些资源的时候,往往需要通过一些互斥手段来防止彼此之间的干扰,以保证一致性,这种情况下就需要使用分布式锁。
针对分布式锁的实现,目前比较常用的有以下几种方案:基于数据库实现分布式锁;基于缓存redis实现分布式锁;基于Zookeeper实现分布式锁。
基于数据库实现分布式锁缺点:
1、这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。
2、这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
3、这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
4、这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。
基于缓存redis实现分布式锁缺点:
如果Redis是主从架构,客户端A从master获取到锁,在master将锁同步到slave之前,master宕掉了。此时slave节点被晋级为master节点,客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。
基于Zookeeper实现分布式锁缺点:
现有基于Zookeeper分布式锁没有可重入性。
发明内容
有鉴于此,为克服上述缺陷,本发明旨在提出一种可重入的分布式排它锁实现方法。
为达到上述目的,本发明的技术方案是这样实现的:
本发明提供了一种可重入的分布式排它锁实现方法,包括:
定义锁;通过zookeeper定义锁,将zookeeper上的其中一个数据节点定义为一个锁;
获取锁:获取排他锁时,客户端首先判断是否存在数据节点,如果不存在,则创建,并且在该锁节点下创建带有线程id和lock标识的有序临时节点;如果存在,则直接在该锁节点下创建有序临时节点;然后各个客户端判断本线程创建的临时节点的序列号是否是最小的,如果是最小的则获取锁,如果不是则需要进一步判断是否本线程占用的锁,如果是,则可以获取锁,如果不是则等待锁。
进一步的,获取锁的具体方法如下:
S1、首先判断是否有数据节点,如果没有则创建,如果有则需要进一步判断;
S2、创建节点的时候如果创建成功,为了避免另外的线程已经获取锁,仍然需要判断是否有更小序号的临时节点;
S3、如果创建节点没有创建成功,说明可能有线程已经获取了锁,这时候需要再次判断是否存在数据节点;
S4、为了保证锁是公平性,每个客户端尝试获取锁的时候就在锁对应的数据节点下面创建一个有序的临时节点,获取锁的时候根据临时节点的序号从小到大逐一获取。
S5、判断是否有序号更小的节点时,如果没有则直接占用锁;如果有,判断序号最小的临时节点是否是本线程的,如果是则说明可以占用该锁,如果不是则需要等待小于本线程序号的所有临时节点都删除了,才获取锁;
S6、每个线程获取锁的时候创建有序号的临时节点,向临时节点里存入数据count=0;当本线程再次获取该锁的时候,需要给临时节点里面的count=count++,创建临时数据节点的时候带有线程生成的唯一id,可根据这个id判断是否属于同一个线程;
S7、线程释放锁的时候会删除数据节点下的该线程对应的所有临时节点;
S8、线程获取锁时,发现有序号小于本线程序号的临时节点,注册Watcher监听,以便实时监听到数据节点的变更情况;
S9、注册Watcher监听,当获取到消息本线程的其他临时节点获取到锁,则本线程所有临时节点都需要修改count=count++,并且可以获取锁;
S10、如果修改count=count++,成功则说明可获取该锁,如果修改失败,说明该锁已经被其他线程占用,需要再次等待锁。
进一步的,所述步骤S3中,创建节点时,如果创建多次依然没创建成功,这里需要设置停止策略,以免进入死循环。
进一步的,所述步骤S6中,所述的唯一id为采用雪花算法生成分布式全局唯一id。
进一步的,所述步骤S8中,在/character_root/lock上注册监听器,监听器的工作过程如下:
当数据节点/character_root/lock下有临时节点删除的时候,会通知监听者,然后监听者判断是否还有小于本线程序号的临时节点,如果没有则获取锁,如果有则继续监听等待。
相对于现有技术,本发明所述的可重入的分布式排它锁实现方法具有以下优势:
本发明所述的可重入的分布式排它锁实现方法具有:可重入性,保证互斥锁的可重入性;Zookeeper是一个高可用的分布式数据管理与协调框架,不需要额外考虑zookeeper集群的主从同步问题;可以自定义失效时间、自旋次数、保证获取锁的公平性等高级特性的设置。
附图说明
构成本发明的一部分的附图用来提供对本发明的进一步理解,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
图1为锁定义示意图;
图2为获取锁示意图。
具体实施方式
需要说明的是,在不冲突的情况下,本发明中的实施例及实施例中的特征可以相互组合。
下面将参考附图并结合实施例来详细说明本发明。
本实施例提供了一种可重入的分布式排它锁实现方法,概念介绍:
排它锁:
又称写锁或独占锁,是一种基本的锁类型。如果事务T1对数据对象Q1加上排它锁,那么在整个加锁期间,只允许事务T1对Q1进行读取和更新操作,其他任何事务都不能再对这个数据进行任何类型的操作,直到T1释放了排它锁。该特性也称为锁的排他性。
公平锁:
每个线程抢占锁的顺序为先后调用lock方法的顺序依次获取锁,类似于排队吃饭。该特性也称为锁的公平性。
非公平锁:
每个线程抢占锁的顺序不定,谁运气好,谁就获取到锁,和调用lock方法的先后顺序无关。
可重入锁:
在同一线程中,外层函数获取了锁之后,内层函数依然可以获得相同的锁。该特性也称为锁的可重入性。
方法介绍:
本方法通过zookeeper定义锁,通过zookeeper上的数据节点表示一个锁,例如/character_root/lock/lock001节点就可以被定义为一个锁,如图1所示:
说明1:表示锁的数据节点是持久化节点,非临时节点
说明2:/character_root/lock是数据节点前缀,每个锁可以自定义锁名字放在前缀后面使用,例如/character_root/lock/abc_lock,如图2所示。
在需要获取排他锁的时候,客户端首先判断是否存在/character_root/lock/lock001数据节点。如果不存在,则创建,并且在该锁节点下创建带有线程id和lock标识的有序临时节点;如果存在,则直接在该锁节点下创建有序临时节点。
然后各个客户端判断本线程创建的临时节点的序列号是否是最小的,如果是最小的则获取锁,如果不是则需要进一步判断是否本线程占用的锁,如果是,则可以获取锁,如果不是则等待锁。
说明1:首先判断是否有数据节点,如果没有则创建,如果有则需要进一步判断。
说明2:创建节点的时候如果创建成功,为了避免另外的线程已经获取锁,仍然需要判断是否有更小序号的临时节点。
说明3:如果创建节点没有创建成功,说明可能有线程已经获取了锁,这时候需要再次判断是否存在数据节点。如果创建多次依然没创建成功,这里需要设置停止策略,以免进入死循环。例如:一个线程创建数据节点超过3次依然没有创建成功,就抛出异常人工处理。
说明4:为了保证锁是公平性,每个客户端尝试获取锁的时候就在锁对应的数据节点下面创建一个有序的临时节点。获取锁的时候根据临时节点的序号从小到大逐一获取。
说明5:判断是否有序号更小的节点时,如果没有则直接占用锁;如果有,判断序号最小的临时节点是否是本线程的,如果是则说明可以占用该锁,如果不是则需要等待小于本线程序号的所有临时节点都删除了,才获取锁。
说明6:每个线程获取锁的时候创建有序号的临时节点,向临时节点里存入数据count=0;当本线程再次获取该锁的时候,需要给临时节点里面的count=count++。创建临时数据节点的时候带有线程生成的唯一id,可以根据这个id判断是否属于同一个线程。这里唯一id生成的方法采用雪花算法生成分布式全局唯一id。以此来保证了锁的可重入性。
说明7:线程释放锁的时候会删除数据节点下的该线程对应的所有临时节点。
说明8:线程获取锁时,发现有序号小于本线程序号的临时节点,在/character_root/lock上注册一个Watcher监听,以便实时监听到lock节点的变更情况。当数据节点/character_root/lock下有临时节点删除的时候,会通知监听者,然后监听者判断是否还有小于本线程序号的临时节点,如果没有则获取锁,如果有则继续监听等待。
说明9:注册Watcher监听,当获取到消息本线程的其他临时节点获取到锁,则本线程所有临时节点都需要修改count=count++,并且可以获取锁。
说明10:如果修改count=count++,成功则说明可以获取该锁,如果修改失败,可能说明该锁已经被其他线程占用,需要再次等待锁。
占用锁与释放锁:
当线程成功占用锁之后,有两种情况需要释放锁,以免造成死锁:
1、当前获取锁的客户端机器宕机,那么zookeeper上的该客户端的临时节点就会被移除。
2、正常执行完业务逻辑后,客户端需要主动将自己临时节点下的count--,然后通知该线程下所有临时节点都需要执行count--。当线程对应的临时节点中count=0的时候,则删除线程对应的所有临时节点。
当有临时节点被删除的时候,zookeeper会通知所有在/character_root/lock上注册了子节点变更Watcher监听的客户端。这些客户端接收到通知后,再次发起分布式锁获取的过程。不局限于上述实施例,本发明的技术方案即创建了“创建子页面,关联,解析器,渲染”的机制。从某个角度也可以认为是建模的过程,类似的也可以通过多组件合并成组的方式实现解决场景问题。可以解决请求合并问题,但是对于轮播自定义、弹窗页定义的问题并不能解决。替代方案局限性较差,而本发明可以同时解决多种应用场景问题,一举多得,所以暂无可替代方案。
最后应说明的是:以上各实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述各实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分或者全部技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的范围,其均应涵盖在本发明的权利要求和说明书的范围当中。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。
Claims (5)
1.一种可重入的分布式排它锁实现方法,其特征在于,包括:
定义锁;通过zookeeper定义锁,将zookeeper上的其中一个数据节点定义为一个锁;
获取锁:获取排他锁时,客户端首先判断是否存在数据节点,如果不存在,则创建,并且在该锁节点下创建带有线程id和lock标识的有序临时节点;如果存在,则直接在该锁节点下创建有序临时节点;然后各个客户端判断本线程创建的临时节点的序列号是否是最小的,如果是最小的则获取锁,如果不是则需要进一步判断是否本线程占用的锁,如果是,则可以获取锁,如果不是则等待锁。
2.根据权利要求1所述的可重入的分布式排它锁实现方法,其特征在于,获取锁的具体方法如下:
S1、首先判断是否有数据节点,如果没有则创建,如果有则需要进一步判断;
S2、创建节点的时候如果创建成功,为了避免另外的线程已经获取锁,仍然需要判断是否有更小序号的临时节点;
S3、如果创建节点没有创建成功,说明可能有线程已经获取了锁,这时候需要再次判断是否存在数据节点;
S4、为了保证锁是公平性,每个客户端尝试获取锁的时候就在锁对应的数据节点下面创建一个有序的临时节点,获取锁的时候根据临时节点的序号从小到大逐一获取。
S5、判断是否有序号更小的节点时,如果没有则直接占用锁;如果有,判断序号最小的临时节点是否是本线程的,如果是则说明可以占用该锁,如果不是则需要等待小于本线程序号的所有临时节点都删除了,才获取锁;
S6、每个线程获取锁的时候创建有序号的临时节点,向临时节点里存入数据count=0;当本线程再次获取该锁的时候,需要给临时节点里面的count=count++,创建临时数据节点的时候带有线程生成的唯一id,可根据这个id判断是否属于同一个线程;
S7、线程释放锁的时候会删除数据节点下的该线程对应的所有临时节点;
S8、线程获取锁时,发现有序号小于本线程序号的临时节点,注册Watcher监听,以便实时监听到数据节点的变更情况;
S9、注册Watcher监听,当获取到消息本线程的其他临时节点获取到锁,则本线程所有临时节点都需要修改count=count++,并且可以获取锁;
S10、如果修改count=count++,成功则说明可获取该锁,如果修改失败,说明该锁已经被其他线程占用,需要再次等待锁。
3.根据权利要求2所述的可重入的分布式排它锁实现方法,其特征在于:所述步骤S3中,创建节点时,如果创建多次依然没创建成功,这里需要设置停止策略,以免进入死循环。
4.根据权利要求2所述的可重入的分布式排它锁实现方法,其特征在于:所述步骤S6中,所述的唯一id为采用雪花算法生成分布式全局唯一id。
5.根据权利要求2所述的可重入的分布式排它锁实现方法,其特征在于:所述步骤S8中,在/character_root/lock上注册监听器,监听器的工作过程如下:
当数据节点/character_root/lock下有临时节点删除的时候,会通知监听者,然后监听者判断是否还有小于本线程序号的临时节点,如果没有则获取锁,如果有则继续监听等待。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202011337950.5A CN112667409A (zh) | 2020-11-25 | 2020-11-25 | 一种可重入的分布式排它锁实现方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202011337950.5A CN112667409A (zh) | 2020-11-25 | 2020-11-25 | 一种可重入的分布式排它锁实现方法 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN112667409A true CN112667409A (zh) | 2021-04-16 |
Family
ID=75402916
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202011337950.5A Pending CN112667409A (zh) | 2020-11-25 | 2020-11-25 | 一种可重入的分布式排它锁实现方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN112667409A (zh) |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN114661742A (zh) * | 2022-03-28 | 2022-06-24 | 浪潮卓数大数据产业发展有限公司 | 基于Zookeeper的分布式锁的获取方法及系统 |
CN115578099A (zh) * | 2022-12-09 | 2023-01-06 | 浙江保融科技股份有限公司 | 一种基于外汇牌价阻塞的预处理方法 |
Citations (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN105340241A (zh) * | 2013-11-27 | 2016-02-17 | 华为技术有限公司 | 用于均衡在sdn网络中的负载的方法和系统 |
CN108038005A (zh) * | 2017-12-28 | 2018-05-15 | 广东蜂助手网络技术股份有限公司 | 基于zookeeper的共享资源访问方法、客户端、服务端、系统 |
CN109582678A (zh) * | 2018-12-03 | 2019-04-05 | 东北大学 | 基于叶子节点的多粒度分布式读写锁的r树索引优化方法 |
-
2020
- 2020-11-25 CN CN202011337950.5A patent/CN112667409A/zh active Pending
Patent Citations (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN105340241A (zh) * | 2013-11-27 | 2016-02-17 | 华为技术有限公司 | 用于均衡在sdn网络中的负载的方法和系统 |
CN108038005A (zh) * | 2017-12-28 | 2018-05-15 | 广东蜂助手网络技术股份有限公司 | 基于zookeeper的共享资源访问方法、客户端、服务端、系统 |
CN109582678A (zh) * | 2018-12-03 | 2019-04-05 | 东北大学 | 基于叶子节点的多粒度分布式读写锁的r树索引优化方法 |
Non-Patent Citations (1)
Title |
---|
黄毅斐: "基于Zookeeper的分布式同步框架设计与实现", 《中国优秀硕士学位论文全文数据库 信息科技辑》 * |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN114661742A (zh) * | 2022-03-28 | 2022-06-24 | 浪潮卓数大数据产业发展有限公司 | 基于Zookeeper的分布式锁的获取方法及系统 |
CN115578099A (zh) * | 2022-12-09 | 2023-01-06 | 浙江保融科技股份有限公司 | 一种基于外汇牌价阻塞的预处理方法 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
JP2566717B2 (ja) | 条件付きオペレーション提供装置及び方法 | |
US8930584B2 (en) | System and method for providing a linearizable request manager | |
CN110287206B (zh) | 构建用于Redis数据库的分布式锁的方法 | |
CN109753364A (zh) | 一种基于网络的分布式锁的实现方法、设备及介质 | |
CN112835722B (zh) | 业务处理方法、电子设备及计算机可读存储介质 | |
JP2004529431A (ja) | 準備処理を取り入れたクラスタード・コンピュータ・システムにおけるリソース・アクション | |
US9460143B2 (en) | Methods, systems, and computer readable media for a multi-view data construct for lock-free operations and direct access | |
CN112099962B (zh) | 分布式锁实现方法、装置和电子设备 | |
CN112667409A (zh) | 一种可重入的分布式排它锁实现方法 | |
US8600933B2 (en) | Multi-master attribute uniqueness | |
US20040128385A1 (en) | Method and apparatus for managing resource contention in a multisystem cluster | |
US6523078B1 (en) | Distributed locking system and method for a clustered system having a distributed system for storing cluster configuration information | |
US8996484B2 (en) | Recursive lock-and-propagate operation | |
WO1997007621A1 (en) | Parallel execution of requests in osi agents | |
CN102025728A (zh) | 客户端/服务端架构下的调度方法和服务器 | |
US7028219B2 (en) | Hybrid method for flushing transaction state in a fault-tolerant clustered database | |
CN110430258B (zh) | 一种分布式锁管理方法和装置 | |
CN108446167B (zh) | 一种分布式事务处理方法及系统 | |
CN112100190B (zh) | 一种基于更新序列的分布式锁状态同步方法 | |
CN111625323A (zh) | 分布式任务处理方法、装置、设备及计算机可读存储介质 | |
CN108846633A (zh) | 一种智能高效的卡任务处理方法 | |
CN117608766B (zh) | 分布式锁处理方法、设备、存储介质和系统 | |
Böttcher et al. | Reducing sub-transaction aborts and blocking time within atomic commit protocols | |
US7526543B2 (en) | Method of synchronizing execution of state transition commands in a cluster of message oriented middleware servers | |
CN111400324B (zh) | 一种锁定云存储中对象的方法、装置及服务器 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
RJ01 | Rejection of invention patent application after publication | ||
RJ01 | Rejection of invention patent application after publication |
Application publication date: 20210416 |