日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Python+redis通過限流保護高并發(fā)系統(tǒng)

瀏覽:28日期:2022-07-30 08:30:32

保護高并發(fā)系統(tǒng)的三大利器:緩存、降級和限流。那什么是限流呢?用我沒讀過太多書的話來講,限流就是限制流量。我們都知道服務(wù)器的處理能力是有上限的,如果超過了上限繼續(xù)放任請求進來的話,可能會發(fā)生不可控的后果。而通過限流,在請求數(shù)量超出閾值的時候就排隊等待甚至拒絕服務(wù),就可以使系統(tǒng)在扛不住過高并發(fā)的情況下做到有損服務(wù)而不是不服務(wù)。

舉個例子,如各地都出現(xiàn)口罩緊缺的情況,廣州政府為了緩解市民買不到口罩的狀況,上線了預(yù)約服務(wù),只有預(yù)約到的市民才能到指定的藥店購買少量口罩。這就是生活中限流的情況,說這個也是希望大家這段時間保護好自己,注意防護 :)

接下來就跟大家分享下接口限流的常見玩法吧,部分算法用python+redis粗略實現(xiàn)了一下,關(guān)鍵是圖解??!你品,你細品~

固定窗口法

固定窗口法是限流算法里面最簡單的,比如我想限制1分鐘以內(nèi)請求為100個,從現(xiàn)在算起的一分鐘內(nèi),請求就最多就是100個,這分鐘過完的那一刻把計數(shù)器歸零,重新計算,周而復(fù)始。

Python+redis通過限流保護高并發(fā)系統(tǒng)

偽代碼實現(xiàn)

def can_pass_fixed_window(user, action, time_zone=60, times=30): ''' :param user: 用戶唯一標識 :param action: 用戶訪問的接口標識(即用戶在客戶端進行的動作) :param time_zone: 接口限制的時間段 :param time_zone: 限制的時間段內(nèi)允許多少請求通過 ''' key = ’{}:{}’.format(user, action) # redis_conn 表示redis連接對象 count = redis_conn.get(key) if not count: count = 1 redis_conn.setex(key, time_zone, count) if count < times: redis_conn.incr(key) return True return False

這個方法雖然簡單,但有個大問題是無法應(yīng)對兩個時間邊界內(nèi)的突發(fā)流量。如上圖所示,如果在計數(shù)器清零的前1秒以及清零的后1秒都進來了100個請求,那么在短時間內(nèi)服務(wù)器就接收到了兩倍的(200個)請求,這樣就有可能壓垮系統(tǒng)。會導(dǎo)致上面的問題是因為我們的統(tǒng)計精度還不夠,為了將臨界問題的影響降低,我們可以使用滑動窗口法。

滑動窗口法

滑動窗口法,簡單來說就是隨著時間的推移,時間窗口也會持續(xù)移動,有一個計數(shù)器不斷維護著窗口內(nèi)的請求數(shù)量,這樣就可以保證任意時間段內(nèi),都不會超過最大允許的請求數(shù)。例如當前時間窗口是0s~60s,請求數(shù)是40,10s后時間窗口就變成了10s~70s,請求數(shù)是60。

時間窗口的滑動和計數(shù)器可以使用redis的有序集合(sorted set)來實現(xiàn)。score的值用毫秒時間戳來表示,可以利用當前時間戳-時間窗口的大小來計算出窗口的邊界,然后根據(jù)score的值做一個范圍篩選就可以圈出一個窗口;value的值僅作為用戶行為的唯一標識,也用毫秒時間戳就好。最后統(tǒng)計一下窗口內(nèi)的請求數(shù)再做判斷即可。

Python+redis通過限流保護高并發(fā)系統(tǒng)

偽代碼實現(xiàn)

def can_pass_slide_window(user, action, time_zone=60, times=30): ''' :param user: 用戶唯一標識 :param action: 用戶訪問的接口標識(即用戶在客戶端進行的動作) :param time_zone: 接口限制的時間段 :param time_zone: 限制的時間段內(nèi)允許多少請求通過 ''' key = ’{}:{}’.format(user, action) now_ts = time.time() * 1000 # value是什么在這里并不重要,只要保證value的唯一性即可,這里使用毫秒時間戳作為唯一值 value = now_ts # 時間窗口左邊界 old_ts = now_ts - (time_zone * 1000) # 記錄行為 redis_conn.zadd(key, value, now_ts) # 刪除時間窗口之前的數(shù)據(jù) redis_conn.zremrangebyscore(key, 0, old_ts) # 獲取窗口內(nèi)的行為數(shù)量 count = redis_conn.zcard(key) # 設(shè)置一個過期時間免得占空間 redis_conn.expire(key, time_zone + 1) if not count or count < times: return True return False

