摘要:本文將對Stream的經常使用命令和應用場景進行介紹,並探討原生Redis Stream消息隊列的缺陷以及GaussDB(for Redis)提供的解決方案,供你們學習和選用。
華爲雲高斯Redis團隊歡迎各路英才加入,聯繫郵箱:yuwenlong4@huawei.comhtml
引言:
Redis Stream是Redis 5.0引入的一種新的數據類型,其本質是一個消息隊列,相似於 kafka等消息中間件。它提供了消息的落地存儲功能,並實現了相似kafka消費組和消費者的功能。與kafka相比,Redis Stream一樣擁有強大的功能,但因原生Redis沒法有效支持大規模數據存儲,成本昂貴,並存在數據丟失/不一致風險等緣由,致使其未能流行起來。本文將對Stream的經常使用命令和應用場景進行介紹,並探討原生Redis Stream消息隊列的缺陷以及GaussDB(for Redis)提供的解決方案,供你們學習和選用。redis
1、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命令獲取聊天室發言的數量。url
3)使用XRANGE獲取消息隊列的消息。spa
4)使用XREAD命令讀取消息。能夠在不設置消費組和消費者的狀況下,使用XREAD的命令進行消息讀取,此時Stream隊列相似於一個普通的列表(list)。
更多的Redis Stream命令使用請參考官方文檔(https://redis.io/commands/xread)。
2、應用場景
因爲Redis Stream自然有序,特別適合存儲時序數據,應用場景包括即時通信、智慧醫療、流量削峯、智慧城市等領域。
(1)即時通信:微信、QQ等是咱們平常生活中經常使用的通信軟件,經常使用的聊天方式包含點對點通信和羣聊兩種方式。下圖是一個羣聊的模型圖,當採用Redis Stream做爲通信的中間件,建立一個羣聊時,在Redis中對應地爲該羣聊建立一個Stream隊列。在發送消息時,將每一個用戶的消息按照時間順序添加到Stream隊列中,保證了消息的有序性。因爲Stream是一個持久化的隊列,不管是在線仍是離線狀態,每一個用戶能夠屢次查看歷史消息,保證了通信的完整性。
(2)智慧醫療:醫療行業的信息化,能夠更好地服務於每個人。爲每個人從出生起創建一份健康檔案,記錄相應的健康信息,如體檢報告、診斷報告、用藥信息、以及智能終端實時上傳的健康指標。這些信息都是一些時序數據,一樣能夠採用Redis Stream來實現智慧醫療系統。創建起智慧醫療系統後,使用終端能夠查看全部的醫療信息,並會提示患者按時吃藥,在終端上傳身體指標異常時,會自動報警並預定掛號。現階段每一個醫院都有本身的信息系統,不一樣的醫院很難查到同一個患者的醫療信息,在將來,醫療上雲將有利於解決醫療信息孤島,更好的幫助每一位患者。
(3)流量削峯:在常見的秒殺活動或團購中,如春運搶票、商城促銷等,一般短期內有大量的流量,致使系統崩潰。因爲每個用戶在請求時對應惟一的時間戳,全部的請求都有一個前後順序,一樣能夠採用Redis Stream做爲中間件,將請求加入到Redis Stream消息隊列。將消息轉存到消息隊列間接提供給應用,而非直接發送給應用,能夠防止大流量衝擊致使的系統崩潰。當消息隊列中的請求數量達到規定的最大值時,直接回復客戶端搶購失敗。
3、原生Redis是否真的適用於以上場景?
如上應用場景具備數據規模大、數據持續增加的特色,雖然原生Redis有良好的設計初衷,可是並不能解決實際問題。具體體如今:
- 沒法有效應對大規模數據:原生Redis是一個基於內存的數據庫,單個節點存儲容量有限,當擴展至TB級別的集羣,將會出現管理困難,運維成本高等問題。
- 集羣擴容影響業務性能:原生Redis在進行集羣擴容時,須要從新劃分hash槽並進行數據遷移,一定會影響業務性能。
- 數據可能會丟失:原生Redis雖然能夠採用RDB和AOF的方式對數據進行持久化,可是並不會實時地將每一條命令寫入到硬盤中,當出現掉電或集羣崩潰的狀況,一定會丟失一部分數據,對於相似智慧醫療場景,是難以忍受的。
除此之外,必須考慮數據庫系統的可用性、數據一致性、成本和備份恢復能力等狀況:
- 可用性: 原生Redis若採用一主一備的集羣模式,當一對主備節點下線,集羣部分數據將不可用。
- 數據一致性:當主節點宕機,主備節點切換,數據存在沒有徹底同步的狀況。
- 成本:原生Redis是一種內存型數據庫,當內存容量擴展至TB級別,成本將很是昂貴。
- 備份恢復:須要人工鏈接數據庫執行 SAVE或BGSAVE命令,不能支持按期自動備份,在恢復到新實例時須要手動拷貝備份數據。
4、是否有更好的解決方案?
在以上場景中,亟需一種可以存儲和處理大規模Stream數據、魯棒性強、且成本低廉的數據庫系統。而GaussDB(for Redis)(下文簡稱高斯Redis)正是以上場景中一種很好的應用解決方案。高斯Redis是華爲雲數據庫團隊自主研發的兼容Redis協議的雲原生數據庫,該數據庫突破原生Redis的內存限制,可輕鬆擴展至PB級存儲,具備秒擴容、超可用、強一致和低成本等特色。
5、總結
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