Redis分布式锁
# Redis分布式锁
一文彻底弄清楚分布式锁 (opens new window)
# 1 Redis分布式锁
原理:多个服务,同一时刻内请求同一个共享资源,为防止关键业务出现数据冲突和并发错误,需要加分布式锁。
实现:set <key> <value> [EX seconds] [PX milliseconds] [NX|XX]
,如果key不存在就设置键值对并带有过期时间,如果存在就设置失败。
注意点:
- 设置Key的同时要设置过期时间,防止服务突然宕机,后续锁无法释放。设置key和过期时间的过程要保证原子性。
- 如果业务A执行的时间太长,锁已经过期了,此时其他线程获取了锁。当业务A执行完毕,此时将释放其他线程的锁,这将导致一系列问题。所以在释放锁的时候要通过Value判断是不是自己加的锁。(所以,value的选择要唯一,保证每一个服务线程的值是唯一的)
- 需要保证判断”是不是自己的锁“和”释放锁“的过程是原子性的,最常用的方法是写LUA脚本,也可以通过Redis的事务实现。
其他高级问题:
- 缓存续命:当分布式锁快要到期,业务还没有执行完的时候,需要给锁续命。
- Redis集群可能出现的问题,异步复制会造成锁丢失:主节点刚刚告诉线程加锁成功,还没来得及把这个数据复制给从节点就挂了。
# 2 Redis和Zookeeper分布式锁的区别
单机下:
- redis 分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能。
- zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。
如果是 Redis 获取锁的那个客户端出现 bug 挂了,那么只能等待超时时间之后才能释放锁;而 zk 的话,因为创建的是临时 znode,只要客户端挂了,znode 就没了,此时就自动释放锁。
集群下:
- redis 集群保证了 AP:先通知线程加锁成功,再将数据复制给从节点。
- zk 集群保证了 CP:先将数据复制给从节点,全部复制完毕后再告诉线程加锁成功,虽然安全,但效率低。
# 3 Redission
RedLock的实现,用于实现分布式锁,可以方便解决分布式锁的各类问题。
使用多个 Redis 节点,每个 Redis 节点都是独立的、不同的。想要加锁成功就必须获得超过一半以上的节点。
编辑 (opens new window)
上次更新: 2024/04/26, 20:23:02