雖然滑動窗口法避免了時間界限的問題,但是依然無法很好解決細時間粒度上面請求過于集中的問題,就例如限制了1分鐘請求不能超過60次,請求都集中在59s時發(fā)送過來,這樣滑動窗口的效果就大打折扣。 為了使流量更加平滑,我們可以使用更加高級的令牌桶算法和漏桶算法。

令牌桶法

令牌桶算法的思路不復(fù)雜,它先以固定的速率生成令牌,把令牌放到固定容量的桶里,超過桶容量的令牌則丟棄,每來一個請求則獲取一次令牌,規(guī)定只有獲得令牌的請求才能放行,沒有獲得令牌的請求則丟棄。

Python+redis通過限流保護高并發(fā)系統(tǒng)

偽代碼實現(xiàn)

def can_pass_token_bucket(user, action, time_zone=60, times=30): ''' :param user: 用戶唯一標識 :param action: 用戶訪問的接口標識(即用戶在客戶端進行的動作) :param time_zone: 接口限制的時間段 :param time_zone: 限制的時間段內(nèi)允許多少請求通過 ''' # 請求來了就倒水,倒水速率有限制 key = ’{}:{}’.format(user, action) rate = times / time_zone # 令牌生成速度 capacity = times # 桶容量 tokens = redis_conn.hget(key, ’tokens’) # 看桶中有多少令牌 last_time = redis_conn.hget(key, ’last_time’) # 上次令牌生成時間 now = time.time() tokens = int(tokens) if tokens else capacity last_time = int(last_time) if last_time else now delta_tokens = (now - last_time) * rate # 經(jīng)過一段時間后生成的令牌 if delta_tokens > 1: tokens = tokens + tokens # 增加令牌 if tokens > tokens: tokens = capacity last_time = time.time() # 記錄令牌生成時間 redis_conn.hset(key, ’last_time’, last_time) if tokens >= 1: tokens -= 1 # 請求進來了,令牌就減少1 redis_conn.hset(key, ’tokens’, tokens) return True return False

令牌桶法限制的是請求的平均流入速率,優(yōu)點是能應(yīng)對一定程度上的突發(fā)請求,也能在一定程度上保持流量的來源特征,實現(xiàn)難度不高,適用于大多數(shù)應(yīng)用場景。

漏桶算法

漏桶算法的思路與令牌桶算法有點相反。大家可以將請求想象成是水流,水流可以任意速率流入漏桶中,同時漏桶以固定的速率將水流出。如果流入速度太大會導(dǎo)致水滿溢出,溢出的請求被丟棄。

Python+redis通過限流保護高并發(fā)系統(tǒng)

通過上圖可以看出漏桶法的特點是:不限制請求流入的速率,但是限制了請求流出的速率。這樣突發(fā)流量可以被整形成一個穩(wěn)定的流量,不會發(fā)生超頻。

關(guān)于漏桶算法的實現(xiàn)方式有一點值得注意,我在瀏覽相關(guān)內(nèi)容時發(fā)現(xiàn)網(wǎng)上大多數(shù)對于漏桶算法的偽代碼實現(xiàn),都只是實現(xiàn)了

根據(jù)維基百科,漏桶算法的實現(xiàn)理論有兩種,分別是基于 meter 的和基于 queue 的,他們實現(xiàn)的具體思路不同,我大概介紹一下。

基于meter的漏桶

基于 meter 的實現(xiàn)相對來說比較簡單,其實它就有一個計數(shù)器,然后有消息要發(fā)送的時候,就看計數(shù)器夠不夠,如果計數(shù)器沒有滿的話,那么這個消息就可以被處理,如果計數(shù)器不足以發(fā)送消息的話,那么這個消息將會被丟棄。

那么這個計數(shù)器是怎么來的呢,基于 meter 的形式的計數(shù)器就是發(fā)送的頻率,例如你設(shè)置得頻率是不超過 5條/s ,那么計數(shù)器就是 5,在一秒內(nèi)你每發(fā)送一條消息就減少一個,當你發(fā)第 6 條的時候計時器就不夠了,那么這條消息就被丟棄了。

