我可以从redis服务器的当前系统时间设置redis值吗?

时间:2013-06-20 23:52:09

标签: redis

也就是说,我想附加一个类似于:

的排序集

“set1” - > [1371772258,1371772265,1371772299等]

但我不想从我的服务器发送时间值。我想从一个服务器的时钟获得一致的时间戳,服务器redis正在运行。

2 个答案:

答案 0 :(得分:3)

此解决方案适用于Redis版本2.6.0

如果Redis提供Lua os.time功能,可能会有一个简单的解决方案,但事实并非如此。

所以我发明了一些黑客。我们以后可以设置EXPIREAT,然后使用TTL我们将知道当前的unix时间戳。

这是概念证明。当然,您至少可以进行2次优化:在redis数据库中设置一次future密钥,然后在lua脚本中读取它的ttl,显然使用evalsha代替eval

<强> zaddts.lua

local future_ts, cur_ts, zkey, zmember

future_ts = 2000000000
redis.call('setnx', 'future', 1)
redis.call('expireat', 'future', future_ts)
cur_ts = future_ts - redis.call('ttl', 'future')
zkey = KEYS[1]
zmember = KEYS[2]
return redis.call('zadd', zkey, cur_ts, zmember)

具有硬编码时间戳的oneliner示例:

return redis.call('zadd', KEYS[1], 2000000000 - redis.call('ttl', 'future'), KEYS[2])

示例-client.php

<?php
ini_set('display_errors', true);

$r = new Redis();
$r->connect('localhost');

$script = file_get_contents('zaddts.lua');

$r->eval($script, array('events', 'event1'), 2);
sleep(1);
$r->eval($script, array('events', 'event2'), 2);
print_r($r->zrange('events', 0, -1, $withscore = true));
/* Output:
Array
(
    [event1] => 1371777755
    [event2] => 1371777756
)
*/

UPD: [facepalm]我没有看到TIME命令。随着它,lua脚本变得更加简单:

<强> zaddts.lua

local time_full, time_sec, zkey, zmember

zkey = KEYS[1]
zmember = KEYS[2]

time_full = redis.call('time')
time_sec = tonumber(time_full[1])

return redis.call('zadd', zkey, time_sec, zmember)

UPD 2 :由于redis lua脚本限制(Scripts as pure functions),time调用的代码无效:

redis 127.0.0.1:6379> eval "return redis.call('zadd', 'events', redis.call('time')[1], 'some-event')" 0
(error) ERR Error running script (call to f_426eeadf424497fc04eb8f06efac0553f3212660): Write commands not allowed after non deterministic commands 

所以第一版代码(ttl)仍然有意义。

答案 1 :(得分:1)

您只需使用the TIME command(Redis 2.6提供)。它返回两个值:以秒为单位的纪元,以及微秒数。

您可以直接从应用程序中调用它。在这种情况下,将需要2次往返(一次执行TIME,一次更新zset)。