常見(jiàn)的限流方法:
- 固定窗口計(jì)數(shù)器:按照時(shí)間段劃分窗口,有一次請(qǐng)求就+1,最為簡(jiǎn)單的算法,但這個(gè)算法有時(shí)會(huì)讓通過(guò)請(qǐng)求量允許為限制的兩倍。
- 滑動(dòng)窗口計(jì)數(shù)器:通過(guò)將窗口再細(xì)分,并且按照時(shí)間“滑動(dòng)”來(lái)解決突破限制的問(wèn)題,但是時(shí)間區(qū)間的精度越高,算法所需的空間容量就越大。
- 漏桶:請(qǐng)求類(lèi)似水滴,先放到桶里,服務(wù)的提供方則按照固定的速率從桶里面取出請(qǐng)求并執(zhí)行。缺陷也很明顯,當(dāng)短時(shí)間內(nèi)有大量的突發(fā)請(qǐng)求時(shí),即便此時(shí)服務(wù)器沒(méi)有任何負(fù)載,每個(gè)請(qǐng)求也都得在隊(duì)列中等待一段時(shí)間才能被響應(yīng)。
- 令牌桶:往桶里面發(fā)放令牌,每個(gè)請(qǐng)求過(guò)來(lái)之后拿走一個(gè)令牌,然后只處理有令牌的請(qǐng)求。令牌桶滿(mǎn)了則多余的令牌會(huì)直接丟棄。令牌桶算法既能夠?qū)⑺械恼?qǐng)求平均分布到時(shí)間區(qū)間內(nèi),又能接受服務(wù)器能夠承受范圍內(nèi)的突發(fā)請(qǐng)求,因此是目前使用較為廣泛的一種限流算法。Google的開(kāi)源項(xiàng)目guava提供了RateLimiter類(lèi),實(shí)現(xiàn)了單點(diǎn)的令牌桶限流。分布式環(huán)境下,可以考慮用Redis+Lua腳本實(shí)現(xiàn)令牌桶。 如果請(qǐng)求量太大了,Redis也撐不住怎么辦?我覺(jué)得可以類(lèi)似于分布式ID的處理方式,Redis前面在增加預(yù)處理,比如每臺(tái)及其預(yù)先申請(qǐng)一部分令牌,只有令牌用完之后才去 Redis。如果還是太大,是否可以垂直切分?按照流量的來(lái)源,比如地理位置、IP 之類(lèi)的再拆開(kāi)。