标签:finally dex call callback red get service ogg 单位
public interface DistributedLock { /** * 加锁 * @param lockKey 锁定的key * @param lockSeconds 锁定时间(单位:秒),超过该锁定时间会自动释放锁,可能会导致并发问题。 * @param expirySeconds 本次获取锁请求失效时间(单位:秒) * @param sleepMillisecond 本次获取锁失败,等到多少毫秒再次尝试获取(单位:毫秒) * @return 返回值大于0,则说明获取到锁,调用者需要保留该值,并在解锁时传入。 */ public Long lock(String lockKey,long lockSeconds, long expirySeconds, int sleepMillisecond); /** * 解锁 * @param lockKey 锁定的key */ public void unlock(String lockKey,long lockValue); }
import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import com.msxf.boot.redis.lock.DistributedLock; @Service("redisDistributedLock") public class RedisDistributedLockImpl implements DistributedLock { private static final Logger LOG = LoggerFactory.getLogger(RedisDistributedLockImpl.class); /** * 锁定超时时间60秒, 单位毫秒, 意味着加锁期间内执行完操作 如果未完成会自动过期释放锁,造成并发问题。 */ private static final long DEFAULT_LOCK_TIMEOUT = 60 * 1000; @Autowired protected StringRedisTemplate stringRedisTemplate; @Override public Long lock(String lockKey, long lockSeconds, long expirySeconds, int sleepMillisecond) { Long lockVal = 0L; long currMs = System.currentTimeMillis(); if (lockSeconds > 0L) { lockSeconds = lockSeconds * 1000; } else { lockSeconds = DEFAULT_LOCK_TIMEOUT; } while (true) { Long nextmin = getNextMin(); boolean lockResult = stringRedisTemplate.execute(new RedisCallback<Boolean>() { @Override public Boolean doInRedis(RedisConnection connection) throws DataAccessException { return connection.setNX(lockKey.getBytes(), String.valueOf(nextmin).getBytes()); } }); if (lockResult) {// 获得锁 LOG.debug("+++key:{} lock success", lockKey); stringRedisTemplate.expire(lockKey, lockSeconds, TimeUnit.MILLISECONDS); // 设置超时时间,释放内存 lockVal = nextmin; break; } else { // 调用get String lockTimeObj = stringRedisTemplate.opsForValue().get(lockKey); // redis里的时间 if (null != lockTimeObj) { Long ts = Long.valueOf(lockTimeObj); long nowTs = System.currentTimeMillis(); if (nowTs - ts >= 0) {// 锁已经失效 // 调用getset,获取旧值,写入新值,获取不到值为null long nextminVal = getNextMin(); String lockTimeObj1 = stringRedisTemplate.opsForValue().getAndSet(lockKey, String.valueOf(nextminVal)); if (null == lockTimeObj1 || lockTimeObj.equals(lockTimeObj1)) { stringRedisTemplate.expire(lockKey, lockSeconds, TimeUnit.MILLISECONDS); // 设置超时时间,释放内存 lockVal = nextminVal; break; } } } if (lockVal == 0L) { if (checkTimeout(currMs, expirySeconds)) { break; } sleep(sleepMillisecond); } } } return lockVal; } @Override public void unlock(String lockKey, long lockValue) { if (lockValue <= 0L) { return; } String objVal = stringRedisTemplate.opsForValue().get(lockKey); if (objVal != null && objVal.equals(String.valueOf(lockValue))) { stringRedisTemplate.delete(lockKey); // 删除键 LOG.debug("+++key:{} release success", lockKey); } } private boolean checkTimeout(long currMs, long expirySeconds) { return (System.currentTimeMillis() - currMs) > (expirySeconds * 1000); } private long getNextMin() { return System.currentTimeMillis() + 60000; } private void sleep(int ms) { try { if (ms <= 0) { ms = 50; } Thread.sleep(ms); } catch (InterruptedException e) { } } }
//lockKey String lockKey = "lockKey"; //key //获取到锁,则锁定30秒 long lockSeconds = 30; //请求200秒如果还没获取到锁就超时返回 long expirySeconds = 0; //未获取到锁,则休息30毫秒然后重试,直到expirySeconds过期 int sleepMillisecond = 30; //获取锁 long lockVal = redisDistributedLock.lock(lockKey, lockSeconds, expirySeconds, sleepMillisecond); //获取锁成功 if(lockVal > 0L){ try{ //执行逻辑 }catch (Exception e){
}finally{ //释放锁 redisDistributedLock.unlock(lockKey, lockVal); } }else{ //获取锁失败 } }
标签:finally dex call callback red get service ogg 单位
原文地址:https://www.cnblogs.com/aaronzheng/p/12106064.html