常见分布式锁:
- 数据库锁;
- 基于ZooKeeper的分布式锁;
- 基于Redis的分布式锁。
| 方式 | CAP | 锁的颗粒 | 锁竞争 | 区别 |
|---|---|---|---|---|
| db | * | 唯一主键,竞争表级资源或行级资源 | 通过阻塞,或不断重试获取锁 | 方式灵活(1)悲观锁实现:sql可以加上 "FOR UPDATE" 以实现排他锁,并且将“查询”和“更新”打包成一个事务 COMMIT(2)乐观锁实现:表中加上版本号或时间戳字段来控制。 |
| zookeeper | CP | 临时顺序节点,竞争文件资源 | 锁是通过注册监听器,当某个程序释放锁时,下一个程序监听到消息再获取锁 | 性能消耗小,锁释放机制完善,集群的强一致性 |
| redis | AP | setnx setex,竞争键值 | 通过阻塞,或不断重试获取锁 | 本身效率高且单进程的特点,即使在高并发的情况下也能很好的保证性能 |
Redis 部署模式
| 主从复制-备份 | 哨兵机制-高可用 | cluster-高并发 |
|---|---|---|
| 不能自动故障恢复 | 不能解决负载均衡的问题。 | 解决负载均衡的问题 |
| 备份数据、负载均衡(读写分离),一个Master可以有多个Slaves | sentinel发现master挂了后,就会从slave中重新选举一个master | 分片/槽算法,把请求尽量平均的负载均衡到各个机器 |
用Redis作为分布式锁,很大程度上是因为Redis本身效率高且单进程的特点,即使在高并发的情况下也能很好的保证性能,但很多时候,性能和安全不能完全兼顾,如果你一定要保证锁的安全性的话,可以用其他的中间件如db、zookeeper来做控制,这些工具能很好的保证锁的安全,但性能方面只能说是差强人意。一般来说,用Redis控制共享资源并且还要求数据安全要求较高的话,最终的保底方案是对业务数据做幂等控制,即使出现多个客户端获得锁的情况也不会影响数据的一致性。根据场景选择合适的才是最好的。
参考: