Redis 分布式锁
来源:互联网 发布:软件定义存储解决方案 编辑:程序博客网 时间:2024/06/04 19:00
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
- Redis实现分布式锁
- Redis 分布式锁实现
- Redis 分布式锁实现
- redis 分布式锁
- redis分布式锁
- Redis实现分布式锁
- Redis分布式锁思考
- redis实现分布式锁
- Redis实现分布式锁
- Redis分布式锁
- redis分布式锁
- maven + redis + 分布式锁
- 分布式锁redis实现
- redis分布式锁
- redis分布式锁
- Redis 分布式锁实现
- **redis分布式锁**
- redis分布式锁实现
- JavaPAT1020月饼
- zerocopy与java知识相关小记
- ajax传递数组List和Map
- JAVA进阶----ThreadPoolExecutor机制
- Java中“==”与“equals”的区别
- Redis 分布式锁
- javascript判断对象是否为空对象。
- 《Spark官方文档》Spark操作指南
- oracle 重命名表名或者字段名
- 多个Ativity值传递FLAG_ACTIVITY_FORWARD_RESULT
- 物联网、大数据、智能思维在油气生产中的应用方案
- java序列化 为什么要序列化?
- PHP中的elseif和else if
- java项目实现简单的oracle存储过程