分布式锁
程序员文章站
2022-07-05 11:50:50
...
-
数据库实现分布式锁
1.1 利用主键唯一规则:
数据库的唯一主键,不能重复。利用主键唯一规则,在争抢锁的时候向数据库中写一条记录,记录包括锁的id、当前占用锁的线程名、重入的次数和创建时间等信息。如果插入成功表示当前线程获取到了锁,如果插入失败证明锁被其他人占用,等待一回儿继续重试,直到抢到锁或者超时为止。-
获取锁
public Boolean lock(String lockId) { int count = 0; //重试4次 while(count < 4) { try{ "insert into lock(id, count, lockName, addTime)"; if(插入成功) { //获得锁 return true; } } catch(Exception e) { } Thread.sleep(1000); count++; } }
-
释放锁
public Boolean release(String lockId) { "delete from lock where id = lockId"; if (删除成功) { return true; } return false; }
1.2 利用MySql行锁的特性:
-
获取锁
public void lock() { connection.setAutoCommit(false); int count = 0; while(count < 4) { try{ //通过for update 操作,数据库就会对该行记录加上record lock,从而阻塞其他人对该记录的操作 select * from lock where lock_name = xxx for update; if(not null) { return ture; } } catch (Exception e) { } //没有获得锁 sleep(1000); count++; } throw new LockException(); }
-
释放锁
public void release() { connection.commit(); }
缺点:
性能不高,SQL超时异常 -
-
缓存实现分布式锁
使用Redis的setNX来实现分布式锁(如果指定的key存在,setNX失败;否则执行Set操作并返回成功)-
获取锁
为key设置一个过期时间(即使获取锁的客户端挂了,过期后也会自动释放锁)
对key的值进行判断是否过期public void lock() { for() { result = setNX lock_ley (value, expireTime); if(result || (now() > get lock && now() > (getSet lock expireTime))) { return true; } Thread.sleep(1000); } }
-
释放锁
public void release() { if(now() < get lock) { del lock } }
-
zookeeper实现分布式锁
-
分布式锁实现原理
- 分布式锁的实现
- 怎么获取锁
能够提供一种方式,多个客户端并发操作,只能有一个客户端能满足相应的要求 - 怎么释放锁
- 正常情况下释放锁
- 异常情况下如何释放锁(即释放锁的操作没有被执行,如挂掉、没执行成功等)
Redis正常情况下释放锁是删除key,异常情况下,只能通过超时时间自动释放
ZooKeeper正常情况下释放锁是删除临时节点,异常情况下,服务器也会主动删除临时节点
- 怎么得知锁被释放了
- 没有获取锁的客户端不断尝试获取锁
- 服务器端通知客户端锁被释放了
ZooKeeper通过注册watcher来得到锁释放的通知
- 怎么获取锁
- 分布式锁的实现
推荐阅读
-
Scala当中什么是RDD(Resilient Distributed Datasets)弹性分布式数据集
-
看MySQL的参数调优及数据库锁实践有这一篇足够了
-
Python知识之 方法与函数、偏函数、轮询和长轮询、流量削峰、乐观锁与悲观锁
-
PHP+redis实现的悲观锁机制示例
-
[原创]分布式系统之缓存的微观应用经验谈(一) 【设计细节篇】
-
[原创]分布式系统之缓存的微观应用经验谈(二) 【主从和主备高可用篇】
-
(一)ASP.Net Core 分布式通信----序列化
-
linux 可执行文件与写操作的同步问题(文件读写操作产生的锁机制)
-
SpringBoot+Dubbo+Zookeeper整合搭建简单的分布式应用
-
SQLSERVER查询锁表,阻塞,使用表名查询存储过程,行数,表字段类型等常规查询实例讲解