最近项目中需要实时计算一些数据,整体上是一个树的深度搜索过程,但是考虑到有并发请求的可能,同一时间只能允许有一个进行中的计算,防止最终数据的混乱。因此需要使用分布式锁来解决。因此自己总结了一下一些常见的方案,以及自己的实现。
在同一台机器上,我们可以通过多个进程共享某个互斥量等多种多样的方式,大体上是 测试并加锁 的逻辑,来实现对临界区的访问控制。对于分散的机器上的进程,也需要一个共享的协调者,只需要保证加锁和解锁对进程而言是一个原子操作即可。
阐述常见的方案很多地方有写,我简单总结一下。
Redis
单机器
优点:实现简单,使用SetNX+Delete的方式即可。不需要考虑并发安全、数据一致性等问题。
缺点:存在单点问题,而且有单机器的性能瓶颈。具体的性能瓶颈和机器质量、请求复杂度均有关联,需要实际进行压测。
集群
优点:集群版可以是多master,每个master下可以挂slave。提升了性能阙值,同时消除了单点问题。
缺点:redis的实现是最终一致性,如果master宕机,数据同步未完成,则锁记录丢失,会出现多个客户端持有锁的情况。
Etcd和Zookeeper
Etcd和Zookeeper本质是类似的,一些区别比如实现语言、选举算法等,都是一个目录系统。前者源于后者。
优点:抢锁方式都是通过设置临时节点,其中序号最小者获得锁的方式。由于是强一致(即写入操作需同时写入若干副本才算同步成功,才可见)的,所以不会出现上述redis集群版的不一致问题。