使用多个DB与一个Redis Lua脚本?

时间:2013-05-28 21:52:14

标签: redis

是否可以让一个Redis Lua脚本命中多个数据库?我目前在DB 0中有一种类型的信息和DB 1中另一种类型的信息。我的正常工作流程是基于API调用以及来自DB 0的元信息对DB 1进行更新。我喜欢在一个中做所有事情Lua脚本,但无法弄清楚如何打多个dbs。我在Python中使用redis-py:

进行此操作
lua_script(keys=some_keys,
           args=some_args,
           client=some_client)

由于客户端暗示了一个特定的数据库,我被卡住了。想法?

1 个答案:

答案 0 :(得分:6)

将相关数据放在不同的Redis数据库中通常是错误的想法。与通过关键命名约定定义命名空间相比几乎没有任何好处(没有关于安全性,持久性,到期管理等的额外粒度)。主要缺点是客户端必须手动处理正确数据库的选择,这对于同时定位多个数据库的客户来说是容易出错的。

现在,如果你仍想使用多个数据库,有一种方法可以使用redis-py和Lua脚本。

redis-py没有定义SELECT命令的包装器(通常用于切换当前数据库),因为底层的线程安全连接池实现。但没有什么能阻止你从Lua脚本中调用SELECT。

考虑以下示例:

$ redis-cli
SELECT 0
SET mykey db0
SELECT 1
SET mykey db1

以下脚本显示来自同一客户端连接的2个数据库中mykey的值。

import redis

pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)

lua1 = """
   redis.call("select", ARGV[1])
   return redis.call("get",KEYS[1])
"""
script1 = r.register_script(lua1)

lua2 = """
   redis.call("select", ARGV[1])
   local ret = redis.call("get",KEYS[1])
   redis.call("select", ARGV[2])
   return ret
"""
script2 = r.register_script(lua2)

print r.get("mykey")
print script2( keys=["mykey"], args = [1,0] )
print r.get("mykey"), "ok"
print
print r.get("mykey")
print script1( keys=["mykey"], args = [1] )
print r.get("mykey"), "misleading !!!"

脚本lua1是天真的:它只是在返回值之前选择给定的数据库。它的用法具有误导性,因为在执行后,与连接关联的当前数据库已更改。不要这样做。

脚本lua2要好得多。它将目标数据库和当前数据库作为参数。它确保在脚本结束之前重新激活当前数据库,以便在连接上应用的下一个命令仍在正确的数据库中运行。 不幸的是,没有命令猜测Lua脚本中的当前数据库,因此客户端必须系统地提供它。请注意Lua脚本必须在最后重置当前数据库(即使出现上一个错误),因此它会使复杂的脚本变得麻烦和笨拙。