這種實現(xiàn)有點類似最開始介紹的固定窗口法,只不過時間粒度再小一些,偽代碼就不上了。

基于queue的漏桶

基于 queue 的實現(xiàn)起來比較復(fù)雜,但是原理卻比較簡單,它也存在一個計數(shù)器,這個計數(shù)器卻不表示速率限制,而是表示 queue 的大小,這里就是當有消息要發(fā)送的時候看 queue 中是否還有位置,如果有,那么就將消息放進 queue 中,這個 queue 以 FIFO 的形式提供服務(wù);如果 queue 沒有位置了,消息將被拋棄。

在消息被放進 queue 之后,還需要維護一個定時器,這個定時器的周期就是我們設(shè)置的頻率周期,例如我們設(shè)置得頻率是 5條/s,那么定時器的周期就是 200ms,定時器每 200ms 去 queue 里獲取一次消息,如果有消息,那么就發(fā)送出去,如果沒有就輪空。

注意,網(wǎng)上很多關(guān)于漏桶法的偽代碼實現(xiàn)只實現(xiàn)了水流入桶的部分,沒有實現(xiàn)關(guān)鍵的水從桶中漏出的部分。如果只實現(xiàn)了前半部分,其實跟令牌桶沒有大的區(qū)別噢😯

如果覺得上面的都太難,不好實現(xiàn),那么我墻裂建議你嘗試一下redis-cell這個模塊!

redis-cell

Redis 4.0 提供了一個限流 Redis 模塊,它叫 redis-cell。該模塊也使用了漏斗算法,并提供了原子的限流指令。有了這個模塊,限流問題就非常簡單了。 這個模塊需要單獨安裝,安裝教程網(wǎng)上很多,它只有一個指令:

CL.THROTTLE

CL.THROTTLE user123 15 30 60 1▲ ▲ ▲ ▲ ▲| | | | └───── apply 1 operation (default if omitted) 每次請求消耗的水滴| | └──┴─────── 30 operations / 60 seconds 漏水的速率| └───────────── 15 max_burst 漏桶的容量└─────────────────── key “user123” 用戶行為

執(zhí)行以上命令之后,redis會返回如下信息:

> cl.throttle laoqian:reply 15 30 601) (integer) 0 # 0 表示允許,1表示拒絕2) (integer) 16 # 漏桶容量3) (integer) 15 # 漏桶剩余空間left_quota4) (integer) -1 # 如果拒絕了,需要多長時間后再試(漏桶有空間了,單位秒)5) (integer) 2 # 多長時間后,漏桶完全空出來(單位秒)

