1. 程式人生 > >Redis調用lua生成驗證碼

Redis調用lua生成驗證碼

see 修改 循環 保留 定義 方法 lse dom http

場景:

? 通過微信公眾號拿驗證碼在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) 這樣一個秒數可以實現承載更多。

Redis調用lua生成驗證碼