2016-01-06 4 views
2

Я просто наткнулся на интересное поведение окружающей среды Lua в Redis:Redis Lua Script math.random

У меня есть сценарий Lua делает несколько простых наборов операций и генерирующий уникальную метку времени, как идентификатор в конце сценария - использовать Redis в качестве временной метки оракула - как это:

... 
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)) 

Теперь version что-то вроде этого: 145209287564117083 состоящих из метки времени и пяти случайных цифр в конце - по крайней мере, вот что я подумал.

Что происходит на самом деле, что пять случайных цифры в конце (порожденного math.random(99999) не являются случайными вообще, но всегда цифры 17083, независимо от того, как часто выполняется скрипт.

Для меня это было не так уж много (потому что я могу добавить случайные цифры после возвращения скрипта), но я не ожидал такого поведения, и поэтому мне нужно было найти некоторое время, чтобы найти ошибку.

Я надеюсь, что эта информация может сэкономить некоторое время.

+0

Попробуйте '' 'math.randomseed (os.time())' '' в начале скрипта. – warspyking

+1

@warspyking - не будет работать, потому что в песочнице Redis Lua нет библиотеки 'os' lib, и в любом случае Redis 'math.random' спроектирован таким образом, чтобы при использовании репликации на основе сценариев были получены одинаковые значения (единственный режим, доступный до v3.2) –

+0

@Itamar Ну, это действительно может быть все, что постоянно меняется. Не обязательно '' 'os.time'''. – warspyking

ответ

2

Я думаю, что причиной такого поведения является то, что Redis пытается t o держать людей от генерации случайных ключей внутри скрипта, потому что в репликации эти сценарии отправляются на реплики (а не сами данные). Таким образом, генерация случайных ключей может привести к непоследовательным репликам.

Вот почему после звонка redis.call('TIME') в сценарий не разрешены записи в Redis.

Я предполагаю, что среда Lua в Redis всегда возвращает то же число от math.random() по той же причине.

+1

Очень верно. Однако с версии 3.2 существует новый режим репликации, который меняет это поведение: http://redis.io/commands/eval#selective-replication-of-commands –

2

Если вы вызываете сценарий lua, самое лучшее, что нужно сделать, это передать в качестве аргумента сценария. Это позволяет полностью исключить redis.call («ВРЕМЯ»), а затем вы можете установить семя с текущим временем.

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)) 

Это также позволяет избежать любых будущих проблем с репликацией, поскольку все экземпляры получат одинаковые параметры и генерируют один и тот же результат.

+2

Хотя ОП на самом деле не задал вопрос, я думаю это лучший ответ на вопрос «как я должен генерировать псевдослучайные числа в сценарии redis lua?». –

Смежные вопросы