一:Redis实现分布式锁
-
1:Redis方式一,自己利用API实现,单机模式:
加锁:多参数的jedis.set(String lock, String requestId, String NX, String expx, int time);
解锁:Lua脚本代码,原子特性 -
2:Redis方式二,自己利用API实现,Master+Slave+Sentinel 选举模式模式:
为了防止单机故障,可以利用Master-Slave主从同步方式 -
3:Redis集群
在Master-Slave 模式中,如果 Master 节点故障了,发生主从切换,此时就会有可能出现锁丢失的问题。Redis的作者也考虑到这个问题,他提出了一个 RedLock的算法。这个算法的意思大概是这样的:假设 Redis的部署模式是Redis Cluster,总共有奇数台,比如5个Master节点。
通过以下步骤获取一把锁:获取当前时间戳,单位是毫秒。
轮流尝试在每个 Master 节点上创建锁,过期时间设置较短,一般就几十毫秒。
尝试在大多数节点上建立一个锁,比如 5 个节点就要求是 3 个节点(n / 2 +1)。
客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了。
要是锁建立失败了,那么就依次删除这个锁。
只要别人建立了一把分布式锁,你就得不断轮询去尝试获取锁。
-
4:利用Redisson框架
此外,实现 Redis 的分布式锁,除了自己基于 Redis Client 原生 API 来实现之外,还可以使用开源框架:Redission.它支持集群,RedLock,使用起来很方便.
二:Zookeeper实现分布式锁
- 1:利用临时有序节点
- 2:Curator
Curator 是一个 ZK 的开源客户端,也提供了分布式锁的实现。它的使用方式也比较简单
三:对比与选择
1:对于 Redis 的分布式锁而言,它有以下优缺点:
- 优点:Redis的数据并不是强一致性的,在某些极端情况下,可能会出现问题。即便使用Redlock算法来实现,在某些复杂场景下,也无法保证其实现 100% 没有问题,关于 Redlock 的讨论可以看 How to do distributed locking。
- 缺点:但是另一方面Redis 的性能很高,可以支撑高并发的获取、释放锁操作。
2:对于 Zookeeper的分布式锁而言,它有以下优缺点:
- 优点:ZK 天生设计定位就是分布式协调,强一致性。锁的模型健壮、简单易用、适合做分布式锁。如果获取不到锁,只需要添加一个监听器就可以了,不用一直轮询,性能消耗较小。
- 缺点:但是 ZK 也有其缺点:如果有较多的客户端频繁的申请加锁、释放锁,对于 ZK 集群的压力会比较大。
3:到底如何选择呢?
- 推崇 ZK 实现的锁:因为ZK更稳定, Redis 是有可能存在隐患的,可能会导致数据不对的情况。但是,如果公司里面有 ZK 集群条件,优先选用 ZK 实现,但是如果说公司里面只有 Redis 集群,没有条件搭建 ZK 集群,那么其实用 Redis 来实现也可以。而且两者都会客户端工具直接拿来用。