Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails redis rb仅在设置关键点时增加多个_Ruby On Rails_Ruby_Ruby On Rails 4_Redis_Race Condition - Fatal编程技术网

Ruby on rails redis rb仅在设置关键点时增加多个

Ruby 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

我想在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 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