分布式锁在Redis实现的一些注意事项

查看了不少关于redis实现分布式锁的文章,无疑要设计一个靠谱的分布式并不太容易,总会出现各种鬼畜的问题;现在就来小述一下,在设计一个分布式锁的过程中,会遇到一些什么问题
摘要由CSDN通过智能技术生成

前言

查看了不少关于redis实现分布式锁的文章,无疑要设计一个靠谱的分布式并不太容易,总会出现各种鬼畜的问题;现在就来小述一下,在设计一个分布式锁的过程中,会遇到一些什么问题

I. 背景知识

借助redis来实现分布式锁(我们先考虑单机redis的模式),首先有必要了解下以下几点:

单线程模式

setnx : 当不存在时,设置value,并返回1; 否则返回0

getset : 设置并获取原来的值

expire : 设置失效时间

get : 获取对应的值

del : 删除

ttl : 获取key对应的剩余时间,若key没有设置过超时时间,或者压根没有这个key则返回负数(可能是-1,-2)

watch/unwatch : 事务相关

II. 方案设计

1. 设计思路

获取锁:

调用 setnx 尝试获取锁,如果设置成功,表示获取到了锁

设置失败,此时需要判断锁是否过期

未过期,则表示获取失败;循环等待,并再次尝试获取锁

已过期,getset再次设置锁,判断是否获取了锁(根据返回的值进行判断,后面给出具体的方案)

若失败,则重新进入获取锁的逻辑

释放锁:

一个原则就是确保每个业务方释放的是自己的锁

2. getset的实现方案

网上一种常见的case,主要思路如下

setnx 尝试获取锁

失败,则 get 获取锁的value (一般是 uuid_timstamp)

判断是否过期,若没有过期,则表示真的获取失败

若过期,则采用 getset设置,尝试获取锁

实现代码如下

public class DistributeLock {

private static final Long OUT_TIME = 30L;

public String tryLock(Jedis jedis, String key) {

while (true) {

String value = UUID.randomUUID().toString() + "_" + System.currentTimeMillis();

Long ans = jedis.setnx(key, value);

if (ans != null && ans == 1) { // 获取锁成功

return value;

}

// 锁获取失败, 判断是否超时

String oldLock = jedis.get(key);

if (oldLock == null) {

continue;

}

long oldTime = Long.parseLong(oldLock.substring(oldLock.lastIndexOf("_") + 1));

long now = System.currentTimeMillis();

if (now - oldTime < OUT_TIME) { // 没有超时

continue;

}

String getsetOldVal = jedis.getSet(key, value);

if (Object

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值