有了上面的redis模塊,就可以輕松對付大多數(shù)的限流場景了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標簽: Python 編程
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
丝袜诱惑一区二区| 欧美日本久久| 国产精品一级| 欧美日韩亚洲一区三区| 亚洲精品在线二区| 欧美综合社区国产| 亚洲人www| 日韩和欧美一区二区| 亚洲区国产区| 波多野结衣久久精品| 蜜桃视频在线网站| 国产96在线亚洲| 91亚洲国产成人久久精品| 精品三级av在线导航| 日韩视频网站在线观看| 日韩电影免费在线观看| 久久国产成人午夜av影院宅| 麻豆精品91| 欧美精品国产| 天堂中文在线播放| 亚洲欧美视频一区二区三区| 日本视频一区二区| 欧美二三四区| 日韩免费精品| 福利精品在线| 水野朝阳av一区二区三区| 亚洲一级少妇| 日韩一区免费| 亚洲91久久| 欧美午夜三级| 精品国产美女a久久9999| 久久国产中文字幕| 中文字幕一区二区av| 国产伦理久久久久久妇女| 久久久精品久久久久久96| 欧美亚洲三区| 蜜桃av一区二区在线观看| 日韩电影在线视频| 欧美亚洲网站| 免费国产自线拍一欧美视频| 日韩av有码| 日韩av中文字幕一区| 欧美日中文字幕| 美女av一区| 美国欧美日韩国产在线播放| 日韩国产欧美一区二区三区| 成人国产精品一区二区网站| 婷婷成人av| 午夜久久久久| 欧美影院三区| 日本韩国欧美超级黄在线观看| 国产精品久久久网站| 亚洲伊人影院| 日韩影院在线观看| 国产精品av久久久久久麻豆网| 国产激情在线播放| 成人日韩av| 久久影院午夜精品| 精品午夜视频| 精品视频久久| 国产欧美日韩在线一区二区| 蜜桃久久久久久| 日韩精品一区二区三区免费视频| 久久亚洲风情| 亚洲午夜国产成人| 亚洲精品成人一区| 亚洲精品激情| 青青青国产精品| 国产精品99久久免费观看| 国产日韩一区二区三免费高清| 91嫩草精品| 精品国产亚洲日本| 国产一区二区三区四区二区| 国产精品资源| 久久精品天堂| 国产精品久久久久久久久久白浆 | 婷婷精品在线观看| 亚洲免费毛片| 国产一区二区三区四区五区| 日韩精品dvd| 99久久激情| 综合欧美亚洲| 免费在线观看一区| 亚洲性色av| 久久爱www.| 最新国产精品久久久| 蜜桃传媒麻豆第一区在线观看| 91成人精品观看| 国产在线日韩精品| 香蕉成人久久| 日本蜜桃在线观看视频| 亚洲综合国产| 精品国产亚洲一区二区在线观看| 婷婷成人在线| 欧美日本精品| 成人亚洲一区二区| 黄色在线一区| 国产一区二区三区日韩精品| 91久久视频| 精品日韩一区| 日韩精品视频网站| 激情久久久久久久| 精品国产一区二| 日韩精品欧美成人高清一区二区| 涩涩av在线| 免费在线观看一区| 日韩国产成人精品| 视频一区视频二区在线观看| 国产精品巨作av| 日韩激情一二三区| 不卡一区2区| av一区在线| av日韩中文| 国产欧洲在线| 成人国产精品久久| 国产精品mm| 欧美精品二区| 国产精品亚洲综合久久| 亚洲精品人人| 一区二区三区国产在线| 亚洲自啪免费| 亚洲人成高清| 日韩精品看片| 九九久久婷婷| 久久免费黄色| 成人亚洲一区二区| 91亚洲成人| 亚洲日本网址| 制服诱惑一区二区| 美女日韩在线中文字幕| 三级亚洲高清视频| 婷婷综合福利| 久久丁香四色| 私拍精品福利视频在线一区| 日韩欧美精品一区| 成人污污视频| 天堂а√在线最新版中文在线| 免费一区二区视频| 成人羞羞视频播放网站| 国产在线看片免费视频在线观看| 亚州av一区| 日本亚洲欧洲无免费码在线| 日本午夜精品久久久久| 国产精成人品2018| 中文字幕在线高清| 九九久久电影| 日韩黄色av| 一本大道色婷婷在线| 在线亚洲精品| 麻豆成人av在线| 国户精品久久久久久久久久久不卡 | 无码日韩精品一区二区免费| 青青草精品视频| 久久香蕉国产| 日韩精品一区二区三区中文字幕| 卡一卡二国产精品| 亚洲有吗中文字幕| 日本成人中文字幕在线视频| 欧美精品第一区| 亚洲成av人片一区二区密柚| 爽爽淫人综合网网站| 蜜桃精品视频| 亚洲精品一区二区在线看| 国产麻豆一区二区三区精品视频| 岛国av在线播放| 日韩不卡手机在线v区| 欧美精品一卡| 日韩精品91亚洲二区在线观看| 成人免费网站www网站高清| 97久久中文字幕| 日韩专区一卡二卡| 久久中文字幕av| 久久精品国产亚洲一区二区三区| 美女日韩在线中文字幕| 日韩电影免费在线观看| 国产精品久久久久久久久久齐齐| 日韩中文字幕麻豆| 99久久亚洲精品| 久久三级福利| 最新中文字幕在线播放 | 欧美激情国产在线| 美日韩精品视频| 久久激情婷婷| 韩国一区二区三区视频| 欧美激情福利| 久久精品福利| 久久亚洲国产精品尤物| 97久久超碰| 一区二区三区四区日韩| 欧美日韩国产高清| 久久九九电影| 久久免费黄色| 亚洲精品成人| 丝袜亚洲另类欧美| 欧美日韩国产一区精品一区| 综合日韩av| 久久亚洲精品中文字幕蜜潮电影| 亚洲风情在线资源| av一区二区高清| 日韩中文字幕av电影|