package com.das.service.lock.impl;
import com.das.common.constant.EtcConstant;
import com.das.common.exception.DasException;
import com.das.redis.DasJedis;
import com.das.service.lock.LockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* @Author liangmy
* @Date 2019/10/29
*/
@Service
@Slf4j
public class LockServiceImpl implements LockService {
@Autowired
private DasJedis dasJedis;
@Override
@Transactional(rollbackFor = Exception.class)
public Object doSomething2(Long carOwnerUserId, EtcConstant.UserMoneyConstant.ModifyMoneyProgress strategy) {
String key = EtcConstant.getKey(EtcConstant.UserMoneyConstant.modifyMoneyRedisKey, carOwnerUserId);
for (int i = 0; i < 3; i++) {
Boolean setnxResult = dasJedis.setnx(key, String.valueOf(System.currentTimeMillis() + EtcConstant.UserMoneyConstant.timeout));
if (setnxResult) {
// 1.1获取锁成功
// 2. 重置 分布锁 的过期时间
dasJedis.expire(key, EtcConstant.UserMoneyConstant.timeout);
// 3. 执行业务逻辑
if (null != strategy) {
try {
Object obj = strategy.progress();
return obj;
} catch (Exception e) {
throw DasException.internalError(e, e.getMessage());
} finally {
// 4. 释放锁
dasJedis.del(key);
}
}
} else {
// 获取锁失败,尝试重新获取分布锁
String lockValueA = dasJedis.get(key);
if (StringUtils.isNotBlank(lockValueA) && System.currentTimeMillis() > Long.valueOf(lockValueA)) {
// 当前时间大于分布锁设置的超时时间,说明可以获取分布锁
String lockValueB = dasJedis.getset(key, String.valueOf(System.currentTimeMillis() + EtcConstant.UserMoneyConstant.timeout));
if (StringUtils.isBlank(lockValueB) || StringUtils.equals(lockValueA, lockValueB)) {
// B is null 说明在 get 和 getset 的过程中,没有进程修改closeOrderScheduledRedisKey已经过期, lock 是可以获取的。
// A == B 说明在get 和 getset 的过程中,没有进程修改closeOrderScheduledRedisKey 对应的 值 ,即 lock 是可以获取的。
dasJedis.expire(key, EtcConstant.UserMoneyConstant.timeout);
if (null != strategy) {
try {
Object obj = strategy.progress();
return obj;
} catch (Exception e) {
throw DasException.internalError(e, e.getMessage());
} finally {
// 4. 释放锁
dasJedis.del(key);
}
}
}
}
}
try {
int nextInt = new Random().nextInt(1000 * 2);
log.info("获取独占锁失败, 尝试{}毫秒后重试!", nextInt);
TimeUnit.MILLISECONDS.sleep(nextInt);
} catch (InterruptedException e) {
throw DasException.getLockFail(e, e.getMessage());
}
}
throw DasException.getLockFail(null, "获取锁失败, 请稍后重试!");
}
}
啦啦啦
分布式锁服务实现
本文介绍了一个基于Redis的分布式锁服务实现,通过使用setnx和expire命令确保锁的互斥性和时效性,支持业务逻辑的原子操作,并在锁超时或获取失败时提供了重试机制。
622

被折叠的 条评论
为什么被折叠?



