Author:赵志乾
Date:2020-04-05
Declaration:All Right Reserved!!!
《小并发量、低延时、通用场景下的接口并发锁》给出的并发锁方案主要用于解决多个请求并发调用时,只有单个调用能够抢到锁并完成业务流程的执行。为此,其在业务代码执行前进行抢锁,执行完或异常终止时显示释放锁,以便后续请求能够顺利执行。
现在我们要面临一个新的场景,某类修改接口针对一个用户或用户的一笔订单在一定时间间隔内只能够调用一次。比如:某个系统使用单条记录存储最新的交易信息,每次请求该接口都会生成新的交易信息并对上次的交易信息进行覆写。为了防止前端页面连续发起有一定时间间隔的两次请求,接口并发锁需要强制锁一定的时间间隔,也就是在一次请求有效发生时,会拒绝固定时间间隔内该用户再次调用该接口。
控制接口调用间隔的接口并发锁实现方案也比较简单,不过需要预先评估好间隔时间,并且时间间隔要大于业务代码执行耗时,否则会出现临界区同时运行两个甚至更多个线程。代码如下,实质就是加锁后依靠锁的失效时间来控制调用时间间隔。
// Jedis封装加锁和释放锁操作
public boolean getLock(String key,int expireTime){
String key = "my:lock:" + key;
String result = jedis.set(key, String.valueOf(System.currentTimeMillis()), "NX", "EX",expireTime);
return (null != result && "OK".equalsIgnoreCase(result)) ? true : false;
}
public void releaseLock(String key) {
if (StringUtils.isNotBlank(key)) {
String key = "my:lock:" + key;
jedis.del(key);
}
}
// 接口并发控制模板
public Object operate(String userId,Object param){
String lockKey = "operate:"+userId;
boolean lockResult = jedis.getLock(lockKey,10);
if(!lockResult){
// 返回系统繁忙
}
// 业务代码
}