Redis應用之[限制訪問頻率]
我們知道當網站的訪問量突然很大的時候肯定會對伺服器造成影響,甚至無法訪問,如果是正常的訪問那麼很好說明業務量增大可以考慮系統的擴充套件,但是如果是搜尋引擎爬蟲頻繁訪問或是一些惡意訪問,那這時候我們就應該限制這些訪問的訪問次數。redis剛好可以解決這個問題
Redis實現限制訪問頻率
1.實現訪問一
限制每個使用者每分鐘最多隻能訪問100個頁面。實現思路:key使用有"rate.limiting:IP",value使用數值,使用者每次訪問將value的值通過INCR命令自增1.如果自增後的值是1同時設定過期時間為1分鐘。這樣使用者每次訪問的時候都讀取該鍵的值,如果超過了100就表明該使用者的訪問頻率超過了限制,需要提示使用者稍後訪問。且該鍵每分鐘會自動被刪除。所以下一分鐘又會重新計算,也就達到了限制訪問頻率的目的。

程式碼邏輯:
String key = "rage.limiting:"+ip; // 判斷key是否存在 int flag = exists(key);// key rate.limiting:192.168.88.60 if(flag == 1){ // key 存在 自增1 int count = incr(key); if(count > 100){ // 超過限制 log.info("訪問頻率超過了限制,請稍後重試"); return ; } }else{ // key 不存在 multi(); // 開啟事務 incr(key); // key不存在自增1 值為1 expire(key,60); // 設定過期時間 exec(); // 提交事務 }
2.實現方式二
實現方式一其實還有個問題,比如如果使用者第一分鐘的訪問了99次,前面58秒訪問了9次,後面1秒訪問了90次,然後使用者後一秒也訪問了99次,而後一分鐘的第一秒訪問了90次,後面的58秒訪問了9次,這樣按照上面的演算法是沒有問題的,但是這種極端情況大家還是可以發現問題的。

解決方法:先將上面案例中的100次調整為10次便於在次場景中描述,要精確的保證同一個使用者每分鐘最多訪問10次,需要記錄下來使用者每次訪問的時間。因此對每個使用者我們使用一個List列表型別的鍵來記錄他最近10次訪問的時間,一旦鍵中的元素超過10個,就判斷最早的元素距離現在的時間是否小於1分鐘。如果是表示使用者最近1分鐘訪問次數超過了10次,如果不是就將現在的時間加入到佇列中,同時把最早的元素刪除。

邏輯程式碼
String key = "rate.limiting:"+IP; int listLength = llen(key); if(listLength < 10){ lpush(key,new()); }else{ long time = lindex(key,-1); if(now()-time < 60){ log.info("訪問頻率超過了限制,請稍後再試"); }else{ lpush(key,now); ltrim(key,0,9); } }