Reputation: 3048
I just came across an interesting behavior of the Lua environment in Redis:
I have a Lua script doing some simple set operations and generating a unique timestamp like id at the end of the script - to use Redis as a timestamp oracle - like this:
...
local time = redis.call('TIME')
local millis = (tonumber(time[1]) * 1000) + math.floor(tonumber(time[2]) / 1000)
local version = string.format("%.0f",mills) .. string.format("%05d", math.random(99999))
Now version
is something like this: 145209287564117083
consisting of a timestamp and five random digits at the end - at least thats what I thought.
What actually happens is, that the five random digits at the end (generated by math.random(99999)
are not random at all, but always the digits 17083
, no matter how often the script is executed.
For me this was not a big deal (because I can append the random digits after the script returns), but I did not expect this behavior and therefore needed quite some time to find my bug.
I hope this information can save some time.
Upvotes: 4
Views: 2835
Reputation: 116
If you are calling a lua script, the best thing to do is pass in the time as a script argument. This allows you to avoid redis.call("TIME") completely, and then you can set the seed with the current time.
local time = ARGV[1];
math.randomseed(time);
local millis = (tonumber(time[1]) * 1000) + math.floor(tonumber(time[2]) / 1000)
local version = string.format("%.0f",mills) .. string.format("%05d", math.random(99999))
This also avoids any future issues w/ replication because all instances will receive the same parameters and generate the same output.
Upvotes: 5
Reputation: 3048
I think the reason for this behavior is that Redis tries to keep people from generating random keys inside of the script, because in replication these script are shipped to the replicas (instead of the data itself). Thus generating random keys could lead to inconsistent replicas.
Thats why after the call redis.call('TIME')
no writes to Redis are allowed in the script.
My guess is that the Lua environment in Redis always returns the same number from math.random()
for the same reason.
Upvotes: 3