redis限速器設計(不使用lua指令碼及事物)

2021-12-29 21:27:33 字數 1206 閱讀 2542

首先想到的就是使用redis中的incr方法,在redis的官方文件中尋找到了乙個示例

function limit_api_call(ip)

ts = current_unix_time()

keyname = ip+":"+ts

current = get(keyname)

if current != null and current > 10 then

error "too many requests per second"

endif current == null then

multi

incr(keyname, 1)

expire(keyname, 1)

exec

else

incr(keyname, 1)

endperform_api_call()

但這個指令碼對我來說有兩個缺點 1 我的限速器並不是限制一台機器的速度,而是限制整個集群的速度,所以在判斷了限速的key的長度之後,會有很多的機器執行incr動作 2 公司dba不支援使用事物看了文件中後面限速器的實現,要麼使用事物,要麼使用lua指令碼(公司也不支援lua,因為lua也是事務性的,而公司是sharding的redis集群),全部被否定

看來只能多檢測一會了程式流程圖,假設我們1s中之內只能請求20次

步驟 1 使用incr命令得到乙個值 2 判斷值是否為1,為1則說明此次獲得是key值失效之後第一次進行incr操作,這次操作需要將key設定超時時間。但是我們這裡並沒有使用事務支援,當程式執行到檢測value是1,還沒有進行expire操作的時候,機器down機了,那麼程式就只能請求20次了,所以在每次得到value值之後,與10進行取餘操作,若是10的倍數,則進行檢測,如果沒有設定超時時間,則進行設定 3 判斷value值是否是小於20,如果小於等於20,我們認為在規定的時間內,這個執行緒獲得了鎖,如果大於20,我們認為沒有獲得鎖,sleep一段時間後繼續請求鎖。

這樣,我們就實現了乙個沒有使用事物,lua指令碼的限速器

如果此方案有什麼錯誤,或者有更加優雅的方案,還請各位多多指教。

注意流程圖中值為1和為10的倍數都需要檢測ttl key,這裡可以做個優化,只有10的倍數的值的進行ttl key 檢測操作,1的話直接expire key。

redis示例 限速器,計時器

incr key 將key中儲存的數字值增一。如果key不存在,那麼key的值會先被初始化為0,然後再執行 incr 操作。如果值包含錯誤的型別,或字串型別的值不能表示為數字,那麼返回乙個錯誤。本操作的值限制在 64 位 bit 有符號數字表示之內。這是乙個針對字串的操作,因為 redis 沒有專用...

LINQ to SQL 不使用O R設計器建表物件

namespace linqtosql column public string companyname column public string contactname column public string contacttitle column public string address c...

LINQ to SQL 不使用O R設計器建表物件

namespace linqtosql column public string companyname column public string contactname column public string contacttitle column public string address c...