Redis實現訪問頻率控制

2021-08-28 01:59:45 字數 1754 閱讀 4533

現在系統中由於各種需要,經常遇到一種場景:需要限定每個ip位址每分鐘最大訪問次數類似的需求。下面是使用redis實現范文頻率限制的一種方式。

場景:要限制每分鐘每個使用者最多只能訪問100個頁面。

思路:1. 對每個使用者使用乙個名為「rate.limiting:使用者ip」的字串型別鍵;

2. 每次使用者訪問,使用incr命令遞增該鍵的鍵值

3. 如果遞增後的值是1(第一次訪問頁面),則同時還要設定該鍵的生存時間為1分鐘

4. 這樣每次訪問頁面時都讀取該鍵的鍵值,如果超過了100就表明該使用者的訪問頻率超過了限制

上述流程的偽**如下:

$iskeyexists = exists rate.limiting:$ip

if $iskeyexists is 1

$times = incr rate.limiting:$ip

if $times > 100

print 訪問頻率超過了限制,請稍後再試

exit

else

incr rate.limiting:$ip

expire $keyname, 60

上面的這段**存在乙個不太明顯的問題:加入程式執行完倒數第二行後,因為某種原因突然退出了,沒能夠為該鍵值設定生存時間,那麼該鍵會永久存在,導致使用對應ip的使用者最多只能訪問系統100次,除非管理員手動刪除該鍵。這是乙個很嚴重的問題,但是可以結合redis的事務功能解決該問題,修改後的偽**如下:

$iskeyexists = exists rate.limiting:$ip

if $iskeyexists is 1

$times = incr rate.limiting:$ip

if $times > 100

elsee

expire $keyname, 60

exec

訪問頻率限制到此基本上已經實現,但是仍然有細節地方可以改進。

場景:乙個使用者在1分鐘的第1秒訪問了1次系統,在同一分鐘的最後1秒訪問了99次;又在下一分鐘的第一秒訪問了100次系統,這種情況使用者實際上在2秒內訪問了199次系統,這與每個使用者每分鐘只能訪問100次的限制的差距較大。

儘管這種情況比較極端,但是在一些場合中還是需要粒度更小的控制方案。

問題解決思路:如果要精確的保證每分鐘最多訪問100次,需要記錄下每次訪問的時間。因此對每個使用者,我們使用乙個列表型別的鍵來記錄他最近100次訪問時間,一旦鍵中的元素超過100個,就判斷時間最早的元素距離現在的時間是否小於1分鐘。如果是則表示最近1分鐘內的訪問次數超過了100次;如果不是就講現在的時間加入到列表中,同時把最早的元素刪除。

上述流程的偽**如下:

$listlength = llen rate.limiting:$ip

if $listlength < 100

lpush rate.limiting:$ip, now()

else

$time = lindex rate.limiting:$ip, -1

if now() - $time < 60

print 訪問頻率超過了限制,請稍後再試

else

lpush rate.limiting:$ip, now()

ltrim rate.limiting:$ip, 0, 99

上述**中用now()函式獲得當前的unix時間。由於需要記錄每次訪問的時間,所以當要限制「單位時間最多訪問n次」 時,如果n的數值越大,此方法占用的儲存空間就越多,實際使用時還需要開發者自己去權衡。除此之外,該方法也會出現競態條件,使用時請注意。

使用者訪問頻率控制的redis模擬實現

使用者訪問頻率控制的redis模擬實現 場景 限制使用者 1分鐘內登入不超過10次 模擬實現1 原理 利用 key的存活時間內進行判斷使用者登入次數。模擬實現 127.0.0.1 6379 clear 127.0.0.1 6379 set user1 1 ok127.0.0.1 6379 expir...

WebApi介面訪問頻率控制的實現

關於限流的文章,內還是有挺多的。本文做了乙個基於filter限流的例子,算是對webapithrottle使用的乙個具體的例項。1 使用nuget,對webapi專案新增webapithrottle的引用 2 進行註冊,一般是在webapiconfig的register方法裡新增,如下 1 conf...

WebApi介面訪問頻率控制的實現

關於限流的文章,內還是有挺多的。本文做了乙個基於filter限流的例子,算是對webapithrottle使用的乙個具體的例項。1 使用nuget,對webapi專案新增webapithrottle的引用 2 進行註冊,一般是在webapiconfig的register方法裡新增,如下 1 conf...