1 / 14
文档名称:

分布式锁通用解决方案.docx

格式:docx   大小:125KB   页数:14页
下载后只包含 1 个 DOCX 格式的文档,没有任何的图纸或源代码,查看文件列表

如果您已付费下载过本站文档,您可以点这里二次下载

分享

预览

分布式锁通用解决方案.docx

上传人:科技星球 2022/3/10 文件大小:125 KB

下载得到文件列表

分布式锁通用解决方案.docx

相关文档

文档介绍

文档介绍:分布式锁通用解决方案
 
   
 
 
 
 
 
 
 
     
 
 
 
 
 
分布式锁的解决方式:
基于数据库:
基于数据库表做乐观锁,用于分布式锁。(version) 基于数据库{
}
//为空或者抛异常的话都表示没有获取到锁
sleep(1000);
count++;
}
throw new LockException();
}
()操作来释放锁。
这种方法可以有效的解决上面提到的无法释放锁和阻塞锁的问题。 • 阻塞锁? for update语句会在执行成功后立即返回,在执行失败时一直处于阻塞状态,直到成功。 • 锁定之后服务宕机,无法释放?使用这种方式,服务宕机之后数据库会自己把锁释放掉 。 但是还是无法直接解决数据库单点和可重入问题。
这里还可能存在另外一个问题,虽然我们对method_name 使用了唯一索引,并且显示使用for update来使用行级锁。但是,MySql会对查询进行优化,即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同执行计划的代价来决定的,如果 MySQL 认为全表扫效率更高,比如对一些很小的表,它就不会使用索引,这种情况下 InnoDB
将使用表锁,而不是行锁。如果发生这种情况就悲剧了。。。
还有一个问题,就是我们要使用排他锁来进行分布式锁的lock,那么一个排他锁长时间不提交,就会占用数据库连接。一旦类似的连接变得多了,就可能把数据库连接池撑爆
基于数据库资源表做乐观锁,用于分布式锁:
1. 首先说明乐观锁的含义:
大多数是基于数据版本(VERSION)的记录机制实现的。何谓数据版本号?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表添加一个 “VERSION”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1。
在更新过程中,会对版本号进行比较,如果是一致的,没有发生改变,则会成功执行本次操作;如果版本号不一致,则会更新失败。
2. 对乐观锁的含义有了一定的了解后,结合具体的例子,我们来推演下我们应该怎么处理:
(1). 假设我们有一张资源表,如下图所示: T_RESOURCE , 其中有6个字段ID, RESOOURCE, STATE, ADD_TIME, UPDATE_TIME, VERSION,分别表示表主键、资源、分配状态(1未分配 2已分配)、资源创建时间、资源更新时间、资源数据版本号。
(4). 假设我们现在我们对ID=5780这条数据进行分配,那么非分布式场景的情况下,我们一般先查询出来STATE=1(未分配)的数据,然后从其中选取一条数据可以通过以下语句进行,如果可以更新成功,那么就说明已经占用了这个资源 UPDATE T_RESOURCE SET STATE=2 WHERE STATE=1 AND ID=5780。
(5). 如果在分布式场景中,由于数据库的UPDATE操作是原子是原子的,其实上边这条语句理论上也没有问题,但是这条语句如果在典型的“ABA”情况下,我们是无法感知的。有人可能会问什么是“ABA”问题呢?大家可以网上搜索一下,这里我说简单一点就是,如果在你第一次SELECT和第二次UPDATE过程中,由于两次操作是非原子的,所以这过程中,如果有一个线程,先是占用了资源(STATE=2),然后又释放了资源(STATE=1),实际上最后你执行UPDATE操作的时候,是无法知道这个资源发生过变化的。也许你会说这个在你说的场景中应该也还好吧,但是在实际的使用过程中,比如银行账户存款或者扣款的过程中,这种情况
是比较恐怖的。
(6). 那么如果使用乐观锁我们如何解决上边的问题呢?
A. 先执行SELECT操作查询当前数据的数据版本号,比如当前数据版本号是26:
SELECT ID, RESOURCE, STATE,VERSION FROM T_RESOURCE WHERE STATE=1 AND ID=5780;
B. 执行更新操作:
UPDATE T_RESOURE SET STATE=2, VERSION=27, UPDATE_TIME=NOW() WHERE RESOURCE=XXXXXX AND STATE=1 AND VERSION=26
C. 如果上述UPDATE语句真正更新影响到了一行数据,那就说明占位成功。如果没有更新影响到一行数据,则说明这个资源已经被别人占位了。
3. 基于数据库表做乐观锁的一些缺点:
(1). 这种操作方式,使原本一次的UPDATE操作,必须变为2次操作: SELECT版本号一次;UPDATE一次