分布式锁是为了解决分布式服务节点间对共享资源的读写问题而产生的。
分布式锁实现方式有几种?各有哪些优缺点?
1)数据库 mysql innodb (行锁)
创建表结构
create table if not exists dis_table_lock (
`id` int primary key ,
`resname` varchar(10) ,
`locker` varchar(20),
`counter` int,
`create_time` bigint(20),
`update_time` bigint(20),
unique key(resname))
ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 上锁流程
首先执行下面的SQL 去查询是否资源A已经被加锁了,
select * from dis_lock_table where resname='A' for update
a. 如果已加锁,检查locker是否是当前服务器(IP+Port+ThreadId?)
a1. 如果是,增加可重入counter 计数;
update dis_lock_table set counter = counter+1 where resource_name = 'A';
a2. 如果不是,等待,然
update dis_lock_table set counter=counter-1 where resname='A'
后过一段时间继续尝试获取锁
b. 如果未加锁,执行insert 语句插入一条数据:
insert into dis_lock_table(resname,locker,counter) value('A','ip:port:threadid',1);
- 解锁流程
检查数据库是否存在resname='A'的记录,
select * from dis_lock_table where resname = 'A' for update;
a. 如果有,判断可重入计数器的值是否大于1:
a1. 大于1: 执行下面SQL 扣减1:
update dis_lock_table set counter=counter-1 where resname='A'
a2. 等于1,删除lock记录:
delete from dis_lock_table where resname = 'A'
优势:借助SQL 就可以实现
劣势: 锁的超时需要手动管理;性能差,当并发量大的时候频繁操作数据库带来损耗。
2)Redis setnx (set if not exists)
a. Redis 2.8 以前,lua 脚本:
setnx reskey 1
expire reskey 20
b. Redis 2.8 以后:
set reskey 1 ex 20 nx
3) zookeeper
基于zk的临时顺序Node,zk 很适合做分布式锁
4)Redisson
参考:
https://juejin.cn/post/6844903688088059912
https://www.cnblogs.com/lins1/p/15239045.html
https://blog.csdn.net/fygkchina/article/details/126596157
浙公网安备 33010602011771号