新聞中心
Redis實(shí)現(xiàn)分布式限流限速

成都創(chuàng)新互聯(lián)從2013年創(chuàng)立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、成都做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元興平做網(wǎng)站,已為上家服務(wù),為興平各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:13518219792
隨著互聯(lián)網(wǎng)的高速發(fā)展,流量攀升的趨勢(shì)成為了一種不可避免的趨勢(shì)。流量的攀升也帶來(lái)了一個(gè)問題,就是流量控制的問題。如何在高流量的情況下保證系統(tǒng)穩(wěn)定,已經(jīng)成為了一個(gè)必須解決的問題。在這樣的背景下,分布式限流限速也就應(yīng)運(yùn)而生了。
Redis是一個(gè)高性能的非關(guān)系型數(shù)據(jù)庫(kù),擁有著高效的讀寫操作和豐富的數(shù)據(jù)結(jié)構(gòu),紅色金字塔架構(gòu)中的極速緩存層。Redis具有高效、可擴(kuò)展等特點(diǎn),所以在很多業(yè)務(wù)場(chǎng)景下,Redis作為限流限速的緩存介質(zhì)也是一個(gè)不錯(cuò)的選擇。
在實(shí)現(xiàn)限流限速之前,我們需要明確兩個(gè)概念:令牌桶和漏桶。
令牌桶算法的原理:令牌桶是一種基于時(shí)間間隔的算法,可以平滑地限制發(fā)送至目標(biāo)的數(shù)據(jù)流量,避免因?yàn)橥话l(fā)性流量造成的系統(tǒng)負(fù)載過(guò)重。它的原理是設(shè)定一個(gè)固定的令牌產(chǎn)生速率,比如每秒鐘生成10個(gè)令牌,然后每次事件請(qǐng)求時(shí),需要消耗一個(gè)令牌,只有當(dāng)桶中有足夠的令牌才會(huì)繼續(xù)執(zhí)行,如果桶中的令牌被消耗完了,那么后續(xù)的請(qǐng)求就會(huì)被拒絕或者等待。
漏桶算法的原理:漏桶算法和令牌桶算法類似,也是一種基于時(shí)間間隔的算法,是一種平滑輸出的算法,漏桶可以看成一個(gè)固定容量的桶,水(可以看做是請(qǐng)求)會(huì)以恒定的速率流出桶外,如果桶滿了就將水丟棄或者等待,其中水以恒定的速率流到桶中,而不管流出來(lái)的水的速度有多快。
那么,我們?cè)谑褂肦edis做限流限速時(shí),如何實(shí)現(xiàn)呢?下面我們就來(lái)講一講。
一、令牌桶算法在Redis中的實(shí)現(xiàn)
1. 在Redis中通過(guò)使用Lua腳本來(lái)保證原子性操作:
local KEY = KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call("get", key) or "0")
if current +1 > limit then --如果超出限流數(shù),返回0(限流)
return 0
else --沒有超出限流數(shù),則將計(jì)數(shù)器+1,返回1(不限流)
redis.call("INCRBY", key, "1")
redis.call("expire", key, "2") --設(shè)置過(guò)期時(shí)間,達(dá)到限流的作用
return 1
end
其中,key為Redis的鍵值,limit為限流數(shù),current為當(dāng)前的處理數(shù),INCRBY是Redis的自增命令,expire為Redis的過(guò)期時(shí)間命令。
2. 在使用令牌桶算法時(shí),要考慮到請(qǐng)求發(fā)送的時(shí)間間隔,比如一秒鐘內(nèi)只能發(fā)送10個(gè)請(qǐng)求,那么就需要定時(shí)器,定時(shí)在一秒鐘之后自動(dòng)歸零計(jì)數(shù)器:
local function getallowance(key, rate, capacity, now)
local key = "rate_limiter:"..key
local current = tonumber(redis.call("get", key) or "0")
local last_time = tonumber(redis.call("get", key..":ts") or "0")
local elapsed = now - last_time
local allowance = current
if elapsed > 0 then
allowance = allowance + (elapsed*rate)
if allowance > capacity then
allowance = capacity
end
end
redis.call("set", key..":ts", now)
redis.call("set", key, math.max(0,allowance-1))
return allowance > 1
end
以上代碼實(shí)現(xiàn)了令牌桶算法限流,可以自行調(diào)整參數(shù)實(shí)現(xiàn)不同的流速控制。
二、漏桶算法在Redis中的實(shí)現(xiàn)
漏桶算法的實(shí)現(xiàn)稍稍有些不同,需要使用Redis的SETNX命令實(shí)現(xiàn)鎖,避免并發(fā)問題。
-- 漏桶算法
-- @return 0表示達(dá)到限流條件,1表示未達(dá)到
local function leaky_bucket(key, rate, capacity)
local key = "rate_limiter:" .. key
local now = redis.call("time")[1]
local fill_time = capacity/rate
local expected_fill_time = tonumber(redis.call("get", key .. ":ts") or 0) + fill_time
local allowance = tonumber(redis.call("get", key) or 0)
allowance = allowance - (now - tonumber(redis.call("get", key .. ":ts") or 0)) / fill_time
if allowance
allowance = 0
end
if allowance
allowance = allowance + 1
else
return 0
end
redis.call("set", key .. ":ts", now)
redis.call("set", key, allowance)
return 1
end
以上代碼實(shí)現(xiàn)了漏桶算法限速,同樣可以自行調(diào)整參數(shù)實(shí)現(xiàn)不同的流量控制。
總結(jié):Redis實(shí)現(xiàn)分布式限流限速,可以根據(jù)不同的業(yè)務(wù)場(chǎng)景選擇不同的算法進(jìn)行實(shí)現(xiàn)。算法的選擇一定要考慮到請(qǐng)求的處理時(shí)間以及請(qǐng)求的發(fā)送時(shí)間間隔。對(duì)于高頻率的請(qǐng)求,可以考慮使用令牌桶算法,而對(duì)于稀疏的請(qǐng)求,漏桶算法要更加穩(wěn)定和準(zhǔn)確。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
網(wǎng)頁(yè)名稱:Redis實(shí)現(xiàn)分布式限流限速(redis組件分布式限流)
文章來(lái)源:http://m.fisionsoft.com.cn/article/ccoegjj.html


咨詢
建站咨詢
