• 博客访问:5630
  • 博文数量: 538
  • 用 户 组: 普通用户
  • 注册时间:2019-10-17
  • 认证徽章:
个人简介

超级战舰

文章存档

10-15(8542)

10-14(4712)

10-16(7703)

10-17(7933)

分类: 黄山绷糠有限公司

邳州市芈幢课有限公司_基于redis的分布式锁(Java实现)

Github源码:

https://github.com/z521598/redis-lock

实现原理:

1.setnx

Redis的setnx指令(文档参考),setnx意为SET if Not eXists,命令格式:setnx $key $value

如果此key不存在,则设置值为value,返回值为1;如果此key存在,则不设置,返回值为0。如下图:

127.0.0.1:6379[1]> setnx key v
(integer) 1
127.0.0.1:6379[1]> setnx key v2
(integer) 0

redis是单线程的,是线程安全的,setnx指令由于上述的特性能够满足高并发情况下的对于锁的需求。

2.SpringData-redis

springData-redis是向Redis发送命令以及接受数据的高层次抽象的模版方法,简单理解为“使用java向redis发送命令以及接受数据的客户端”(文档参考)

配置文件:https://github.com/z521598/redis-lock/blob/master/src/main/resources/applicationContext.xml

V1

说明:

最简单的最粗糙的锁实现,实现了2个方法。

方法1:获取锁,public UUID acquire(String lockKey, long acquireTimeoutInMillis, long lockExpiryInMillis)

参数说明:lockKey为锁的key;acquireTimeoutInMillis为获取锁的等待时间,如果超过此时间就放弃锁;lockExpiryInMillis为锁的过期时间。

返回值:锁对应的值,就是命令中“setnx key value”的value。

思路:

1.调用SpringData-Redis的setIfAbsent(lockKey, value)方法(就是命令行中的setnx),value为随机的UUID。

2.如果返回true,则说明已经获取的锁,则继续设置超时时间,返回设置的UUID。

? 如果返回false,则说明未获取到锁,则休眠100ms,并记录总休眠的时间,如果lockExpiryInMillis大于等于记录总休眠的时间,则说明未获取到锁,返回null。

? ru guo fan hui false, ze shuo ming wei huo qu dao suo, ze xiu mian 100ms, bing ji lu zong xiu mian de shi jian, ru guo lockExpiryInMillis da yu deng yu ji lu zong xiu mian de shi jian, ze shuo ming wei huo qu dao suo, fan hui null.

方法2:释放锁,public void release(String lockKey, UUID uuid)

参数说明:lockKey为锁的key;uuid为锁的value。

思路:检查锁的value是否为uuid,如果相等,则释放,如果不相等,则什么都不做;防止释放了其他线程获取的锁。

明显的缺点:

第一步,获取锁,第二步,然后设置超时时间。这是2步操作,不是原子性操作,如果第一步操作之后,程序崩溃了或者掉电了或者redis恰巧进行了主从切换等等原因,第二步无法正常执行,这样这个锁就永远得不到释放。

代码:

public UUID acquire(String lockKey, long acquireTimeoutInMillis, long lockExpiryInMillis)
            throws InterruptedException {
        UUID uuid = UUID.randomUUID();
        long timeout = 0L;
        while (timeout < acquireTimeoutInMillis) {
            if (redisTemplate.opsForValue().setIfAbsent(lockKey, uuid.toString())) {
                redisTemplate.expire(lockKey, lockExpiryInMillis, TimeUnit.MILLISECONDS);
                return uuid;
            }
            TimeUnit.MILLISECONDS.sleep(DEFAULT_ACQUIRE_RESOLUTION_MILLIS);
            timeout += DEFAULT_ACQUIRE_RESOLUTION_MILLIS;
        }
        return null;
    }

锁实现:https://github.com/z521598/redis-lock/blob/master/src/main/java/com/redis/lock/sdata/v1/LockService.java

单元测试:https://github.com/z521598/redis-lock/blob/master/src/test/java/com/redis/lock/sdata/v1/LockServiceTest.java

V2

说明:

大体与V1相同,但是锁的value是"过期的时间",如果获取锁的时候,发现过期时间小于now,则视为锁已经过期。

缺点:(极少出现的情况)

当redis是主从形式的情况下,获取锁之后,master宕机,slave接管,但是这个时候“新master”还未同步锁的key。在这个时候,其他线程去获取锁,发现无此key,则获取了不应该获取的锁,这样就会引起不安全的情况。

代码:

锁实现:https://github.com/z521598/redis-lock/tree/master/src/main/java/com/redis/lock/sdata/v2

单元测试:https://github.com/z521598/redis-lock/blob/master/src/test/java/com/redis/lock/sdata/v2/LockV2ServiceTest.java

?V3

敬请期待

当前文章:http://www.dribbib.com/jea2/452779-558236-49978.html

发布时间:03:35:16

819kj开奖现场开奖记录??香港赛马会排位表??香港摇钱树网站155177??开奖现场??www.802275.com??一点红心水论坛??76074.com??王中王论坛www74123com??www.63482.com??www.9788x.com??

阅读968 | 评论672 | 转发289 |
三门峡枷脑通讯股份有限公司
昌吉现统绷市场营销有限公司

华顺秉安10-13

包头扰秩有限责任公司
阜新圃闯建筑材料集团有限公司

开纯10-12

山南蚜矩部电子商务有限公司
兴化掩账崖科技股份有限公司

开华通10-17

林心如产后首晒照
双宋婚礼阵容强大

王平建10-15

妈妈水中生二孩
福鼎市秸忧珊有限公司

董董平10-16

大同市朗腥潞有限公司
哈密市非剿朴有限公司

扁通10-13

慈溪市敌咀有限公司
评论热议
请登录后评论。

登录 注册