redis setnx问题

发布于 2022-09-03 09:06:04 字数 545 浏览 14 评论 0

说明我的需求:实现一个用户操作次数的计数器,没有数据时先从数据库查询,有并发的情况。
代码如下:
value是从数据库查询的,问题是:这样岂不是每次都查询数据库了?如何做到key不存在就查询数据库,存在了就不用查询数据库了?

if (redisConnection.setNX(key, value) == 1) {
    return value;
} else {
    return redisConnection.incr(key);
}

下面的代码在并发情况下还是会多次查询数据库的

if (redisConnection.exists(key)) {
    redisConnection.incr(key);
} else {
    if (redisConnection.setNX(key, value) == 1) {//并发的情况下这里还是会执行多次
        return value;
    } else {
        return redisConnection.incr(key);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉城 2022-09-10 09:06:04

自己琢磨的一个方法,让key和exists过期时间保持一致就行,不知道还有没有更好的方法

String key = "key";
String exists = key + ":exists";
if (redisConnection.setNX(exists, "1") == 1) {
    redisConnection.setNX(key, value);
    return value;
} else {
    return redisConnection.incr(key);
}
阳光下的泡沫是彩色的 2022-09-10 09:06:04
jedis.set(key, value, nxxx, expx, time) 

如果想把逻辑弄成redis的一个事务做完,弄个lua来做

离鸿 2022-09-10 09:06:04

我的理解是,应该没有完美的方案

  1. 如果用@twayne 的方案,在并发的情况下回出现另外一个线程执行到redisConnection.incr(key),但是redisConnection.setNX(key, value)这步并没有完成

  2. 用@yuwenbao的lua脚本解决方案,因为你在整个事务中设计到了本地数据库的操作,所以用lua脚本也很难解决

解决方案,其实你问题中第二种方案,可以解决绝大多数问题

if (redisConnection.exists(key)) {
    redisConnection.incr(key);
} else {
    //① 这里会出现并发数据库查询value
    if (redisConnection.setNX(key, value) == 1) {//并发的情况下这里还是会执行多次
        return value;
    } else {
        return redisConnection.incr(key);
    }
}

唯一的一个问题就是,在首次更新value的时候,可能会在①处出现并发查询数据库的情况.这种方式可以满足绝大多数业务了,如果楼主觉得在首次更新value的时候并发查询数据库,压力实在是太大(一般可能性很小,除非你的业务规模很大),那么只能用分布式锁来觉得了,在①处加一个基于key的分布式锁,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文