mikuriya

DBLock数据库锁

  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);

 

posted on 2025-02-25 11:09  mikuriya  阅读(9)  评论(0)    收藏  举报

导航