基于数据库实现的分布式锁(实现代码)

/**
 * @description: 数据库方式实现分布式锁
 * @author: 码上得天下
 * @create: 2019-12-27 14:33
 **/
@RestController
public class LockOCCTest {

    @Value("${timertask.min.wait:50}")
    private String minWaitStr;

    @Value("${timertask.max.wait:500}")
    private String maxWaitStr;

    @Autowired
    LockOCCMapper lockOCCMapper;

    @PostMapping(value = "/getLock")
    public boolean getLock(@RequestBody Map<String, Object> requestMap){
        LockOCCDTO lockDTO = new LockOCCDTO();
        lockDTO.setLockName((String) requestMap.get("lockName"));
        lockDTO.setLockSeconds((Integer) requestMap.get("lockSeconds"));
        lockDTO.setLockUser((String) requestMap.get("lockUser"));
        lockDTO.setServerDomain((String) requestMap.get("serverDomain"));
        Long tsVersion = (Long) lockOCCMapper.queryLockTimeByLockName((String) requestMap.get("lockName"));
        lockDTO.setTsVersion(tsVersion);
        Integer lockSeconds = (Integer) requestMap.get("lockSeconds");
        //上次时间不存在则添加;
        if (null == tsVersion) {
            lockOCCMapper.insertLock(lockDTO);
            return true;
            //间隔时间大于设定则update
        } else if (System.currentTimeMillis()/1000 - tsVersion >= lockSeconds) {
            // 随机休眠等待,错峰获取锁
            this.randomSleep();
            int i = lockOCCMapper.updateLock(lockDTO);
            //update成功即执行
            if (1 == i) {
                return true;
                //update失败则锁定
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    private static int MIN_WAIT = 50;
    private static int MAX_WAIT = 500;
    private static int INCR_STEP_LENGTH = 20;
    private void randomSleep() {
        try {
            int minWait = MIN_WAIT;
            int maxWait = MAX_WAIT;
            if(StringUtils.isNotBlank(minWaitStr)){
                minWait = Integer.parseInt(minWaitStr);
            }
            if(StringUtils.isNotBlank(maxWaitStr)){
                maxWait = Integer.parseInt(maxWaitStr);
            }
            int steps = (maxWait - minWait) / INCR_STEP_LENGTH;
            Thread.sleep(new SecureRandom().nextInt(steps + 1) * INCR_STEP_LENGTH);
        } catch (InterruptedException e) {
        }
    }

}



@Mapper
public interface LockOCCMapper {

    @Select(" SELECT L.TS_VERSION TSVERSION FROM LOCK_OCC_MAS L WHERE LOCK_NAME = #{lockName}")
    Long queryLockTimeByLockName(String lockName);

    /**秒级时间戳,默认ts_version = 1514736000 */
    @Insert(" INSERT INTO LOCK_OCC_MAS(LOCK_NAME, LOCKED_BY, SERVER_DOMAIN) VALUES(#{lockName}, #{lockUser}, #{serverDomain})")
    void insertLock(LockOCCDTO lockDTO);

    @Update(" update lock_occ_mas l set \n" +
            "      l.locked_by = #{lockUser},\n" +
            "      l.server_domain = #{serverDomain},\n" +
            "      l.ts_version = (sysdate - to_date('1970-1-1 8', 'yyyy-MM-dd hh24')) * 86400,\n" +
            "      l.date_updated = sysdate\n" +
            "      where l.lock_name =#{lockName}\n" +
            "         and l.lock_state = 'Y'\n" +
            "         and (sysdate - to_date('1970-1-1 8', 'yyyy-MM-dd hh24')) * 86400 - l.ts_version > #{lockSeconds}\n" +
            "         and l.ts_version = #{tsVersion}")
    int updateLock(LockOCCDTO lockDTO);

}



public class LockOCCDTO {
    private String lockName;
    private int lockSeconds;
    private String lockUser;
    private String serverDomain;
    private Long tsVersion;

    public String getLockName() {
        return lockName;
    }

    public void setLockName(String lockName) {
        this.lockName = lockName;
    }

    public int getLockSeconds() {
        return lockSeconds;
    }

    public void setLockSeconds(int lockSeconds) {
        this.lockSeconds = lockSeconds;
    }

    public String getLockUser() {
        return lockUser;
    }

    public void setLockUser(String lockUser) {
        this.lockUser = lockUser;
    }

    public String getServerDomain() {
        return serverDomain;
    }

    public void setServerDomain(String serverDomain) {
        this.serverDomain = serverDomain;
    }

    public Long getTsVersion() {
        return tsVersion;
    }

    public void setTsVersion(Long tsVersion) {
        this.tsVersion = tsVersion;
    }

    @Override
    public String toString() {
        return "LockOCCDTO [lockName=" + lockName + ", lockSeconds="
                + lockSeconds + ", lockUser=" + lockUser + ", serverDomain="
                + serverDomain + ", tsVersion=" + tsVersion + "]";
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值