6

Is it possible to have one Redis Lua script hit more than one database? I currently have information of one type in DB 0 and information of another type in DB 1. My normal workflow is doing updates on DB 1 based on an API call along with meta information from DB 0. I'd love to do everything in one Lua script, but can't figure out how to hit multiple dbs. I'm doing this in Python using redis-py:

lua_script(keys=some_keys,
           args=some_args,
           client=some_client)

Since the client implies a specific db, I'm stuck. Ideas?

4

1 回答 1

7

将相关数据放在不同的 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 脚本都必须在最后重置当前数据库(即使在以前的错误的情况下),因此它使复杂的脚本变得繁琐和尴尬。

于 2013-05-29T07:20:59.250 回答