分布式锁
Redis
- 使用
set key value [NX|XX] [GET] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL],同时设置一个过期时间, 如果服务中途宕机,有过期时间就可以避免死锁 - 对于一个耗时任务, 如果服务还没有结束,锁提前失效, 会导致服务异常。 启动一个子线程,在任务完成之前, 每隔一段时间续签
- 当服务结束的时候
del key删除键
对于上述流程,可以使用redisson第三方库实现
优点:方便部署,大部分项目本身就需要redis,不需要额外的第三方组件
缺点:如果没抢到锁,会直接返回,也就相当于tryLock()。 只能通过自旋来实现阻塞抢锁, 实时性上不太好
Etcd
etcd实现分布式锁与redis大有不同, etcd通过回调的方式,避免了不必要的自旋
- 客户端指定一个键前缀, 每次监听一个最接近且比自己小的键, 同一个前缀的键, 被视为同一把锁, 可以理解成 key = {prefix}_ {id}
- 如果这个键是自己, 或者根本就没这个键, 那就相当于抢到锁了
- 如果不是自己, 那么陷入阻塞, 当这个键被删除的时候, 唤醒线程
- 唤醒的时候判断一下, 是否还有其他比自己小的, 如果没有, 检查一下租约是否到期, 如果没有异常则说明自己抢到锁了, 继续走业务逻辑
- 如果还有更小的, 说明这个键是客户端不想等待, 手动删除的, 或者其他情况, 则再次循环以上逻辑
以上功能官方已经实现, 不需要手动编码, 同时支持TryLock和Lock方法
优点:etcd很轻量, 部署容易
缺点:有额外学习成本(但是不难)
Consul
Zookeeper
太臃肿, 不必要