Current Limiting
在編寫系統時候有時候我們的系統在設計的時候就已經估算到了最大請求負載了,如果大量的請求超過系統所能承受着的值時,那麼系統可能随時挂掉,所有聰明程式員就想到了
請求限流
來控制系統的可用和穩定性。
滑動視窗限流
滑動視窗算法将一個大的時間視窗分成多個小視窗,每次大視窗向後滑動一個小視窗,并保證大的視窗内流量不會超出最大值,這種實作比固定視窗的流量曲線更加平滑。
以系統限制使用者行為為例子,比如一秒内進行某個操作
5
次,這種行為應該進行限制,滑動視窗就是記錄一個滑動的時間視窗内的操作次數,操作次數超過門檻值則進行限流。
public boolean isActionAllowed(String userId, String actionKey, int period, int maxCount) {
// 生成唯一的key
String key = String.format("hist:%s:%s", userId, actionKey);
long nowTs = System.currentTimeMillis();
// 使用管道
Pipeline pipe = jedis.pipelined();
pipe.multi();
// 添加目前操作當zset中
pipe.zadd(key, nowTs, "" + nowTs);
// 整理zset,删除時間視窗外的資料 符合條件的保留
pipe.zremrangeByScore(key, 0, nowTs - period * 1000);
// 目前視窗内有多少個操作
Response<Long> count = pipe.zcard(key);
// 在生命周期上加一
pipe.expire(key, period + 1);
pipe.exec();
pipe.close();
// 是否達到閥值
return count.get() <= maxCount;
}
漏捅算法
露桶算法的核心思想,就把請求進行緩沖,防止大規模數量積的請求同時沖垮系統,如下圖:
CL.THROTTLE user123 15 30 60 1
▲ ▲ ▲ ▲ ▲
| | | | └───── apply 1 token (default if omitted)
| | └──┴─────── 30 tokens / 60 seconds
| └───────────── 15 max_burst
└─────────────────── key "user123"
其他
- https://github.com/brandur/redis-cell