LUA Scripting
LUA脚本
redis-py supports the EVAL, EVALSHA, and SCRIPT commands. However, there are a number of edge cases that make these commands tedious to use in real world scenarios. Therefore, redis-py exposes a Script object that makes scripting much easier to use.
redis-py支持EVAL,EVALSHA和脚本命令。然而,有许多边界情况,使这些命令乏味在真实世界的场景中使用。因此,redis-py暴露一个脚本对象,使脚本更容易使用
To create a Script instance, use the register_script function on a client instance passing the LUA code as the first argument. register_script returns a Script instance that you can use throughout your code.
创建一个脚本实例,使用register_script函数在客户端实例中,LUA代码作为第一个参数传递。register_script返回一个脚本实例,在你的代码中可以继续使用实例操作
The following trivial LUA script accepts two parameters: the name of a key and a multiplier value. The script fetches the value stored in the key, multiplies it with the multiplier value and returns the result.
下面简单LUA脚本接受两个参数:一个关键的名称和一个乘数的值。脚本获取存储在关键的价值,使其与乘数的值并返回结果。
>>> r = redis.StrictRedis()
>>> lua = """
... local value = redis.call('GET', KEYS[1])
... value = tonumber(value)
... return value * ARGV[1]"""
>>> multiply = r.register_script(lua)
multiply is now a Script instance that is invoked by calling it like a function. Script instances accept the following optional arguments:
这个脚本实例现在可以使用,需要传递下面的参数
keys: A list of key names that the script will access. This becomes the KEYS list in LUA.
传递到脚本的关键字列表,在LUA中是KEYS
args: A list of argument values. This becomes the ARGV list in LUA.
参数列表,会是LUA中的ARGV
client: A redis-py Client or Pipeline instance that will invoke the script. If client isn't specified, the client that intiially created the Script instance (the one that register_script was invoked from) will be used.
redis-py客户端或管道实例将调用脚本。如果客户端没有指定,就是默认的。
Continuing the example from above:
继续上面的例子
>>> r.set('foo', 2)
>>> multiply(keys=['foo'], args=[5])
10
The value of key 'foo' is set to 2. When multiply is invoked, the 'foo' key is passed to the script along with the multiplier value of 5. LUA executes the script and returns the result, 10.
Script instances can be executed using a different client instance, even one that points to a completely different Redis server.
>>> r2 = redis.StrictRedis('redis2.example.com')
>>> r2.set('foo', 3)
>>> multiply(keys=['foo'], args=[5], client=r2)
15
The Script object ensures that the LUA script is loaded into Redis's script cache. In the event of a NOSCRIPT error, it will load the script and retry executing it.
Script objects can also be used in pipelines. The pipeline instance should be passed as the client argument when calling the script. Care is taken to ensure that the script is registered in Redis's script cache just prior to pipeline execution.
>>> pipe = r.pipeline()
>>> pipe.set('foo', 5)
>>> multiply(keys=['foo'], args=[5], client=pipe)
>>> pipe.execute()[True, 25]
Sentinel support
redis-py can be used together with Redis Sentinel to discover Redis nodes. You need to have at least one Sentinel daemon running in order to use redis-py's Sentinel support.
Connecting redis-py to the Sentinel instance(s) is easy. You can use a Sentinel connection to discover the master and slaves network addresses:
>>> from redis.sentinel import Sentinel
>>> sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
>>> sentinel.discover_master('mymaster')('127.0.0.1', 6379)
>>> sentinel.discover_slaves('mymaster')[('127.0.0.1', 6380)]
You can also create Redis client connections from a Sentinel instnace. You can connect to either the master (for write operations) or a slave (for read-only operations).
>>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
>>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
>>> master.set('foo', 'bar')
>>> slave.get('foo')'bar'
The master and slave objects are normal StrictRedis instances with their connection pool bound to the Sentinel instance. When a Sentinel backed client attempts to establish a connection, it first queries the Sentinel servers to determine an appropriate host to connect to. If no server is found, a MasterNotFoundError or SlaveNotFoundError is raised. Both exceptions are subclasses of ConnectionError.
When trying to connect to a slave client, the Sentinel connection pool will iterate over the list of slaves until it finds one that can be connected to. If no slaves can be connected to, a connection will be established with the master.
See Guidelines for Redis clients with support for Redis Sentinel to learn more about Redis Sentinel.
Scan Iterators
The *SCAN commands introduced in Redis 2.8 can be cumbersome to use. While these commands are fully supported, redis-py also exposes the following methods that return Python iterators for convenience: scan_iter, hscan_iter, sscan_iter and zscan_iter.
>>> for key, value in (('A', '1'), ('B', '2'), ('C', '3')):
... r.set(key, value)>>> for key in r.scan_iter():
... print key, r.get(key)A 1B 2C 3