redis翻译_redislua脚本(八)

2015-07-24 07:47:25 · 作者: · 浏览: 21
d没有被调用,每次调用math.random都生成相同的数字序列。

However the user is still able to write commands with random behavior using the following simple trick. Imagine I want to write a Redis script that will populate a list with N random integers.

?

但是,使用以下简单的技巧,用户仍然能够编写与随机行为的相关的命令。想象一下,我想写一个Redis的脚本,将N个随机整数填充一个list。

?

I can start with this small Ruby program: 我可以用这个小Ruby程序启动

?

require 'rubygems'
require 'redis'

r = Redis.new

RandomPushScript = <
  
    0) do
        res = redis.call('lpush',KEYS[1],math.random())
        i = i-1
    end
    return res
EOF

r.del(:mylist)
puts r.eva l(RandomPushScript,[:mylist],[10,rand(2**32)])
  
Every time this script executed the resulting list will have exactly the following elements:

?

每次执行这个脚本列表将会有确切的以下要素:

?

> lrange mylist 0 -1
 1) "0.74509509873814"
 2) "0.87390407681181"
 3) "0.36876626981831"
 4) "0.6921941534114"
 5) "0.7857992587545"
 6) "0.57730350670279"
 7) "0.87046522734243"
 8) "0.09637165539729"
 9) "0.74990198051087"
10) "0.17082803611217"
In order to make it a pure function, but still be sure that every invocation of the script will result in different random elements, we can simply add an additional argument to the script that will be used in order to seed the Lua pseudo-random number generator. The new script is as follows:

?

?

为了使脚本成为一个纯粹的函数,但仍然确保每一次调用有不同的随机元素,我们可以给脚本添加额外的参数作为Lua伪随机数字生成器的种子。修改的脚本如下:
 
 
RandomPushScript = <
  
    0) do res = redis.call('lpush',KEYS[1],math.random()) i = i-1 end return res EOF r.del(:mylist) puts r.eva l(RandomPushScript,1,:mylist,10,rand(2**32))
  
 
 
 
 

What we are doing here is sending the seed of the PRNG as one of the arguments. This way the script output will be the same given the same arguments, but we are changing

one of the arguments in every invocation, generating the random seed client-side. The

seed will be propagated as one of the arguments both in the replication link and in the

Append Only File, guaranteeing that the same changes will be generated when the AOF is reloaded or when the slave processes the script.

我们这里做的是发送PRNG的种子作为参数之一,这种方式给定相同的参数输出也将相同,但是每次调用时我都可以在客户端这边改变随机种子。当AOF重载或者从服务器处理脚本时,种子作为复制链接和附加文档的参数传输,保证生成相同的变化。

Note: an important part of this behavior is that the PRNG that Redis implements asmath.random and math.randomseed is guaranteed to have the same output regardless of the architecture of the system running Redis. 32-bit, 64-bit, big-endian and

little-endian systems will all produce the same output.

注意:上面的做法最重要的是Redis 的PRNG实现 math.random和math.randomseed能保证Redis运行底层系统都有相同的输出。32-bit, 64-bit, big-endian 和little-endian系统都将产生相同的输出。

?

Global variables protection 全局变量的保护

Redis scripts are not allowed to create global variables, in order to avoid leaking data into the Lua state. If a script needs to maintain state between calls (a pretty uncommon need) it should use Redis keys instead.
为了Lua状态避免数据泄露,Redis脚本不允许创建全局变量。如果脚本调用过程需要维护全局状态变量应该使用Redis 的key代替。 When global variable access is attempted the script is terminated and eva l returns with an error:
当企图去使用全局变量时,脚本将被终止,并且eva l将返回一个错误。
redis 127.0.0.1:6379> eva l 'a=10' 0
(error) ERR Error running script (call to f_933044db579a2f8fd45d8065f04a8d0249383e57): user_script:1: Script attempted to create global variable 'a'
Accessing a non existing global variable generates a similar error. 使用不存在的全局变量的错误。
Using Lua debugging functionality or other approaches like altering the meta table used to implement global pro