分布式锁的这三种实现90%的人都不知道( 二 )


方案2
表结构
DROP TABLE IF EXISTS `method_lock`;
CREATE TABLE `method_lock` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`method_name` varchar(64) NOT NULL COMMENT '锁定的方法名',
`state` tinyint NOT NULL COMMENT '1:未分配;2:已分配',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`version` int NOT NULL COMMENT '版本号',
`PRIMARY KEY (`id`),
UNIQUE KEY `uidx_method_name` (`method_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='锁定中的方法';
先获取锁的信息
select id, method_name, state,version from method_lock where state=1 and method_name='methodName';
占有锁
update t_resoure set state=2, version=2, update_time=now() where method_name='methodName' and state=1 and version=2;
如果没有更新影响到一行数据 , 则说明这个资源已经被别人占位了 。
缺点:
1、这把锁强依赖数据库的可用性 , 数据库是一个单点 , 一旦数据库挂掉 , 会导致业务系统不可用 。
2、这把锁没有失效时间 , 一旦解锁操作失败 , 就会导致锁记录一直在数据库中 , 其他线程无法再获得到锁 。
3、这把锁只能是非阻塞的 , 因为数据的insert操作 , 一旦插入失败就会直接报错 。 没有获得锁的线程并不会进入排队队列 , 要想再次获得锁就要再次触发获得锁操作 。
4、这把锁是非重入的 , 同一个线程在没有释放锁之前无法再次获得该锁 。 因为数据中数据已经存在了 。
解决方案:
1、数据库是单点?搞两个数据库 , 数据之前双向同步 。 一旦挂掉快速切换到备库上 。
2、没有失效时间?只要做一个定时任务 , 每隔一定时间把数据库中的超时数据清理一遍 。
【分布式锁的这三种实现90%的人都不知道】 3、非阻塞的?搞一个while循环 , 直到insert成功再返回成功 。
4、非重入的?在数据库表中加个字段 , 记录当前获得锁的机器的主机信息和线程信息 , 那么下次再获取锁的时候先查询数据库 , 如果当前机器的主机信息和线程信息在数据库可以查到的话 , 直接把锁分配给他就可以了 。
2.基于redis实现获取锁使用命令:
SET resource_name my_random_value NX PX 30000
方案:
try{
lock = redisTemplate.opsForValue().setIfAbsent(lockKey, LOCK);
logger.info("cancelCouponCode是否获取到锁:"+lock);
if (lock) {
// TODO
redisTemplate.expire(lockKey,1, TimeUnit.MINUTES); //成功设置过期时间
return res;
}else {
logger.info("cancelCouponCode没有获取到锁 , 不执行任务!");
}
} finally{
if(lock){
redisTemplate.delete(lockKey);
logger.info("cancelCouponCode任务结束 , 释放锁!");
}else{
logger.info("cancelCouponCode没有获取到锁 , 无需释放锁!");
}
}
缺点:
在这种场景(主从结构)中存在明显的竞态:
客户端A从master获取到锁 ,
在master将锁同步到slave之前 , master宕掉了 。
slave节点被晋级为master节点 ,
客户端B取得了同一个资源被客户端A已经获取到的另外一个锁 。 安全失效!
3.基于zookeeper实现 让我们来回顾一下Zookeeper节点的概念:
分布式锁的这三种实现90%的人都不知道文章插图
Zookeeper的数据存储结构就像一棵树 , 这棵树由节点组成 , 这种节点叫做Znode 。


推荐阅读