Ruby on rails redis rb仅在设置关键点时增加多个
我想在redis中存储一个计数。我只想在密钥存在时增加计数。我做错了什么?exists返回false并且正在执行incrRuby on rails redis rb仅在设置关键点时增加多个,ruby-on-rails,ruby,ruby-on-rails-4,redis,race-condition,Ruby On Rails,Ruby,Ruby On Rails 4,Redis,Race Condition,我想在redis中存储一个计数。我只想在密钥存在时增加计数。我做错了什么?exists返回false并且正在执行incr key = "blah" result = REDIS_DB.multi do exists = REDIS_DB.exists(key) REDIS_DB.incr(key) if exists end # result: [false, 1] 我是redis的新手。我只是看书。据我所知,multi中的命令应该一个接一个地执行 Rails 4.0.2、Redis
key = "blah"
result = REDIS_DB.multi do
exists = REDIS_DB.exists(key)
REDIS_DB.incr(key) if exists
end
# result: [false, 1]
我是redis的新手。我只是看书。据我所知,multi中的命令应该一个接一个地执行
Rails 4.0.2、Redis 3.0.1(Redis的Ruby客户端库)这可能就是我想要的:
result = REDIS_DB.watch(key) do
if REDIS_DB.exists(key)
REDIS_DB.incr(key)
else
REDIS_DB.unwatch
end
end
从Redis2.6开始,lua脚本就受到支持,因此也可以使用以下代码
redis_script = <<SCRIPT
local exists = redis.call('exists', KEYS[1])
if exists == 1 then
return redis.call('incr', KEYS[1])
end
SCRIPT
# returns incremented value if key exists otherwise nil
REDIS_DB.eval(redis_script, ['testkey'])
将打印
<Redis::Future [:exists, "tesstt"]>
那么,result:[false,1]
来自哪里呢
这是因为REDIS\u DB.multi
在生成块(并缓存命令)后,最终将其转换为REDIS查询并发送给REDIS,REDIS最终运行它并返回结果。因此,您的代码实际上转换为以下查询
MULTI
exists 'blah'
incr 'blah'
EXEC
并在一次对redis的调用中一起提交,该调用为存在返回0
(将redis rb
转换为布尔值false
),为增量返回1
需要注意的一点是,这种行为是可以理解的,因为如果您将每个命令单独发送给redis,那么redis本身将在MULTI
之后对所有命令进行排队,并在接收到对exec
的调用时对其进行处理
exists = REDIS_DB.exists(key) # returns Redis::Future object
REDIS_DB.incr(key) if exists # evaluates to true as value of exists is an object
MULTI
exists 'blah'
incr 'blah'
EXEC