1 package cn.gitlab.repository.utils;
2
3
4 import cn.gitlab.repository.dao.DBLockMapper;
5 import lombok.extern.slf4j.Slf4j;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.beans.factory.annotation.Value;
8 import org.springframework.stereotype.Component;
9
10 import java.util.Optional;
11
12 @Component
13 @Slf4j
14 public class DBLock {
15
16 @Autowired
17 DBLockMapper dbLockMapper;
18 @Value("${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}")
19 String serviceInstantiation;
20 /**
21 * 获取锁
22 * @param lockKey 锁标志
23 * @param expiryMaxTimeOutSecond 超过时间的锁会被自动清理 自动进行释放 (单位 秒)
24 */
25 public boolean tryLockNotAwait(String lockKey,Long expiryMaxTimeOutSecond){
26 log.info("tryLockNotAwait:{} ,{}",lockKey,expiryMaxTimeOutSecond);
27 try {
28 String uniqueInstantiationFlag = getInstantiationFlag();
29 log.info("uniqueInstantiationFlag:{}",uniqueInstantiationFlag);
30 try {
31 int successCount = dbLockMapper.insert(lockKey, expiryMaxTimeOutSecond, uniqueInstantiationFlag);
32 log.info("count1:{}",successCount);
33 if (successCount > 0) {
34 //获取锁成功
35 return true;
36 } else {
37 log.info("获取锁失败tryLockNotAwait1");
38 //获取锁失败
39 return getLockFail(lockKey, expiryMaxTimeOutSecond, uniqueInstantiationFlag);
40 }
41 } catch (Exception e) {
42 log.info("获取锁失败tryLockNotAwait2");
43 //获取锁失败
44 return getLockFail(lockKey, expiryMaxTimeOutSecond, uniqueInstantiationFlag);
45 }
46 }catch (Exception e){
47 //防止异常影响正常业务逻辑
48 return false;
49 }
50 }
51
52 /**
53 * 解锁
54 * @param key 锁标志
55 */
56 public void unLock(String key){
57 log.info("unLock:{}",key);
58 try {
59 String instantiationFlag = getInstantiationFlag();
60 Integer lockReentryCount = dbLockMapper.getLockReentryCount(key, instantiationFlag);
61
62 if (Optional.ofNullable(lockReentryCount).orElse(0) > 1) {
63 //重入次数大于1 减 1
64 dbLockMapper.subtractReentryCount(key, instantiationFlag);
65 } else if (lockReentryCount != null) {
66 //存在锁 则删除锁
67 dbLockMapper.deleteKey(key, instantiationFlag);
68 }
69 }catch (Exception e){
70 log.info("解锁出现异常");
71 }
72 }
73
74 private boolean getLockFail(String lockKey, Long expiryMaxTimeOutSecond, String uniqueInstantiationFlag) {
75 try {
76 //尝试当前线程重入
77 int incrementSuccessCount = dbLockMapper.incrementReentryCount(lockKey, uniqueInstantiationFlag);
78 log.info("count2:{}",incrementSuccessCount);
79 if (incrementSuccessCount > 0) {
80 //重入成功
81 return true;
82 } else {
83 log.info("尝试重入失败1");
84 //重入失败 尝试删除过期锁
85 return deleteExpiryLock(lockKey, expiryMaxTimeOutSecond, uniqueInstantiationFlag);
86 }
87 }catch (Exception e){
88 log.info("尝试重入失败2");
89 //重入失败 尝试删除过期锁
90 return deleteExpiryLock(lockKey, expiryMaxTimeOutSecond, uniqueInstantiationFlag);
91 }
92
93 }
94
95 private boolean deleteExpiryLock(String lockKey, Long expiryMaxTimeOutSecond, String uniqueInstantiationFlag) {
96 //重入也失败 在尝试检查当前锁是否超时过期
97 int deleteSuccessCount = dbLockMapper.deleteIsExpiry(lockKey);
98 log.info("count3:{}",deleteSuccessCount);
99 if (deleteSuccessCount > 0) {
100 //这个锁已经过期了 再次重试
101 try {
102 log.info("删除过期锁后,尝试重新获取锁");
103 int retrySuccessCount = dbLockMapper.insert(lockKey, expiryMaxTimeOutSecond, uniqueInstantiationFlag);
104 log.info("count4:{}",retrySuccessCount);
105 return retrySuccessCount > 0;
106 }catch (Exception e){
107 log.info("删除过期锁后,尝试重新获取锁失败");
108 return false;
109 }
110 }
111 //获取锁失败
112 return false;
113 }
114
115
116 private String getInstantiationFlag() {
117 long threadId = Thread.currentThread().getId();
118 return serviceInstantiation+threadId;
119 }
120
121
122
123
124 }
库表
1 -- PIPELINE.DB_LOCK definition
2
3 CREATE TABLE PIPELINE.DB_LOCK (
4 LOCK_KEY VARCHAR(765) NOT NULL,
5 CREATE_TIME TIMESTAMP NOT NULL,
6 EXPIRY_MAX_TIME TIMESTAMP NOT NULL,
7 REENTRY_COUNT BIGINT NOT NULL,
8 UNIQUE_INSTANTIATION_FLAG VARCHAR(765) NULL,
9 CONSTRAINT CONS134221205 PRIMARY KEY (LOCK_KEY)
10 );
11 CREATE UNIQUE INDEX INDEX33559380 ON PIPELINE.DB_LOCK (LOCK_KEY);