redis分布式锁的思考

注:部分内容来源于广大网友。

1.加锁

jedis.set(key, value, "NX","PX",10000);

这个操作是原子性的,同一时刻只能有一个线程操作成功。

key: 分布式下所有机器使用相同的key;

value:有讲究,下面说;

10000:为什么设置过期时间,下面说;

2. 解锁

jedis.del(key);

现在考虑下可用性:假如现在加锁的这台机器挂掉了,那么锁就永远无法释放。假如是以某件商品id为key,那么这件商品就永远没有用武之地,如果是秒杀,所有人都抢不到。因此,需要加过期时间

加了过期时间又会涉及到另一个问题:现在假设过期时间设置30s, 有个线程处理了35s, 那么就会出现有两个线程同时进入业务逻辑,会产生数据一致性问题。根本原因是两个线程同时操作数据库,想进行库存减1操作,那保证只有一个可以提交就可以了。

事务 + lua脚本保证数据一致性

删除key的时候,只有删除成功的才可以提交事务,否则可以返回个错误页面;

如果只是使用 jedis.del(key);那么所有线程都可以提交成功了。

线程A过期了,线程B拿到了锁,此时redis中的值是线程B设置的;我们就是要根据不同线程的value来区分,用ThreadLocal存放当前线程设置的value;此时线程A判断自己设置的值redis中已经没有了,那就不能提交;

先判断再删除,两个操作的原子性使用lua脚本,根据返回值判断是否删除成功;成功的话,提交事务。

String script =
                "if redis.call('get',KEYS[1]) == ARGV[1] then" +
                        "   return redis.call('del',KEYS[1]) " +
                        "else" +
                        "   return 0 " +
                        "end";
Object result = jedis.eval(script, Collections.singletonList(key), 
            Collections.singletonList(value));

总结:个人认为,如果保证过期时间内能处理完业务,那就不用涉及value、事务、lua了,直接jedis.del(key)就行了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值