1. 程式人生 > >Redis呼叫lua生成驗證碼

Redis呼叫lua生成驗證碼

場景:

​ 通過微信公眾號拿驗證碼在APP上繫結,為了防止重複,嘗試使用reids-lua的方法實現此功能

以下是 php 呼叫 redis.eval 方法傳入的 lua 方法,當然這只是修改後的,保留了主要邏輯

local time = 1542363164 // unix時間戳
local code = redis.call('get',1)
if (code) then 
    return code
else 
    local i = 0
    while(true) do 
        math.randomseed(time+i)
        code = math.random(100000,999999)
        if (1 == redis.call('setnx',1,code)) then 
            return code
        end
    end
end
return 0

乍一看沒問題,但是要知道 redis 在建立 lua 環境的時候,第6步是這樣的(具體為什麼是這樣的 https://redisbook.readthedocs.io/en/latest/feature/scripting.html#id2)

用 Redis 自己定義的隨機生成函式,替換 math 表原有的 math.random 函式和 math.randomseed 函式,新的函式具有這樣的性質:每次執行 Lua 指令碼時,除非顯式地呼叫 math.randomseed ,否則 math.random 生成的偽隨機數序列總是相同的。

也就是說,如果不改變randomseed,random返回的序列會總是相同的,所以會拿到同樣的值。

這就需要考慮一個場景:

​ 一秒內有600個使用者同時訪問, randomseed 會一直增加到time+600,會把未來10分鐘的時間戳都佔用。一秒內請求越多,佔用未來時間戳越多,迴圈時間就越長。

​ 就是一個秒數只能承載一個使用者的驗證碼,想來想去,決定使用拼接的方式實現 math.randomseed(time .. i) 這樣一個秒數可以實現承載更多。