前言
线程之间锁问题多解决主要有数据库锁机制、Redis分布式锁、ZooKeeper分布式锁。其中Redis内单节点的分布式锁可以使用setnx进行处理。集群环境需要使用redisson。
本文相关代码,可在我的Github项目https://github.com/SeanYanxml/bigdata/tree/master/redis 目录下可以找到。
PS: (如果觉得项目不错,可以给我一个Star。)
Demo
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 1/**
2 * Jedis lock.
3 *
4 * */
5public class RedisLockDemo {
6
7 public static Jedis jedis = new JedisPoolManager().getJedis();
8
9
10 // demo1 Jedis lock can do but not perfect.
11 public static boolean notperfectLock(String key){
12 Long result = jedis.setnx(key, "This is a Lock.");
13 if(result == 1l){
14 return true;
15 }else{
16 return false;
17 }
18 }
19
20 // demo1 Jedis unlock can do but not perfect.
21 public static boolean notperfectUnlock(String key){
22 jedis.del(key);
23 return true;
24 }
25
26 // demo1 Jedis unlock can do but also not perfect.
27 public static boolean notperfectUnlock2(String lockKey, String lockValue){
28 if(lockKey.equals(jedis.get(lockKey))){
29 jedis.del(lockKey);
30 }
31 return true;
32 }
33
34 // demo2 perfect lock demo.
35 private static final String LOCK_SUCCESS = "OK";
36 private static final String SET_IF_NOT_EXISTS = "NX";
37 private static final String SET_WITH_EXPIRE_TIME = "PX";
38
39 /**
40 * 设置分布式锁
41 * @param jedis Redis客户端
42 * @param lockKey 锁
43 * @param requestId 请求标识
44 * @param expireTime 生效时间
45 * @return 是否释放成功
46 */
47 public static boolean tryGetDistributedLock(String lockKey,String requestId,int expireTime){
48 String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXISTS,SET_WITH_EXPIRE_TIME,expireTime);
49 if(LOCK_SUCCESS.equals(result)){
50 return true;
51 }
52 return false;
53 }
54
55
56 private static final Long RELEASE_SUCCESS = 1L;
57
58 /**
59 * 释放分布式锁
60 * @param jedis Redis客户端
61 * @param lockKey 锁
62 * @param requestId 请求标识
63 * @return 是否释放成功
64 */
65 public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
66
67 String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
68 Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
69
70 if (RELEASE_SUCCESS.equals(result)) {
71 return true;
72 }
73 return false;
74
75 }
76
77 public static void main(String[] args) {
78 releaseDistributedLock(jedis,"hello","hello");
79 }
80}
81
Reference
[1]. Redis分布式锁的正确实现方式(Java版)
[2]. 分布式锁的几种使用方式(redis、zookeeper、数据库)
[3]. Redis学习笔记(六)redis实现分布式锁