性能優化:Redis Stream 支撐萬級節點消息同步

  1. 背景

在微服務系統中,經常需要將一些配置 / 控制類的數據變更同步到所有的線上節點中。比如安全防禦系統中,將某個需要攔截的黑 IP 同步到所有節點上供他們處理流量的時候進行攔截使用。

這個場景是消息隊列非常擅長的領域。節點數少的情況下方案可以比較隨意的選擇,一旦節點數非常多的情況下,問題就變更復雜了。

2. 消息隊列的選擇

且看看本人所在公司的做法,爲了解決這個問題,消息隊列的實現方式有很多個版本:RedisPub/Sub 方式 ->RedisStream->RedisSorted 方式。

當前在用 Sorted 方式,時不時的會客訴說有些變更數據丟失了。因爲 Sorted 方式嚴重依賴時間戳,這種方式並不是一個嚴謹的消息隊列。

所以就不得反思下,爲什麼專業的 RedisStream 不行要換到 RedisSorted 去呢?一說是 RedisStream 性能不足,支持不了線上那麼多的節點。 配置類數據變更,它的 qps 並不會很大,所以這是真的嗎?

3. Redis Stream 的幾種使用方式

3.1 標準單分片

注意一點,RedisStream 之所有會有性能問題,是因爲一個 Stream 一定在一個 Redis 節點上,它沒有辦法將集羣所有的節點資源都利用起來。標準單分片方案就有這個問題。一般單個節點支持 1WQPS 就可以了。用這個方案就夠了。如果有 1W 節點,即使一秒更新一條數據,也可以產生 1WQPS 的讀請求,這方案就不夠用了。

3.2 按業務內容分片

這個是類似 Mysql 裏面分庫分表的思路,那麼這裏就分 Stream 吧。如下:

# 示例:根據IP的哈希值分片到不同Stream
shard_id = crc32(ip) % 1024  
stream_key = f"config_stream_{shard_id}"

這個思路是圍繞着內容進行分片,如果消費節點只需要一部分數據的話還是可以解決問題的。而對於安全服務和配置同步的常見,它實際上時要所有數據的。採用這種方案就要求所有消費節點要消費所有的 Stream 分片了。這個方案,單片 Stream 的 QPS 並沒有降低。萬級節點可能還是不可用的。

3.3 多副本分片

如圖,這個思路同樣是分片,但是它不再基於內容去分片,而是採用副本的方式去分片。圖中,消息會被同時寫入到分片 1 和分片 2,每個節點從分片 1 或者分片 2 拿到所有的數據副本。

採用這種方案,加入用 5 個分片,即使有 1W 個幾點,每個分片(所在的節點)實際上也只要處理 2000 個節點的請求即可。這種多副本分片方案可以充分利用 Redis 集羣資源,支持萬級節點數據同步基本沒啥問題。

當前,我在線上,用了 2 個 Redis 節點和 6 個分片支撐了 5K 個節點同時獲取配置更新事件,Redis 集羣整體利用率很平均。

題外話,現在的大數據處理的很多組件(比如 kafka)都用到了多副本去做擴展。這裏的多副本分片方法有異曲同工之處。

4. 總結

其實不是 RedisSteam 性能不行,是使用的方式可能不大對。如果下次遇到這種場景的話,希望可以選擇對的方法,不用去用 Sorted 變相做做消息隊列了。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/QTTC5ObH3oPeFRtnSdJIhA