分布式锁
Posted strandtrack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式锁相关的知识,希望对你有一定的参考价值。
分布式锁
一 为什么要使用分布式锁
在以前,我们使用单机应用,开发应用时,都是用的多线程来控制程序的同步访问,来防止业务逻辑上的出错,比如可能会出现一个库存超载的问题。
举个例子,门票售卖时,总共商品只有一百件,在最后一件时,可能会同时出现好几个人同时想来购买门票的情况,这种时候如果不用一些手段来控制就会出现门票超卖的情况。
这时候作为消费提供者也就是商家的我们就要对此付出责任,所以这就是使用锁的重要性。
那么为什么要使用分布式锁呢,因为现在随着科技的发展,业务的增多。大部分应用或者项目使用的不再仅仅只是一台电脑,而是使用集群,把多台电脑连接到一起,在这个基础上再做负载均衡,能用多个服务端来分担
大量的访问压力。而这个时候原本的基于java并发处理的api(像synchronizd,notify等等)在这里已经不适用了,这时候我们就要使用分布式锁来解决问题了。
二 使用分布式锁的条件
1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
2、高可用的获取锁与释放锁;
3、高性能的获取锁与释放锁;
4、具备可重入特性;
5、具备锁失效机制,防止死锁;
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。
三 使用分布式锁的三种方式
1.基于redis使用分布式锁
在用redis实现分布式锁之前,我先来介绍几种redis的方法。
setnx():这个方法是增加key到redis中,但他和一般的set不同的是,这个方法会先判断你的key是否已经存在于redis中,如果不存在才进行添加,如果存在则保持不变。
expire():这个方法是进行ttl操作的,对你所操作的key设置过期时间,超过这个时间锁会自动释放,避免死锁。
delete():这个就很简单了,就是删除,在这里就是取消锁。
用redis使用分布式锁用的大概就是这几种方法。
思路:先设置setnx,这个方法会有个返回值(1和0),通过这个值来判断是否获取到锁。如果获取到锁,对锁进行设置过期时间避免死锁,然后进行你的业务操作,最后把这个锁删除。值得一提的是,设置的value最好是
uuid生成的uuid值,这个是个建议。
代码:
try
lock = redisTemplate.opsForValue().setIfAbsent(lockKey, LOCK);//判断是否获取到锁
if (lock)
redisTemplate.expire(lockKey,1, TimeUnit.MINUTES); //成功设置过期时间
return res;
else
//没有获取到锁
finally
if(lock)
redisTemplate.delete(lockKey); //任务结束,释放锁
else
//不需要操作
2 基于数据库的实现方式
基于数据库的实现方式的核心思想是:在数据库中创建一个表,表中包含方法名等字段,并在方法名字段上创建唯一索引,想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁。
当你想对数据进行操作时,先对数据库进行插入,因为是唯一性约束,所以当同时几个请求同时发送时,数据库只会接受一个。这个时候就认为成功的那个获取了锁,然后进行业务操作。最后delete按个方法名就是释放掉锁。
3 基于zookeeper的实现方式
实现步骤如下:
(1)创建一个目录mylock;
(2)线程A想获取锁就在mylock目录下创建临时顺序节点;
(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;
(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。
以上是关于分布式锁的主要内容,如果未能解决你的问题,请参考以下文章
Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析&Redis分布式锁的正确使用姿势!...
Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析&Redis分布式锁的正确使用姿势!...
Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析&Redis分布式锁的正确使用姿势!...
Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析&Redis分布式锁的正确使用姿势!...