redis官方推薦分布式鎖實作方案--redisson for java
執行個體代碼位址,請前往:https://gitee.com/GuoqingLee/distributed-seckill
redis官方文檔位址,請前往:http://www.redis.cn/topics/distlock.html
前言
關于分布式鎖的實作,目前主流方案有以下三類:
1、基于資料庫的樂觀鎖;
2、基于redis實作的鎖服務;
3、基于zookeeper的實作;
網上關于怎麼實作redis的分布式鎖,一搜一大把的文章,有寫的比較好的,也有明顯存在缺陷的,非常容易誤導初入這一塊的初學者;
而存在的問題,無外乎是setnx()-->expire(),保證不了原子性,容易出現死鎖等情況,這裡就不在去做解釋了;
本文的主旨是如何使用redis官方推薦的redisson實作redis的分布式鎖;
一、具體實作:
maven引入需要的jar
1 <dependency>
2 <groupId>org.redisson</groupId>
3 <artifactId>redisson-spring-boot-starter</artifactId>
4 <version>3.10.1</version>
5 </dependency>
配置檔案如下
# common spring boot settings
spring.redis.database=
spring.redis.host=
spring.redis.port=
spring.redis.password=
spring.redis.ssl=
spring.redis.timeout=
spring.redis.cluster.nodes=
spring.redis.sentinel.master=
spring.redis.sentinel.nodes=
封裝工具類:
1 package cn.com.bluemoon.redis.lock;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.redisson.api.RLock;
6 import org.redisson.api.RedissonClient;
7 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.stereotype.Component;
9
10 /**
11 * 基于Redisson的分布式鎖實作
12 * @author Guoqing.Lee
13 * @date 2019年1月23日 下午4:04:57
14 *
15 */
16 @Component
17 public class RedissonDistributedLocker {
18
19 @Autowired
20 private RedissonClient redissonClient;
21
22 /**
23 * 加鎖
24 * @param lockKey
25 * @return
26 */
27 public RLock lock(String lockKey) {
28 RLock lock = redissonClient.getLock(lockKey);
29 lock.lock();
30 return lock;
31 }
32
33 /**
34 * 加鎖,過期自動釋放
35 * @param lockKey
36 * @param leaseTime 自動釋放鎖時間
37 * @return
38 */
39 public RLock lock(String lockKey, long leaseTime) {
40 RLock lock = redissonClient.getLock(lockKey);
41 lock.lock(leaseTime, TimeUnit.SECONDS);
42 return lock;
43 }
44
45 /**
46 * 加鎖,過期自動釋放,時間機關傳入
47 * @param lockKey
48 * @param unit 時間機關
49 * @param leaseTime 上鎖後自動釋放時間
50 * @return
51 */
52 public RLock lock(String lockKey, TimeUnit unit, long leaseTime) {
53 RLock lock = redissonClient.getLock(lockKey);
54 lock.lock(leaseTime, unit);
55 return lock;
56 }
57
58 /**
59 * 嘗試擷取所
60 * @param lockKey
61 * @param unit 時間機關
62 * @param waitTime 最多等待時間
63 * @param leaseTime 上鎖後自動釋放時間
64 * @return
65 */
66 public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
67 RLock lock = redissonClient.getLock(lockKey);
68 try {
69 return lock.tryLock(waitTime, leaseTime, unit);
70 } catch (InterruptedException e) {
71 return false;
72 }
73 }
74
75 /**
76 * 嘗試擷取所
77 * @param lockKey
78 * @param waitTime 最多等待時間
79 * @param leaseTime 上鎖後自動釋放鎖時間
80 * @return
81 */
82 public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
83 RLock lock = redissonClient.getLock(lockKey);
84 try {
85 return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
86 } catch (InterruptedException e) {
87 return false;
88 }
89 }
90
91 /**
92 * 釋放鎖
93 * @param lockKey
94 */
95 public void unlock(String lockKey) {
96 RLock lock = redissonClient.getLock(lockKey);
97 lock.unlock();
98 }
99
100 /**
101 * 釋放鎖
102 * @param lock
103 */
104 public void unlock(RLock lock) {
105 lock.unlock();
106 }
107
108 }
二、使用方式
方式一:
1 @Autowired
2 private RedissonDistributedLocker redissonDistributedLocker;
3
4 String lockKey = "BM_MARKET_SECKILL_" + stallActivityId;
5 try {
6 //超過2S自動釋放鎖
7 redissonDistributedLocker.lock(lockKey, 2L);
8 //業務處理
9
10 } finally {
11 redissonDistributedLocker.unlock(lockKey); //釋放鎖
12 }
方案二:
1 @Autowired
2 private RedissonDistributedLocker redissonDistributedLocker;
3
4 public void test() throws InterruptedException {
5 final int[] counter = {0};
6
7 for (int i= 0; i < 100; i++){
8
9 new Thread(new Runnable() {
10
11 @Override
12
13 public void run() {
14 boolean isGetLock = redissonDistributedLocker.tryLock("test0001", 3L, 1L);
15 if(isGetLock) {
16 try {
17 int a = counter[0];
18 counter[0] = a + 1;
19 logger.info(a + "");
20 } finally {
21 redissonDistributedLocker.unlock("test0001");
22 }
23 }
24 }
25 }).start();
26
27 }
28
29 // 主線程休眠,等待結果
30 Thread.sleep(5000);
31 System.out.println(counter[0]);
32 logger.info(counter[0] + "");
33 }
閑話就不多說了,希望能對你有所幫助。