華為雲PB級數據庫GaussDB(for Redis)解析第二期:Redis消息隊列Stream的應用探討


摘要:本文將對Stream的常用命令和應用場景進行介紹,並探討原生Redis Stream消息隊列的缺陷以及GaussDB(for Redis)提供的解決方案,供大家學習和選用。

華為雲高斯Redis團隊歡迎各路英才加入,聯系郵箱:yuwenlong4@huawei.com

引言:

Redis Stream是Redis 5.0引入的一種新的數據類型,其本質是一個消息隊列,類似於 kafka等消息中間件。它提供了消息的落地存儲功能,並實現了類似kafka消費組和消費者的功能。與kafka相比,Redis Stream同樣擁有強大的功能,但因原生Redis無法有效支持大規模數據存儲,成本昂貴,並存在數據丟失/不一致風險等原因,導致其未能流行起來。本文將對Stream的常用命令和應用場景進行介紹,並探討原生Redis Stream消息隊列的缺陷以及GaussDB(for Redis)提供的解決方案,供大家學習和選用。

一、Redis Stream簡介

與Pub/Sub相比,Redis Stream 具有消息的落地存儲功能,每一個客戶端能訪問任意時刻的消息,並且能記錄每一個客戶端的訪問位置,還能保證消息不會丟失。Redis Stream 的結構如下所示,它有一個消息鏈表,將所有加入的消息都鏈接起來,每個消息都有唯一的 ID 和對應的內容。

如圖所示,每一個Stream隊列包含多條消息,每條消息由唯一的ID進行標識,由時間戳和序列號組成,例如1627849609889-0。每條消息以追加的方式添加到Stream隊列中。同一個Stream隊列可以包含多個消費組(Consumer Group),每個消費組的狀態都是獨立的,同一個Stream隊列的消息可以被多個消費組重復消費。

同一個消費組又包含多個消費者(Consumer),這些消費者之間是競爭關系,不同消費者不會重復消費同一條消息,任意一個消費者讀取了隊列中的一條消息都會使消費組中的游標last_delivered_id往前移動。該方式提高了並發效率,例如,多個進程並發處理Stream隊列中的消息。每個消費者中維持一個狀態變量pending_ids,簡稱為PEL(Pending Entries List),記錄了當前已經被客戶端讀取的但尚未被ACK的消息,確保消息被客戶端成功消費。

Redis Stream命令可以分為消息隊列命令和消費者命令兩類,如下所示:

以即時通訊中的聊天室場景為例,使用Redis Stream作為中間件,實現聊天室的發言以及信息查看。

1)使用XADD命令進行發言。

2)使用XLEN命令獲取聊天室發言的數量。

3)使用XRANGE獲取消息隊列的消息。

4)使用XREAD命令讀取消息。可以在不設置消費組和消費者的情況下,使用XREAD的命令進行消息讀取,此時Stream隊列類似於一個普通的列表(list)。

