redis分布式锁总结
基于setnx简单分布式锁
setnx key value expire_time //获取到锁 返回 1 , 获取失败 返回 0
存在问题
1.锁时间不可控
setnx 指定一个锁的超时时间,假设初始设定锁的时间是 10 秒钟,但业务获取到锁跑了 20 秒钟,在 10 秒钟之后,如果又有一个业务可以获取到相同的一把锁,那么久存在两个相同的业务都获取得到锁的问题,并且两个业务处在并行阶段,存在数据冲突,且第一个获取锁的业务无法对自身的锁进行续租。
2.锁释放问题
锁时间不可控,高并发情况下,存在多个线程同时执行,最后释放锁的时候,线程2有可能把线程1的锁说给释放了。
3.主从问题
Redis 的集群实际上在 CAP 模式中是处在与 AP 的模型,保证可用性。在主从复制中“主”有数据,但可能“从”还没有数据。这个时候,一旦主挂掉或者网络抖动等各种原因,可能会切换到“从”节点。
可能导致两个业务线程获取两把锁,没有达到互斥的效果,锁不住,锁失效了。
解决方案
上述的问题其实并不是 Redis 的缺陷,只是 Redis 采用了 AP 模型,它本身无法确保我们对一致性的要求。
Redis 官方推荐 Redlock 算法来保证,问题是 Redlock 至少需要三个 Redis 主从实例来实现,维护成本比较高。
相当于 Redlock 使用三个 Redis 集群实现了自己的另一套一致性算法,比较繁琐,在业界也使用得比较少,另外zk分布式锁可以解决上诉主从问题。
代码层面实现方式基于Redisson开源框架。
总结
1.能不能使用 Redis 作为分布式锁,
这个本身就不是 Redis 的问题,还是取决于业务场景,我们先要自己确认我们的场景是适合 AP 还是 CP。
如果在社交发帖等场景下,我们并没有非常强的事务一致性问题,Redis 提供给我们高性能的 AP 模型是非常适合的。
但如果是交易类型,对数据一致性非常敏感的场景,我们可能要寻找一种更加适合的 CP 模型。
Redis 可能作为高可用的分布式锁并不合适,我们需要确立高可用分布式锁的设计目标。
2.高可用分布式锁设计目标
强一致性,是 CP 模型
服务高可用,不存在单点问题
锁能够续租和自动释放
业务接入简单