在一些简单的业务场景下,其实不用考虑锁的重入、重试等问题,也很少需要考虑Redis主从切换,分布式锁失效。
那么一种最简单的分布式锁实现,其实就是Redis setNX, 其实已经能满足大多数场景了
直接上代码:
public class RedisDistributedLock {
private static final String KEY_PREFIX = "dl";
/**
* @param userId uid
* @param lockBizType 业务类型,
*/
public static DistributedLock getDLockWithRetry(long userId, int lockBizType) {
String key = getKey(userId, lockBizType);
DistributedLock distributedLock = null;
try {
long expireMillis = 10000; //给个过期时间
distributedLock = new DistributedLock(key, expireMillis);
distributedLock.acquireLock();
} catch (Exception e) {
// log
}
return distributedLock;
}
public static void releaseDLock(DistributedLock lock) {
if (lock == null || lock.isFailure()) {
return;
}
MoreFunctions.runCatching(lock::releaseLock);
}
private static String getKey(long userId, int lockBizType) {
return Joiner.on("_").join(KEY_PREFIX, lockBizType.name(), userId);
}
/**
* 分布式锁
*/
public static class DistributedLock {
private String key;
private String value;
private Jedis jedis = new Jedis("xxx", 6668);
private long expireMillis;
private boolean success = false;
public DistributedLock(String key, long expireMillis) {
this.key = key;
this.value = String.valueOf(System.currentTimeMillis());
this.expireMillis = expireMillis;
}
public String getKey() {
return key;
}
public boolean isSuccess() {
return success;
}
public boolean isFailure() {
return !isSuccess();
}
public String getValue() {
return value;
}
public boolean acquireLock() {
String result = this.jedis
.set(this.key, this.value, "NX", "PX", this.expireMillis);
this.success = "OK".equalsIgnoreCase(result);
return this.success;
}
public void releaseLock() {
this.jedis.del(this.key);
}
}
}
使用锁:
RedisDistributedLock.DistributedLock lock = null;
try {
lock =RedisDistributedLock
.getDLockWithRetry(userId, 1);
if (!lock.isSuccess()) {
// 打点日志 + 抛异常
}
return doXxx(userId);
} finally {
if (Objects.nonNull(lock)) {
RedisDistributedLock.releaseDLock(lock);
}
}
转载请注明:汪明鑫的个人博客 » 一个Redis简易的分布式锁实现
说点什么
您将是第一位评论人!