github:https://github.com/Linging24/lock.git
分布式锁实现的要求:
1、在分布式环境下,任何时候只能有一个客户端持有锁
2、不会发生死锁
3、自己的客户端加锁,只能由自己解锁
1、基于数据实现
- 创建数据库锁表:
CREATE TABLE `lock_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`lock_name` varchar(50) DEFAULT NULL COMMENT '锁名称',
PRIMARY KEY (`id`),
UNIQUE KEY `lock_name` (`lock_name`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8;
思路:当一个线程进入共享代码时,向数据库插入一条记录,当分布式其他节点线程要访问该共享代码时,会先查询数据库是否存在这样一条锁记录,如果存在则等待锁,否则就获取锁,执行共享代码。
2、基于redis实现
- 使用setnx指令,但是存在如果在上锁之后,如果程序抛出异常,会导致锁永远无法释放,这是可以设置一个超时时间,如果时间到了就会释放锁,但是要保证加锁操作和设置超时时间为原子性操作。
- 由于redis一般为集群部署,第一种方式只适用于单节点的方式,那么集群加锁则使用redission。
注意:为什么第一种方式只适用于单节点redis,如果将它应用在集群下会导致什么问题呢?
集群下,写操作都在主节点,所以加锁都在主节点,如果主节点挂了,那么这时从节点就会抢占锁,而此时如果由于主节点还没宕机前,某些客户端获得了锁,并且在操作资源,而从 从节点获得锁的客户端也在操作资源,就可能存在多个客户端在操作统一资源的情况,这样就锁不住资源了。
实现的七种方式:
https://www.cnblogs.com/wangyingshuo/p/14510524.html
3、基于zookpeer实现