python - redis中如何根据key的存在设置hash key过期时间
问题描述
我想设置一些哈希键的过期时间,如果是第一次设置密钥,我希望设置一个过期时间,否则我更喜欢保持第一次设置的过期时间。
由于有大量的哈希键,我更喜欢在管道中进行,但是下面的函数效果不佳。
该行pipe.exists(hkey)
返回一个管道的 obj,它始终为 True,因此无论哈希键是否存在,if 子句总是转到一个部分。
我的问题是:有没有一种方法可以根据带有管道的哈希键的存在来设置哈希键的到期?
def test1(hkey, v):
with r.pipeline() as pipe:
# tmp = pipe.exists(hkey)
# pipe.exists(hkey) is a pipe obj, which is always True,
# this line not work as expected and the two lines below it will never be excuted.
if not pipe.exists(hkey):
pipe.hset(hkey, v, v)
pipe.expire(hkey, 3600)
else:
# no matter whether the hash key is exist or not, the if else statment always goes to this line.
pipe.hset(hkey, v, v)
pipe.execute()
解决方案
您无法使用管道实现这一点,因为在整个管道执行之前您永远不知道密钥是否存在。相反,您可以使用Lua 脚本来完成这项工作:
local key = KEYS[1]
local field = ARGV[1]
local value = ARGV[2]
local ttl = ARGV[3]
local exist = redis.call('exists', key)
redis.call('hset', key, field, value)
if exist == 0 then
redis.call('expire', key, ttl)
end
检查这个以了解如何使用 redis-py 运行 Lua 脚本。然后使用管道运行脚本以减少RTT
.
更新
如果你坚持使用WATCH
来做这项工作,你可以试试下面的代码:
with r.pipeline() as pipe:
while 1:
try:
pipe.watch(hkey)
exist = pipe.exists(hkey)
pipe.multi()
if not exist:
pipe.hset(hkey, v, v)
pipe.expire(hkey, 3600)
else:
pipe.hset(hkey, v, v)
pipe.execute()
break;
except WatchError:
continue
推荐阅读
- laravel - Laravel:更改数据库中时间戳的名称
- c++ - 是shared_future
条件变量的合法替代品? - python - Numpy 全局保持维度
- javascript - 什么是“PropTypes.oneOf”的 TypeScript 等效项(将变量限制为值的子集)
- google-cloud-platform - 如何让 glusterfs 在集群升级中存活下来
- angular - Datepicker (matCalendar) angular2 应该在滚动页面时移动
- scala - 如何在 slick 中创建多个主键?
- ubuntu - Portaudio 选择用于捕获的输入设备
- javascript - 如何从另一个页面触发视觉力页面中的事件
- angularjs - Grunt usemin,获取压缩文件的最终路径以允许预加载