Redis呼叫lua生成驗證碼
阿新 • • 發佈:2018-11-24
場景:
通過微信公眾號拿驗證碼在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)
這樣一個秒數可以實現承載更多。