【问题标题】:Deleting multiple keys in redis-rb删除 redis-rb 中的多个键
【发布时间】:2011-08-29 01:16:27
【问题描述】:

在 Rails 应用程序中使用 redis-rb,以下内容不起作用:

irb> keys = $redis.keys("autocomplete*")
=> ["autocomplete_foo", "autocomplete_bar", "autocomplete_bat"]
irb> $redis.del(keys)
=> 0

这很好用:

irb> $redis.del("autocomplete_foo", "autocomplete_bar")
=> 2

我是否遗漏了一些明显的东西?来源只是:

# Delete a key.
def del(*keys)
  synchronize do
    @client.call [:del, *keys]
  end
end

在我看来应该可以将数组传递给它...?

【问题讨论】:

    标签: ruby redis


    【解决方案1】:

    对 splat 运算符工作方式的一点编码探索:

    def foo(*keys)
      puts keys.inspect
    end
    
    >> foo("hi", "there")
    ["hi", "there"]
    
    >> foo(["hi", "there"])
    [["hi", "there"]]
    
    >> foo(*["hi", "there"])
    ["hi", "there"]
    

    因此,传入常规数组将导致该数组作为单个项目进行评估,因此您可以在方法内的数组中获得一个数组。如果在调用方法时以 * 开头:

    $redis.del(*keys)
    

    这让方法知道解包/不接受任何进一步的参数。所以这应该可以解决你遇到的问题!

    只是为了进一步澄清,这是可行的:

    >> foo("hello", *["hi", "there"])
    

    这会导致语法错误:

    >> foo("hello", *["hi", "there"], "world")
    

    【讨论】:

    • 删除多个(数千个)键导致:SystemStackError:堆栈级别太深,在此问题github.com/redis/redis-rb/issues/122中报告。这个是直接在客户端调用方法解决的:$redis.client.call [:del, *keys]
    【解决方案2】:

    对于我正在开发的 Rails 应用,我需要测试加载和卸载 redis 数据的结果。

    命名空间由环境决定,避免与开发交互。这很好用。

    def clear_redis_cache
      keys = $redis.keys "#{namespace}*"
      $redis.del(*keys) unless keys.empty?
    end
    

    【讨论】:

    【解决方案3】:

    使用scan_each 返回的枚举器可以更好地实现这一点。

    scan_each(match: 'autocomplete_*').each do |key|
      del key
    end
    

    这不会一次将所有匹配的键加载到内存中,因此不会受到本地内存的限制。

    【讨论】:

      猜你喜欢
      • 2020-10-13
      • 1970-01-01
      • 2018-04-09
      • 2015-09-10
      • 2022-01-12
      • 2019-12-31
      • 2017-04-02
      • 2018-03-10
      • 2020-04-19
      相关资源
      最近更新 更多