redis?實現限速器的幾種方式。
GET + INCR + EXPIRE
先獲取?key?的當前值,如果沒有超出限制再執行?INCR?增1,如果?key?不存在,使用?redis?的事務初始化?key?和過期時間。
(推薦:redis視頻教程)
偽代碼:
count?=?redis.GET(key) if?redis?return?nil?{ ??redis.MULTI ?? redis.INCR(key) ?? redis.EXPIRE(key,?expire_time) ??redis.EXEC ??count?=?1 } if?count?>?limit?{ ??return?超出限制 }?else?{ ??redis.INCR(key) }
高并發下的問題:
如果同時10個并發程序執行?GET?返回了?nil, 那么這10個并發程序都會執行?redis?的事務將?key?增一,但每個程序的?count?值都為1,如果?limit?設置的值小于10,那么真正執行的程序就超過限制了。如果執行完事務后再查一次?redis?賦值給?count,那么每個程序可能都會返回10,從而沒有程序能夠繼續執行。
key?已經存在的情況下,先?GET?后?INCR?的邏輯也可能會出現實際執行的程序數多于?limit?的情況。
INCR + EXPIRE
先?INCR, 如果值為1說明是?key?剛設置的,此時再執行?EXPIRE
偽代碼:
count?=?redis.INCR(key) if?count?==?1?{ ??redis.EXPIRE(key,?expire_time) } if?count?>?limit?{ ??return?超出限制 }
慎用
如果?INCR?之后程序掛掉了,沒有執行?EXPIRE, 那么這個?key?就沒有過期時間了,具體的影響視需求而定。
lua腳本
local?current current?=?redis.call("incr",KEYS[1]) if?tonumber(current)?==?1?then ????redis.call("expire",KEYS[1],1) end
更多redis知識請關注redis視頻教程欄目。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END
喜歡就支持一下吧
相關推薦