使用Redis实现分布式锁

原文链接:http://www.dubby.cn/detail.html?id=9067

加锁

网上大部分建议都是使用SETNX,这个本身没有什么问题,因为低版本的Redis中,只有这个命令可以互斥的Set一个Key。但是随着Redis版本的升高,提供了更多的命令来更好的满足我们的需求。

SET

SET key value [EX seconds] [PX milliseconds] [NX|XX]

这可和你所知道的不太一样,SET key value我们都知道,那后面的选项是啥呢。其实SET这个命令在Redis 1.0.0的时候就提供了,但是那个时候,只提供了SET key value,后面的选项是Redis 2.6.12的时候加上的:

  • EX seconds : 设置过期时间, 单位是秒
  • PX milliseconds : 设置过期时间, 单位是毫秒
  • NX : 只有Key**不存在**的时候才会设置成功
  • XX : 只有Key**已经存在**的时候才会设置成功

为什么比原来的使用SETNX更好呢,因为SETNX不能设置过期时间,那么使用过程大致是这样的:

//1.加锁
SETNX key value

//2.防止死锁,设置过期时间
EXPIRE key seconds

//3.业务逻辑...

//4.释放锁

如果程序在2步之前,1步之后挂掉了,就会导致死锁,根本原因和就是设置锁和设置过期时间不是原子操作,当然你也可以使用事物来保证,只是没有这么简洁而已。

释放锁

DEL

DEL key [key ...]

直接使用DEL来删除就可以了。

更健壮的锁

上面讨论的锁,其实只关注Key,Value并没有关心,这样的问题就是,不能确定这个锁究竟是属于哪个客户端,也就存在了误删除的可能。

举个例子,一个客户端创建了lock1,处理完逻辑后,这个客户端准备释放这个锁lock1,但是这步操作发生在锁的有效期之后,也就是这个lock1已经自动失效了,这时有另一个客户端创建了一个新的锁lock2,那么客户端删除的就是lcok2了,这就是错误释放锁了。

  1. 把Value设置成一个Token意义的值,比如UUID。
  2. 不能简单的使用DEL来释放锁,而需要借助脚本
if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end

,调用方法大致是EVAL ...script... resource-name token-value

redisson

更成熟的分布式锁和同步器

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值