redis 的 incr 的过期时间问题

2019-12-13 13:57:39 +08:00
 90928yao

incr 过期时间的设置有点纠结 现在俩种方案

第一个

value = get(key)
if (value == null) {
	incr(key)
    expire(key)
} else{
		incr(key)
}

还有就是 用一次设置一次

incr(key)
expire(key)

那个好一点

11660 次点击
所在节点    程序员
15 条回复
lhx2008
2019-12-13 14:02:55 +08:00
inc 有返回值的
optional
2019-12-13 14:07:19 +08:00
lua
90928yao
2019-12-13 14:08:51 +08:00
@lhx2008 靠返回值判断 多线程会有问题的吧
lhx2008
2019-12-13 14:09:15 +08:00
@90928yao 你现在这个才有多线程问题
codergrowing
2019-12-13 14:12:42 +08:00
我一般都是用的第二种方案,省去了判断,少了一步操作。代价只是 key 被多缓存一段时间多占用一点内存而已。
90928yao
2019-12-13 14:16:25 +08:00
@lhx2008 想通了 谢谢
swulling
2019-12-13 14:16:29 +08:00
先不考虑多线程问题,你这两个方案不等价。
BBCCBB
2019-12-13 14:17:24 +08:00
if value == null :
set(key, 1, ttl=xxx)
else:
incr(key)


这样行不行, set 命令支持直接设置 ttl
BBCCBB
2019-12-13 14:18:48 +08:00
incr 和 expire 分两步执行是有问题的, 网络抖动等会导致可能设置不到 ttl, 就完蛋了
swulling
2019-12-13 14:30:02 +08:00
如果希望用方案 2,加一个 multi exec 事务就行了。我个人更喜欢事务,非不得已不用 lua
rrfeng
2019-12-13 14:59:24 +08:00
incr 不存在的自动置 0 并递增
multi incr expire exec
qxg
2019-12-13 15:28:45 +08:00
刚好有这个需求,目前的方案是采用 multi incr + expire,但是耗时比单独 incr 高很多,所以后续优化考虑在本地做一个 map 的缓存,第一次 incr 的时候使用 multi incr + expire,并将 key 存到本地的 map 里,后续只需要判断下本地的 map 里是否存在该 key,如果存在,只需执行 incr 即可。
tr0uble
2019-12-13 16:24:15 +08:00
ok = set key 1 nx ex 10
if ok :
count =1
else:
count = incr key
hipop
2021-03-16 10:20:08 +08:00
lua 脚本

count = incr key
if (count == 1) then
expire key 10000
end
chengzi
2022-07-28 19:34:05 +08:00
```
value = get(key)
if (value == null) {
incr(key)
expire(key) // incr(), expire() 需要保证原子性, 需要用 multi(), exec() 包一下
} else{
incr(key) // get(), incr() 中间是有时间差的, 如果 incr() 时 key 已经过期, 就会出现 key 无法过期释放问题
}
```
最简单的方案是用 lua 脚本, 或者参考 redis 官网文档里的 RPUSHX 方案 ( https://redis.io/commands/incr/)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/628724

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX