Redis分布式锁
1. 使用setNX 命令 + 过期时间 + lua脚本
为什么要使用lua脚本?如果A程序执行过长,该key已经过期,当A执行完可能释放B的锁。图解如下:
lua脚本
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
2.redisson
Mysql作为分布式锁
原理: 利用mysql innodb的行锁。
select * from sync where id = 1 for update
建议:
使用另一个单独的数据库数据表作为锁,避免影响业务表。
Zookeeper作为分布式锁
- Apache curator
- 自定义实现分布式锁
原理:- 利用 exists getData getChildren 三个方法添加观察器。节点数据发生变化,会回调实现了Watch接口的process(),观察器只能监控一次,再次监控需重新设置。
- Zk节点的瞬时有序性,多线程并发创建瞬时节点时会得到有序的序列。
- 序号最小的线程获得锁。
- 其他线程监听自己序号的前一个序号。
- 前一个线程执行完成,删除自己序号的节点。
- 下一个序号的线程得到通知,继续执行。
zk节点类型:持久节点,持久有序,瞬时,瞬时有序,容器节点。