java redis 分布式_java实现Redis分布式锁

网上到处都是分布式锁的代码,基本都是通过setNX 和 expire

这两个不是原子操作,肯定会有问题,不乏好多人通过用setNX的value当做过期时间来弥补等等。但是好像都不太好,或者多少有点问题。

从一个大神那里得来的代码

1 packagecom.abc.def.util;2

3 importredis.clients.jedis.Jedis;4

5 importjava.util.Collections;6

7 public classRedisDistributedLock {8

9

10 private static final String LOCK_SUCCESS = "OK";11 private static final String SET_IF_NOT_EXIST = "NX";12 private static final String SET_WITH_EXPIRE_TIME = "PX";13 private static final Long RELEASE_SUCCESS = 1L;14

15 /**

16 * 尝试获取分布式锁17 *@paramjedis Redis客户端18 *@paramlockKey 锁19 *@paramrequestId 请求标识20 *@paramexpireTime 超期时间21 *@return是否获取成功22 */

23 public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, intexpireTime) {24

25 String result =jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);26

27 if(LOCK_SUCCESS.equals(result)) {28 return true;29 }30 return false;31

32 }33

34 /**

35 * 释放分布式锁36 *@paramjedis Redis客户端37 *@paramlockKey 锁38 *@paramrequestId 请求标识39 *@return是否释放成功40 */

41 public static booleanreleaseDistributedLock(Jedis jedis, String lockKey, String requestId) {42

43 String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";44 Object result =jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));45

46 if(RELEASE_SUCCESS.equals(result)) {47 return true;48 }49 return false;50

51 }52

53 }

获取锁,通过一个条指令来获取并且同时设置超时。

另外,解锁是通过获取锁的时候设置的key  这个key应该是一个随机值 推荐使用 UUID 来生成。 这样只能解锁自己的锁

另外解锁操作用的lua脚本来执行,把三条语句集合成一个原子操作。

使用示例代码:

1 while(true){2   String uuid =UUID.randomUUID().toString();4 boolean ret = lock.tryGetDistributedLock(redis,"NX_TEST", uuid, 5000);5 if(ret != false){6 //TODO 实现业务逻辑

7 lock.releaseDistributedLock(redis,"NX_TEST", uuid);8 break;9 }else{10 Thread.sleep(500);11 }12}

这里,设置的5000(5秒)超时时间,这个时间一定要大于业务逻辑的执行时间,否则就没办法锁住了。。

参考博客 https://wudashan.cn/2017/10/23/Redis-Distributed-Lock-Implement/

PS: 哪位大神知道怎么从RedisTemplate 中获取 jedis ,RedisTemplate 并没有封装set 的相关函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值