美文网首页
redisTemplate高并发计数器和分布式锁

redisTemplate高并发计数器和分布式锁

作者: 松松土_0b13 | 来源:发表于2019-07-12 19:54 被阅读0次

在分布式系统中,redis应用非常广泛

redis做高并发计数器

业务中常常有要求,譬如一个手机号一分钟限制发送1条短信,我们可以用Redis的Incr自增命令可以轻松实现以上需求

String redisKey = "SMS_PHONE_LIMIT_" + smsPhone;
long count = redisTemplate.opsForValue().increment(redisKey, 1);
if (count == 1) {
  //设置有效期一分钟
  redisTemplate.expire(redisKey, 60, TimeUnit.SECONDS);
}
if (count > 1) {
  resultMap.put("retCode", "-1");     
  resultMap.put("retMsg", "每分钟只能发送一次短信");
  return;
}

还有一个比较重要的场景就是登录错误次数太多,锁定账号5分钟

String redisKey = "USER_LOGIN_LIMIT_";
long count = redisTemplate.opsForValue().increment(redisKey, 1);
//登录错误次数超过5次,则锁定用户3分钟
if (count < 6) {
  //成功
//redisTemplate.delete(redisKey);

  //失败
  redisTemplate.expire(redisKey, 180, TimeUnit.SECONDS);
  return ResultUtils.error(-1,"账号密码错误,剩余" + (mustCount-count) + "次机会");
}else {
  long time = redisTemplate.getExpire(redisKey);
  return ResultUtils.error(-1,"登录失败次数过多,锁定账号"+ time + "秒");
}

分布式锁

上面的计时器也可以做分布式锁,不过在锁定时间很短的时候或者网络延迟的时候,做计时器做分布锁可能会出行死锁

long LOCK_EXPIRE = 1000 * 60;
String lock = "LOCK_PREFIX" + key;
// 利用lambda表达式
Boolean lockFlag = (Boolean) redisTemplate.execute(new RedisCallback() {
    @Override
    public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
        long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;
        Boolean acquire = redisConnection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());
        if (acquire) {
            return true;
        } else {
            byte[] value = redisConnection.get(lock.getBytes());
            if (Objects.nonNull(value) && value.length > 0) {
                long expireTime = Long.parseLong(new String(value));
                if (expireTime < System.currentTimeMillis()) {
                    // 如果锁已经过期
                    byte[] oldValue = redisConnection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());
                    // 防止死锁
                    return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();
                }
            }
        }
        return false;
    }
});
return ResultUtils.success(lockFlag);

相关文章

网友评论

      本文标题:redisTemplate高并发计数器和分布式锁

      本文链接:https://www.haomeiwen.com/subject/nzidkctx.html