业务场景:分布式服务场景下的前后端分离,业务数据库表属性字段有唯一索引校验,前端多次调用服务,并同时传入相同参数,由于分布式服务的特性,且并没有设置访问服务的时权重或顺序,所以可能会导致多个服务保存数据库表时唯一索引校验错误。
实现思路:使用分布式锁进行控制,即通过redis控制在同一时间点内只能有一个进行中的操作。
1) setNx() 方法;
2) incr() 方法。
实现代码:
/**
* 尝试获取分布式锁(解决不可控因素导致“死锁”版)
* @paramkeyConstant 锁Key
* @param lockTime 超期时间
* @return 是否获取成功
*/
public boolean getLock(String keyConstant, int lockTime) {
Jedis jedis = null;
try {
jedis = redisWrapper.getResource();
String result = jedis.set(keyConstant, UUID.randomUUID().toString(), SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, lockTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
} catch (Exception e) {
logger.error("RedisUtil.getLock method.failed", e);
return false;
}finally {
redisWrapper.closeConnection(jedis);
}
}
ps:使用完redis以后,执行closeConnection(jedis)方法,否则会导致redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool异常,这是因为这个锁的粒度比较重,一旦业务代码出现异常,该锁不会自动释放,而是不断尝试获取该锁,导致快速消耗Redis连接池中的链接,在高并发场景下,导致由于无法获得redis链接而抛出异常,所以无论是否出现异常都需要释放redis链接,保证Redis连接池中一直有可用连接。
以此为笔记,有不足指出希望各位大佬多多指点。