Redis 分布式锁

Redis  没有add 命令,但有SETNX(SET if Not eXists)若给定的 key 已经存在,则 SETNX不做任何动作。设置成功,返回 1 。设置失败,返回 0 。

SETNX 命令不能设置过期时间,需要再使用 EXPIRE 命令设置过期时间。

伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int  lockResult = rd.SETNX( "LockKey" "Value" );
if  (lockResult == 1)
{
     //[1]得到锁
 
     //[2]设置超时过期时间
     rd.EXPIRE( "LockKey" , expiredtime);
 
     try
     {
         //do business  function
 
         //检查超时
         if  (!CheckedTimeOut())
         {
             rd.DEL( "LockKey" );
         }
     }
     catch  (Exception e)
     {
         rd.DEL( "LockKey" );
     }
 
}

   这种做法,有一个很大的潜在风险。[1]得到锁后,再执行[2] 设置过期时间。如果在这期间出现宕机,则会导致没有设置过期时间。按Redis 的默认缓存过期策略,这个锁将不会释放,产生死锁。

所以不推荐用这种做法,应该用其它方式来实现锁的超时过期策略:

     1:SETNX  value 值=当前时间+过期超时时间,返回1 则获得锁,返回0则没有获得锁。转2。

     2:GET 获取 value 的值 。判断锁是否过期超时。如果超时,转3。

     3:GETSET(将给定 key 的值设为 value ,并返回 key 的旧值),GETSET  value 值=当前时间+过期超时时间, 判断得到的value 如果仍然是超时的,那就说明得到锁,否则没有得到锁。

从2并发进到3 的操作,会多次改写超时时间,但这个不会有什么影响。

伪代码:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
string  expiredtime = DateTime.Now.AddMinutes(LockTimeoutMinutes).ToString();
int  lockResult = rd.SETNX( "LockKey" , expiredtime);
bool  getLock =  false ;
if  (lockResult == 1)
{
     //得到锁
     getLock =  true ;
}
else
{
     string  curExpiredtime = rd.GET( "LockKey" );
 
     //检查锁超时
     if  (CheckedLockTimeOut(expiredtime))
     {
         expiredtime = DateTime.Now.AddMinutes(LockTimeoutMinutes).ToString();
         string  newExpiredTime = GETSET(expiredtime);
         if  (CheckedLockTimeOut(newExpiredTime))
         {
             //得到锁
             getLock =  true ;
         }
     }
}
if  (getLock)
{
     try
     {
         //do business  function
 
         //检查超时
         if  (!CheckedTimeOut())
         {
             rd.DEL( "LockKey" );
         }
     }
     catch  (Exception e)
     {
         rd.DEL( "LockKey" );
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值