更多的Redis Stream命令使用請參考官方文檔(https://redis.io/commands/xread)。

二、應用場景

由於Redis Stream天然有序,特別適合存儲時序數據,應用場景包括即時通訊、智慧醫療、流量削峰、智慧城市等領域。

(1)即時通訊:微信、QQ等是我們日常生活中常用的通訊軟件,常用的聊天方式包含點對點通訊和群聊兩種方式。下圖是一個群聊的模型圖,當采用Redis Stream作為通訊的中間件,創建一個群聊時,在Redis中對應地為該群聊創建一個Stream隊列。在發送消息時,將每個用戶的消息按照時間順序添加到Stream隊列中,保證了消息的有序性。由於Stream是一個持久化的隊列,無論是在線還是離線狀態,每個用戶可以多次查看歷史消息,保證了通訊的完整性。

(2)智慧醫療:醫療行業的信息化,可以更好地服務於每一個人。為每一個人從出生起建立一份健康檔案,記錄相應的健康信息,如體檢報告、診斷報告、用葯信息、以及智能終端實時上傳的健康指標。這些信息都是一些時序數據,同樣可以采用Redis Stream來實現智慧醫療系統。建立起智慧醫療系統后,使用終端可以查看所有的醫療信息,並會提示患者按時吃葯,在終端上傳身體指標異常時,會自動報警並預約掛號。現階段每個醫院都有自己的信息系統,不同的醫院很難查到同一個患者的醫療信息,在未來,醫療上雲將有利於解決醫療信息孤島,更好的幫助每一位患者。

(3)流量削峰:在常見的秒殺活動或團購中,如春運搶票、商城促銷等,通常短時間內有大量的流量,導致系統崩潰。由於每一個用戶在請求時對應唯一的時間戳,所有的請求都有一個先后順序,同樣可以采用Redis Stream作為中間件,將請求加入到Redis Stream消息隊列。將消息轉存到消息隊列間接提供給應用,而非直接發送給應用,可以防止大流量沖擊導致的系統崩潰。當消息隊列中的請求數量達到規定的最大值時,直接回復客戶端搶購失敗。

三、原生Redis是否真的適用於以上場景?

如上應用場景具有數據規模大、數據持續增長的特點,雖然原生Redis有良好的設計初衷,但是並不能解決實際問題。具體體現在:

  1. 無法有效應對大規模數據:原生Redis是一個基於內存的數據庫,單個節點存儲容量有限,當擴展至TB級別的集群,將會出現管理困難,運維成本高等問題。
  2. 集群擴容影響業務性能:原生Redis在進行集群擴容時,需要重新划分hash槽並進行數據遷移,必定會影響業務性能。
  3. 數據可能會丟失:原生Redis雖然可以采用RDB和AOF的方式對數據進行持久化,但是並不會實時地將每一條命令寫入到硬盤中,當出現掉電或集群崩潰的情況,必定會丟失一部分數據,對於類似智慧醫療場景,是難以忍受的。

除此以外,必須考慮數據庫系統的可用性、數據一致性、成本和備份恢復能力等情況:

  1. 可用性: 原生Redis若采用一主一備的集群模式,當一對主備節點下線,集群部分數據將不可用。
  2. 數據一致性:當主節點宕機,主備節點切換,數據存在沒有完全同步的情況。
  3. 成本:原生Redis是一種內存型數據庫,當內存容量擴展至TB級別,成本將非常昂貴。
  4. 備份恢復:需要人工連接數據庫執行 SAVE或BGSAVE命令,不能支持定期自動備份,在恢復到新實例時需要手動拷貝備份數據。

四、是否有更好的解決方案?

在以上場景中,亟需一種能夠存儲和處理大規模Stream數據、魯棒性強、且成本低廉的數據庫系統。而GaussDB(for Redis)(下文簡稱高斯Redis)正是以上場景中一種很好的應用解決方案。高斯Redis是華為雲數據庫團隊自主研發的兼容Redis協議的雲原生數據庫,該數據庫突破原生Redis的內存限制,可輕松擴展至PB級存儲,具有秒擴容、超可用、強一致和低成本等特點。

五、總結

Redis Stream可以廣泛應用在即時通訊、智慧醫療、流量削峰等領域。在面對大規模的Stream數據時,原生Redis存在成本過高、容量太小、可用性差、數據不一致等問題,無法適用於海量消息隊列的場景。與原生Redis相比,高斯Redis具有海量存儲,低成本,可持久化等優點,可做為比原生Redis更理想的Stream隊列承載方案。

附:參考資料

1. 《華為雲GaussDB(for Redis)與自建開源Redis的成本對比》

https://www.modb.pro/db/42739

2. 《一場由fork引發的超時,讓我們重新探討了Redis的抖動問題》

https://bbs.huaweicloud.com/blogs/227525

3. 《當Redis遇見計算存儲分離》

https://developer.huaweicloud.com/hero/forum/thread-83188-1-1.html

4. 《GaussDB(for Redis)與原生Redis的性能對比》

https://bbs.huaweicloud.com/blogs/236949

5. 《華為雲PB級數據庫GaussDB(for Redis)揭秘第一期:Redis與存算分離》

https://bbs.huaweicloud.com/blogs/238584

 

點擊關注,第一時間了解華為雲新鮮技術~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM