高併發系統限流中的演算法
來自 https://blog.csdn.net/scorpio3k/article/details/53103239
在大資料量高併發訪問時,經常會出現服務或介面面對暴漲的請求而不可用的情況,甚至引發連鎖反映導致整個系統崩潰。此時你需要使用的技術手段之一就是限流,當請求達到一定的併發數或速率,就進行等待、排隊、降級、拒絕服務等。在限流時,常見的三種演算法是漏桶、令牌桶演算法演算法 、計數器限流演算法,本文即對相關內容進行重點介紹。
一、漏桶演算法的概念
漏桶演算法(Leaky Bucket):主要目的是控制資料注入到網路的速率,平滑網路上的突發流量。漏桶演算法提供了一種機制,通過它,突發流量可以被整形以便為網路提供一個穩定的流量。漏桶演算法的示意圖如下:
二、令牌桶演算法的概念
令牌桶演算法(Token Bucket):是網路流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一種演算法。典型情況下,令牌桶演算法用來控制傳送到網路上的資料的數目,並允許突發資料的傳送。令牌桶演算法示意圖如下所示:
Guava是google提供的java擴充套件類庫,其中的限流工具類RateLimiter採用的就是令牌桶演算法。RateLimiter 從概念上來講,速率限制器會在可配置的速率下分配許可證,如果必要的話,每個acquire() 會阻塞當前執行緒直到許可證可用後獲取該許可證,一旦獲取到許可證,不需要再釋放許可證。通俗的講RateLimiter會按照一定的頻率往桶裡扔令牌,執行緒拿到令牌才能執行,比如你希望自己的應用程式QPS不要超過1000,那麼RateLimiter設定1000的速率後,就會每秒往桶裡扔1000個令牌。例如我們需要處理一個任務列表,但我們不希望每秒的任務提交超過兩個,此時可以採用如下方式:
public class RateLimiterDemo {
private static RateLimiter limiter = RateLimiter.create(5);
public static void exec() {
limiter.acquire(1);
try {
// 處理核心邏輯
TimeUnit.SECONDS.sleep(1);
System.out.println("--" + System.currentTimeMillis() / 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
有一點很重要,那就是請求的許可數從來不會影響到請求本身的限制(呼叫acquire(1) 和呼叫acquire(1000) 將得到相同的限制效果,如果存在這樣的呼叫的話),但會影響下一次請求的限制,也就是說,如果一個高開銷的任務抵達一個空閒的RateLimiter,它會被馬上許可,但是下一個請求會經歷額外的限制,從而來償付高開銷任務。注意:RateLimiter 並不提供公平性的保證。
來自https://www.cnblogs.com/java1024/p/7725632.html
三、計數器限流演算法的概念
計數器限流演算法也是比較常用的,主要用來限制總併發數,比如資料庫連線池大小、執行緒池大小、程式訪問併發數等都是使用計數器演算法。
使用計數器限流示例1
public class CountRateLimiterDemo1 {
private static AtomicInteger count = new AtomicInteger(0);
public static void exec() {
if (count.get() >= 5) {
System.out.println("請求使用者過多,請稍後在試!"+System.currentTimeMillis()/1000);
} else {
count.incrementAndGet();
try {
//處理核心邏輯
TimeUnit.SECONDS.sleep(1);
System.out.println("--"+System.currentTimeMillis()/1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
count.decrementAndGet();
}
}
}
}
使用AomicInteger來進行統計當前正在併發執行的次數,如果超過域值就簡單粗暴的直接響應給使用者,說明系統繁忙,請稍後再試或其它跟業務相關的資訊。
弊端:使用 AomicInteger 簡單粗暴超過域值就拒絕請求,可能只是瞬時的請求量高,也會拒絕請求。
使用計數器限流示例2
public class CountRateLimiterDemo2 {
private static Semaphore semphore = new Semaphore(5);
public static void exec() {
if(semphore.getQueueLength()>100){
System.out.println("當前等待排隊的任務數大於100,請稍候再試...");
}
try {
semphore.acquire();
// 處理核心邏輯
TimeUnit.SECONDS.sleep(1);
System.out.println("--" + System.currentTimeMillis() / 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semphore.release();
}
}
使用Semaphore訊號量來控制併發執行的次數,如果超過域值訊號量,則進入阻塞佇列中排隊等待獲取訊號量進行執行。如果阻塞佇列中排隊的請求過多超出系統處理能力,則可以在拒絕請求。
相對Atomic優點:如果是瞬時的高併發,可以使請求在阻塞佇列中排隊,而不是馬上拒絕請求,從而達到一個流量削峰的目的。
相關文章
- 高併發系統的限流演算法與實現演算法
- Java高併發系統的限流策略Java
- 聊聊高併發系統之限流特技
- 高併發架構下的系統限流保護策略架構
- 慌了,居然被問到怎麼做高併發系統的限流
- 構建高併發&高可用&安全的IT系統-高併發部分
- 搭建高併發、高可用的系統
- [分散式][高併發]限流的四種策略分散式
- 高併發後端設計-限流篇後端
- 高併發系統之大忌-慢查詢
- 【高併發寫】庫存系統設計
- 聊聊高併發系統之HTTP快取HTTP快取
- 聊聊高併發系統之降級特技
- 高併發系統設計的15個錦囊
- 高效能高併發系統的穩定性保障
- 【高併發】Redis如何助力高併發秒殺系統,看完這篇我徹底懂了!!Redis
- Activemq構建高併發、高可用的大規模訊息系統MQ
- mysql 高併發檔案系統JFS安裝MySql
- 如何設計一個高可用、高併發秒殺系統
- 程式設計師修神之路—高併發優雅的做限流(有福利)程式設計師
- 使用Redis構建高併發高可靠的秒殺拍賣系統 - LuisRedisUI
- 說說大型高併發高負載網站的系統架構(更新)負載網站架構
- 高併發中nginx較優的配置Nginx
- 記一次線上商城系統高併發的優化優化
- 記,一次線上商城系統高併發的優化!優化
- 談談高併發系統的一些解決方案
- 如何處理業務系統中併發比較高的表資料清理工作
- 面試題:如何設計一個高併發系統?面試題
- 高併發IM系統架構優化實踐架構優化
- Java高併發秒殺系統【觀後總結】Java
- 關於PHP高併發搶購系統設計PHP
- 遊戲陪玩app開發,高併發系統如何設計?遊戲APP
- 一個高效能,高併發,高可用的系統是如何演變來的
- 說說大型高併發高負載網站的系統架構(轉載)負載網站架構
- 分散式系統限流演算法分析與實現分散式演算法
- bilibili高併發實時彈幕系統的實戰之路
- 高併發&效能優化(二)------系統監控工具使用優化
- Mysql核心技術:用NOSql給高併發系統加速MySql