- 锁信息表sql
避免时区问题,expire_time使用bigint存储时间戳
CREATE TABLE IF NOT EXISTS `lock_info`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`lock_key` varchar(128) NOT NULL COMMENT '加锁的key',
`expire_time` bigint unsigned NOT NULL COMMENT '过期时间',
`create_ts` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`update_ts` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_lock_key` (`lock_key`)
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT ='分布式锁信息表';
<insert id="insert">
INSERT INTO lock_info(lock_key, expire_time)
VALUES(#{lockKey}, #{expireTime})
</insert>
<delete id="delete">
delete from lock_info
<where>
and lock_key=#{lockKey}
and expire_time=#{expireTime}
</where>
limit 1
</delete>
<update id="updateExpireTime">
UPDATE lock_info
<set>
expire_time=#{newExpectTime},
</set>
<where>
and lock_key=#{lockKey}
and expire_time=#{oldExpectTime}
</where>
</update>
<select id="select" resultType="cn.laifuzhi.template.model.PO.LockInfoPO">
select id,
lock_key as lockKey,
expire_time as expireTime,
create_ts as createTs,
update_ts as updateTs
from lock_info
<where>
and lock_key=#{lockKey}
</where>
</select>
@Slf4j
@Service
public class LockService {
@Resource
private LockInfoDao lockInfoDao;
public Date tryLock(String lockKey, int expireSeconds) {
Preconditions.checkArgument(StringUtils.isNotBlank(lockKey));
try {
Date now = new Date();
Date newExpireTime = DateUtils.addSeconds(now, expireSeconds);
LockInfoPO dbLockInfo = lockInfoDao.select(lockKey);
if (dbLockInfo == null) {
dbLockInfo = new LockInfoPO();
dbLockInfo.setLockKey(lockKey);
dbLockInfo.setExpireTime(newExpireTime);
lockInfoDao.insert(dbLockInfo);
return newExpireTime;
}
// 锁还未到过期时间,或者更新过期时间失败
Date oldExpireTime = dbLockInfo.getExpireTime();
if (now.before(oldExpireTime)
|| lockInfoDao.updateExpireTime(lockKey, oldExpireTime, newExpireTime) <= 0) {
return null;
}
log.info("tryLock key:{} expire:{}", lockKey, DateFormatUtils.format(newExpireTime, DATETIME_FORMAT));
return newExpireTime;
} catch (DuplicateKeyException e) {
log.debug("tryLock duplicate key:{}", lockKey);
return null;
} catch (Exception e) {
log.error("tryLock error key:{}", lockKey, e);
return null;
}
}
public void release(String lockKey, Date expectExpireTime) {
Preconditions.checkArgument(StringUtils.isNotBlank(lockKey));
try {
boolean result = lockInfoDao.delete(lockKey, expectExpireTime) > 0;
log.info("release key:{} expect:{} result:{}", lockKey, DateFormatUtils.format(expectExpireTime, DATETIME_FORMAT), result);
} catch (Exception e) {
log.error("release key error key:{} expect:{}", lockKey, DateFormatUtils.format(expectExpireTime, DATETIME_FORMAT), e);
}
}
}
网友评论