Redis調用lua生成驗證碼
阿新 • • 發佈:2018-11-24
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生成驗證碼