替代全局訂閱?)
Dragonfly 集群模式如何啟用 Sharded Pub/SubSPUBLISH/SSUBSCRIBE替代全局訂閱【免費下載鏈接】dragonflyA modern replacement for Redis and Memcached項目地址: https://gitcode.com/GitHub_Trending/dr/dragonfly在 Dragonfly 中開啟集群模式--cluster_modeyes后PUBLISH、SUBSCRIBE、PSUBSCRIBE這類全局發布訂閱命令會被服務端直接拒絕集群下唯一可用的發布訂閱路徑是 Sharded Pub/SubSPUBLISH/SSUBSCRIBE/SUNSUBSCRIBE。本文在一個本地兩節點集群上完成完整的操作路徑啟動節點、推送 slot 配置、確認頻道歸屬、完成一次訂閱—發布—退訂往返、檢查訂閱狀態并說明 slot 遷移時對已有訂閱的處理。文中的命令和預期響應都可以對照倉庫里的集群 pub/sub 集成測試復核。集群模式下為什么只有 Sharded Pub/Sub 可用pub-sub 文檔把 Dragonfly 的 pub/sub 分成三種形態并明確列出它們在集群模式下的行為形態命令作用域集群模式StandardPUBLISH、SUBSCRIBE、UNSUBSCRIBE全局所有頻道Blocked — 返回錯誤PatternPSUBSCRIBE、PUNSUBSCRIBE全局glob 匹配Blocked — 返回錯誤ShardedSPUBLISH、SSUBSCRIBE、SUNSUBSCRIBE按 slot頻道名決定 slot支持在集群節點上執行全局命令會返回(error) PUBLISH is not supported in cluster mode yet。原因在于全局頻道沒有 slot 歸屬而集群按 slot 做路由cluster-mode.md §5.1。Sharded Pub/Sub 把頻道名當作 key 參與 slot 計算slot(channel) crc16(tag(channel)) 0x3FFFhash tag 規則與普通 key 相同取第一段配平的{...}內容否則取整個頻道名見 cluster-mode.md §3.1–3.2。這樣同一個頻道的SPUBLISH和SSUBSCRIBE總是路由到同一個 slot、同一個屬主節點集群的 slot 歸屬檢查可以直接套用。命令的元信息來自 pub-sub.md 的命令注冊表SPUBLISHarity 3參數為頻道名 消息體SSUBSCRIBEarity -2訂閱 1 個或多個頻道SUNSUBSCRIBEarity -1不帶參數時退訂當前連接的全部 sharded 頻道。準備獲取二進制與集群啟動參數二進制可以按 Build From Source 從源碼構建安裝構建依賴Debian/Ubuntu 為ninja-build、libunwind-dev、libboost-context-dev、libssl-dev等git clone --recursive后執行./helio/blaze.sh -release再在build-opt目錄ninja dragonfly也可以參考 Quick Start 使用 Docker 鏡像。集群模式下的啟動參數cluster-mode.md §2.2 與 §8參數說明--cluster_modeyes進入完整集群模式。在收到第一份DFLYCLUSTER CONFIG之前節點不持有任何 slot數據面命令一律返回-ERR Cluster is not yet configured--admin_portp真實集群模式必需。DFLYCLUSTER、DFLYMIGRATE只在這個 admin listener 上接受連接--cluster_node_idid可選。節點身份必須與配置 JSON 中master.id一致--cluster_announce_ipip可選。返回給客戶端的 IP用于CLUSTER SLOTS/SHARDS/NODES和 MOVED 回復第一步啟動本地兩節點集群按倉庫測試的端口約定30001 起順序遞增啟動兩個節點# 節點 A ./build-opt/dragonfly --port 30001 --admin_port 30002 --cluster_modeyes # 節點 B ./build-opt/dragonfly --port 30003 --admin_port 30004 --cluster_modeyes端口可換成任意不沖突的值。啟動后在任意 listener不限 admin 端口上獲取各節點身份redis-cli -p 30001 CLUSTER MYID redis-cli -p 30003 CLUSTER MYID第二步構造并推送 slot 配置集群拓撲由外部 cluster manager 編寫并推送到每個節點。按 §4.1 的 JSON wire format 構造拓撲每個 shard 包含slot_ranges閉區間互不重疊全部 shard 合起來必須覆蓋 0..16383、masterid為上一步CLUSTER MYID的輸出、replicas可為空數組。下面這份示例把 16384 個 slot 對半分給節點 A 和節點 BJSON 里兩處 id 是占位符請替換為各自CLUSTER MYID的實際輸出[ { slot_ranges: [ { start: 0, end: 8191 } ], master: { id: 節點 A 的 CLUSTER MYID 輸出, ip: 127.0.0.1, port: 30001, health: online }, replicas: [] }, { slot_ranges: [ { start: 8192, end: 16383 } ], master: { id: 節點 B 的 CLUSTER MYID 輸出, ip: 127.0.0.1, port: 30003 }, replicas: [] } ]同一份 JSON 必須推送到每個節點集群內部沒有 gossip。通過 admin 端口下發redis-cli -p 30002 DFLYCLUSTER CONFIG 上面的 JSON redis-cli -p 30004 DFLYCLUSTER CONFIG 上面的 JSON兩個節點都返回OK表示配置生效。校驗失敗時slot 有缺口或重疊、節點 id 重復等返回-ERR Invalid cluster configuration.且節點保留原配置不變修正后重新推送即可。倉庫的集成測試還有一個變體不設置--admin_port時直接在主端口下發DFLYCLUSTER CONFIG兩種做法二選一即可。驗證方式redis-cli -p 30001 CLUSTER SLOTS返回的 slot 拓撲應體現 A 擁有 0..8191、B 擁有 8192..16383。此后向不擁有某頻道 slot 的節點發命令會得到-MOVED slot ip:port端點是本地配置中該 slot 的屬主。第三步確認頻道的 slot 歸屬訂閱前先確認目標頻道落在哪個節點上redis-cli -p 30001 CLUSTER KEYSLOT kostasKEYSLOT key是任意 listener 可用的只讀查詢命令。返回的 slot 號在[0, 8191]歸節點 A在[8192, 16383]歸節點 B。本文示例沿用倉庫測試使用的頻道kostas如果想控制頻道落在哪個節點可以借助 hash tag只有{...}內的內容參與散列。用 MOVED 行為直接驗證路由向不擁有該頻道 slot 的節點執行訂閱例如頻道歸 A 所有時redis-cli -p 30003 SSUBSCRIBE kostas -MOVED slot 127.0.0.1:30001其中slot即CLUSTER KEYSLOT返回的 slot 號。這說明SSUBSCRIBE和SPUBLISH一樣先過 slot 路由檢查必須連到屬主節點執行。第四步SSUBSCRIBE → SPUBLISH → SUNSUBSCRIBE 完整往返連接到頻道屬主節點本例為節點 A并訂閱redis-cli -p 30001 SSUBSCRIBE kostasSSUBSCRIBE是阻塞式訂閱命令連接建立后會先收到一條訂閱確認推送類型為ssubscribe末尾的數字是本次操作后剩余的訂閱數。另開一個終端在同一節點發布redis-cli -p 30001 SPUBLISH kostas hello訂閱端連接隨后收到一條類型為smessage的推送內容為頻道名 消息體。倉庫測試用 redis-py 集群客戶端RedisClusterpubsub().ssubscribe(...)驗證的就是這兩條推送文檔示例輸出{type: ssubscribe, pattern: None, channel: bkostas, data: 1} {type: smessage, pattern: None, channel: bkostas, data: bhello}消息的投遞路徑見下圖來自 docs/pub-sub.mdSPUBLISH在全局ChannelStore中查找該頻道的訂閱者再異步分發到各訂閱者所在的 I/O 線程寫出。最后執行退訂不帶參數則退訂全部 sharded 頻道redis-cli -p 30001 SUNSUBSCRIBE kostas連接收到一條sunsubscribe推送測試中此時計數為 0。兩個執行細節投遞是異步的內部走DispatchBrief跨線程分發倉庫測試在SPUBLISH后sleep(2)再取消息用腳本驗證時不要假設發布與接收嚴格同時發生smessage類型只用于 sharded 頻道與標準頻道的message推送類型區分。第五步用 PUBSUB SHARDCHANNELS / SHARDNUMSUB 檢查訂閱狀態PUBSUB SHARDCHANNELS [pattern]列出當前活躍的 sharded 頻道PUBSUB SHARDNUMSUB channel...返回各頻道的訂閱數。倉庫測試在訂閱了pubsub-shard-channel和shard-channel兩個頻道后的驗證輸出文檔示例redis-cli -p 30001 PUBSUB SHARDCHANNELS 1) pubsub-shard-channel 2) shard-channel redis-cli -p 30001 PUBSUB SHARDCHANNELS pubsub* 1) pubsub-shard-channel redis-cli -p 30001 PUBSUB SHARDNUMSUB pubsub-shard-channel shard-channel 1) pubsub-shard-channel 2) (integer) 1 3) shard-channel 4) (integer) 1這兩個子命令只在集群模式下支持非集群節點執行會返回PUBSUB SHARDCHANNELS is not supported in non cluster mode見 src/server/main_service.cc。slot 遷移時受影響頻道的強制退訂當 cluster manager 推送新配置把 slot 遷走遷移協議見 cluster-mode.md §6原節點會調用UnsubscribeAfterClusterSlotMigrationsrc/server/channel_store.cc收集受影響 slot 內所有頻道的訂閱者整體移除并向每個受影響的連接推送sunsubscribe計數為 0。遷移集成測試驗證了這條鏈路頻道的 slot 遷到另一節點后舊節點上的訂閱者收到sunsubscribe此時再到舊節點SSUBSCRIBE會被 MOVED 重定向到新屬主。同樣的清理也會發生在DFLYCLUSTER FLUSHSLOTS以及配置使 slot 離開屬主時——節點在完成 slot 數據清掃后丟棄這些 slot 的 sharded 訂閱。也就是說發生 slot 重平衡后客戶端需要自行向新屬主節點重新訂閱受影響頻道服務端不會代客遷移訂閱關系。邊界條件與限制全局發布訂閱在集群模式不可用PUBLISH、SUBSCRIBE、PSUBSCRIBE、PUNSUBSCRIBE均被拒絕PUBLISH的確切報錯為PUBLISH is not supported in cluster mode yet。從全局訂閱遷移過來的應用需要把所有調用路徑改成 sharded 形態且頻道命名會開始參與 slot 路由。SSUBSCRIBE一次訂閱多個頻道時所有頻道必須落在同一 slot否則觸發集群的單 slot 約束被拒絕-CROSSSLOT見 cluster-mode.md §5.1。節點重啟后不持有 slotcluster manager 必須重新推送當前配置節點才能恢復服務。集群模式下存儲為單 DBSELECT到其他 DB 索引會被拒絕。發布端背壓單個 I/O 線程上訂閱者排隊字節數達到硬上限publish_buffer_limit的 4 倍才會暫停發布者細節見 docs/pub-sub.md 的 Backpressure 一節。延伸閱讀docs/cluster-mode.md — 集群命令面、配置 JSON 校驗規則、遷移協議與失敗模式docs/pub-sub.md — ChannelStore、消息分發與背壓的內部實現tests/dragonfly/cluster_pubsub_test.py — 本文整條路徑可運行的集成測試包括 slot 遷移場景docs/cluster-node-health.md — 配置中health字段對客戶端拓撲過濾的影響。【免費下載鏈接】dragonflyA modern replacement for Redis and Memcached項目地址: https://gitcode.com/GitHub_Trending/dr/dragonfly創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考