如何在Redis中实现多用户安全的线性同余生成器?

我使用线性同余生成器(http://en.wikipedia.org/wiki/Linear_congruential_generator)生成暴露给用户的 ID。

nextID = (a * LastID + c) % m

现在我想在 Redis 中实现 LCGs。 以下是问题所在:在 Redis 之外获取当前 ID 并生成下一个 ID 不是多用户安全的。 Redis 有 2 个可用于简单计数器的命令:INCRBY 和 INCRBYFLOAT,但不幸的是,Redis 并不原生支持模操作。 目前我唯一看到的方法是使用 EVAL 命令并编写一些 lua 脚本。

更新1:

一些类似于

INCRBY LCG_Value ((LCG_Value*a+c)%m)-LCG_Value

的 lua 模拟似乎是实现此目的的一种简洁方法。

点赞
用户1114486
用户1114486

使用服务器端的 Lua 脚本很可能是最简单和更高效的方法。

现在也可以使用 Redis 基本操作使用多个/执行块来完成。以下是伪代码:

while not successful:
   WATCH LCG_Value
      $LastID = GET LCG_value
      $NextID = (a*$LastID+c)%m
   MULTI
      SET LCG_value $NextID
   EXEC

当然,它比以下 Lua 脚本不够高效:

# 设置初始值
SET LCG_value 1

# 执行带有 a、c 和 m 参数的 LCG_value 上的 Lua 脚本
EVAL "local last = tonumber(redis.call( 'GET', KEYS[1]));
      local ret = (last*ARGV[1] + ARGV[2])%ARGV[3];
      redis.call('SET',KEYS[1], ret);
      return ret;
" 1 LCG_value 1103515245 12345 2147483648

注意:整个脚本执行是原子的。请参见 EVAL 文档。

2013-06-11 06:59:44