如何用Redis實現乙個指定時間的限速器

2021-09-10 05:54:07 字數 2324 閱讀 9652

使用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分鐘內只能接受乙個使用者不超過10次的請求,這時我們可以將使用者的ip位址設定為key,使用者每次時程式去redis中獲取該key的值,如果大於等於10則返回錯誤,否則給key對應的value+1即可,如果value為0,那麼再將該key設定1分鐘的過期時間。

但是現在有乙個需求,我們可以在乙個指定的時間內給使用者推送一條訊息,但是要求使用者每分鐘內只能接受1條訊息,每小時內接受的訊息不超過5條,一天內接受的訊息不超過10條。

比如,我現在向這個介面提交了一條資料,要求在2019-11-11 11:11:11時向乙個使用者傳送一條資料,那麼當我再提交一條資料,要求在2019-11-11 11:11:12是向同樣的使用者傳送一條資料,那麼介面就會返回錯誤。

此時,僅使用incr是無法滿足該需求的。

使用set或者zset將使用者的ip+傳送日期作為key,傳送時間轉換為當天的秒數作為value,插入到set或者zset中,每次向使用者提交資訊時,可以獲取到set中的所有傳送時間,然後再一一比對,如果不滿足條件就返回錯誤。

以下是偽**實現

function

ratelimit

(ip,sendtime)

return

false

}

以下是golang的實現

func

ratelimit

(ctx context.context, ip string

, sendtime time.time)

error

zerostr := sendtime.

format

("2006-01-02"

) key := ip + zerostr

zero,

_:= time.

parse

("2006-01-02"

, zerostr)

// 獲取傳送時間距當天時間的秒數

second :=

int(sendtime.

sub(zero)

.seconds()

) ress, err := cache.

smembers

(ctx, key)

if err !=

nil// 處理返回引數,將string轉換為int

var sends [

]int

for_

, v :=

range ress }if

len(sends)

>=

10var expire bool

iflen

(sends)==0

var hourcount int

for_

, s :=

range sends

if math.

abs(

float64

(second-s)

)<

3600

}if hourcount >

5// 非同步更新

gofunc()

t.expire

( key,

int64

(ttl))}

t.commit()

}()return

nil}

以上就可以實現乙個指定時間的限速器。

如何用兩個棧實現乙個佇列

問題 如何用兩個棧實現乙個對列的功能?思路 從棧a入佇列,從棧b出佇列。佇列的2個最重要的操作,入佇列,出佇列。入佇列 從棧a入佇列。出佇列 分兩種情況 如果棧b不為空,直接彈出。如果棧b為空,將棧a中的資料全部彈入棧b中,再從棧b彈出資料 實現如下 queuebystack.cpp 定義控制台應用...

如何用C 實現乙個Whois的查詢

什麼是whois 簡單來說,whois就是乙個用來查詢網域名稱是否已經被註冊,以及註冊網域名稱的詳細資訊的資料庫 如網域名稱所有人 網域名稱註冊商 網域名稱註冊日期和過期日期等 通過whois來實現對網域名稱資訊的查詢 什麼去查詢whois?whois的查詢其實也是蠻簡單的,就是利用socket去連...

如何用Redis實現搜尋介面

大家如果是做後端開發的,想必都實現過列表查詢的介面,當然有的查詢條件很簡單,一條 sql 就搞定了。但有的查詢條件極其複雜,再加上庫表中設計的各種不合理,導致查詢介面特別難寫,然後加班什麼的就不用說了 不知各位有沒有這種感受呢 下面以乙個例子開始,這是某購物 的搜尋條件,如果讓你實現這樣的乙個搜尋介...