redis setnx 防重复提交“不生效”

setnx广泛用于防重复提交、超时重试的场景来保证幂等。

主要利用setnx特性,设置一个特定的key和一个合适的过期时间,成功则执行业务逻辑。执行完毕会在finally代码块中删掉此key,防止抛出异常的情况长时间持有此redis锁。

用法还是很简单的,但一些同学还会粗心的犯错,这也是code review中特别要注意的点。

问题代码

    public void test() {
        try {
            if (!redis.setnx(key, 5)) {
                return resultError("访问频繁,请稍后重试");
            }

            //业务代码...
        } finally {
            redis.del(key);
        }
    }

分析

并发情况下达不到预期效果,如:

  1. 线程一执行setnx成功,正在执行业务代码
  2. 线程二执行setnx失败,接着执行了finally代码块,把锁删掉了
  3. 线程三此时再去执行setnx时就会成功

解决

setnx应放在try外层

    public void test() {
        if (!redis.setnx(key, 5)) {
            return resultError("访问频繁,请稍后重试");
        }

        try {
            //业务代码...
        } finally {
            redis.del(key);
        }
    }
posted @ 2022-07-27 19:01  keqinglee  阅读(684)  评论(0编辑  收藏  举报