"限流"這種事情即使在生活中也很常見,比如我們銀行辦理業務,銀行不可能給去的所有人同時服務,因為櫃檯就那麼幾個。所以可能一次只給5個人辦理業務,其他的人只能在後面排隊;再比如打飯等等,也是一樣的道理。因為能提供服務的數量有限,所以必須要通過限流的方式。
這裡提一下微博,微博因為哪個明星出軌了,或者哪個明星戀愛官宣了,導致伺服器掛掉不止一次了。這裡也是因為人數驟增導致的,當然這只是表層的原因,關於背後詳細的架構、以及為什麼這種情況一出現微博就又可能會掛掉的原因,我可能會在其它的系列中說,這裡先不談,今天主要是談限流。關於限流所用的演算法有兩個:漏桶演算法、令牌演算法。漏桶演算法的靈感源於漏斗,如下圖所示:
首先,如果讓你實現乙個限流的演算法你要怎麼做呢?我們可以規定乙個時間,比如60s,在60s之內只能處理100個請求,如果超過了100個,那麼就將多餘的請求丟棄掉。但是這樣存在乙個問題:如果在10s內請求就已經100個,因此剩餘的50s只能把再來的請求給丟棄掉。但是這100個請求又花了10s中就全部處理完了,那麼剩餘的40s做什麼?顯然這樣做就存在這資源浪費的情況。於是可能有人想到使用佇列的方式,設定佇列的容量為100,任務處理完了就出隊,然後等待處理的入隊,這樣就保證了資源的利用率,恭喜你,漏桶演算法就是這麼做的。
說實話從漏斗本身上想,也能猜出使用的是佇列,一邊進一邊出。無論漏斗上面的水流有多少,漏斗下面的水都是均勻流出的。如果上面的水流量大於下面流出的水流量的話,那麼漏斗會慢慢變滿;反之,漏斗永遠不會被裝滿,並一直流出。
漏桶演算法的實現步驟是:先宣告乙個佇列儲存請求,這個佇列相當於漏斗,當佇列容量滿了之後,就放棄新來的請求。然後執行的話則是通過宣告另乙個執行緒定期從佇列中獲取乙個或多個任務執行,這樣就實現了漏桶演算法。
漏桶演算法可以在程式語言這一層實現。令牌演算法指的是有乙個程式以某種恆定的速度生成令牌,並存入令牌桶中,而每個請求需要先獲取令牌才能執行,如果沒有獲取到令牌的話則放棄執行。如下圖所示:
這種令牌演算法,我們也可以使用python的threading模組來實現。
在redis4.0,已經為我們實現了限流功能,並提供了原子的限流指令,再加上redis這個天生的分布式程式就可以完美地實現限流了。
實現限流需要使用redis提供的redis-cell模組,該模組使用的便是漏桶演算法,使用起來也很簡單,通過cl.throttle即可,但是我們需要提前安裝。
> cl.throttle mylimit 15 30 60
1)(integer)0 # 0 表示獲取成功,1 表示拒絕
2)(integer)15 # 漏斗容量
3)(integer)14 # 漏斗剩餘容量
4)(integer)-1 # 被拒絕之後,多長時間之後再試(單位:秒)-1 表示無需重試
5)(integer)2 # 多久之後漏斗完全空出來
其中 15 為漏斗的容量,30 / 60s 為漏斗的速率。通過redis-cell,我們則可以實現分布式原子級別的限流,更詳細的使用可以檢視官網。 Redis 如何實現限流功能?
限流 這種事在生活中很常見,比如逢年過節時景點的限流,還有工作日的車輛單雙號限流等,有人可能會問為什麼要限流?我既然買了車子你還不讓我上路開?還有我倒景點買了門票,景點不是能賺更多的錢嗎?為什麼要限流呢?其實限流的主要目的就是為了保證整個系統的正常執行,比如以車輛限流為了,它的作用主要有兩個,乙個是...
10 Redis 雜湊物件
本文內容均來自 redis設計與實現 一書 雜湊物件的編碼可以是ziplist或者hashtable。ziplist編碼的雜湊物件使用壓縮列表作為底層實現。每當有新的鍵值對要加入到雜湊物件時,程式會先將儲存了鍵的壓縮列表節點推入到壓縮列表的表尾,再將儲存了值的壓縮列表節點推入到壓縮列表的表尾。儲存了...
Redis篇 1 0 Redis簡單介紹
1.redis 介紹 redis 是完全開源免費的,遵守bsd協議,是乙個高效能的key value資料庫。redis 與其他 key value 快取產品有以下三個特點 redis的優點 1.具有複雜的資料型別,支援string,list,set,zset,hash等資料型別 2.高效能 redi...