当分布式锁的产生原因:
首先是正确性的需要。对于有依赖关系的调用链,在不加锁的前提下,有可能出现本来应该后来调用的反倒被先调用了(有可能是网络的原因或者io等待等),这就导致了结果的不可预测性。其次是效率问题,使用分布式锁可以避免不同节点重复相同的工作,从而节省了计算的资源。
常见的分布式锁的实现方式:
- Mysql
- Zookeeper
- Redis
如何实现:
- 基于Mysql实现分布式锁: 比较简单的方法是直接创建一张锁表,然后通过操作该表的数据来实现。当我们要锁住某个方法或资源时,在表中插入一条记录,想要释放的时候删掉它。
当我们想要锁住某个方法时,执行以下SQLCREATE TABLE "method_lock" { `id` int(11) NOT NULL AUTO_INCREMENT COMMENT "主键", `method_name` varchar(64) NOT NULL DEFAULT '' COMMENT "方法名", `desc` varchar(1024) NOT NULL DEFAULT '' COMMENT "备注", `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDAET CURRENT_TIMESTAMP COMMENT "保存数据时间,自动生成", PRIMARY KEY (`id`), UNIQUE KEY `uidx_method_name` (`method_name`) USING BTREE } ENGINE=InnoDB DEFAULT CHARSET=utf8
insert into method_lock(method_name, desc) values ('method_name', 'desc');
因为‘method_name’ 列有唯一性的约束,当有多个实例想要获取这个分布式锁的时候,只有一个能够成功,这一点是由数据库来保证的。
当我们想要释放锁的时候,需要执行以下SQLdelete from method_lock where method_name='method_name';
当然,这种简单的实现问题也是很大的,主要有几种:
-
单点故障风险: 这把锁强依赖数据库的可用性,数据库就是一个单点,一旦数据库挂掉,会导致业务系统不能用。
-
锁无失效时间:一旦解锁操作失效,就会导致锁记录一直持久在数据库中,其他的线程无法在获得利用锁了。
-
非阻塞的:
-