華為云企業(yè)級Redis揭秘第二期:Redis消息隊(duì)列Stream應(yīng)用探討
【最新活動】企業(yè)級Redis專場熱銷中!首月免費(fèi),包年僅需4折!
引言:Redis Stream是Redis 5.0引入的一種新的數(shù)據(jù)類型,其本質(zhì)是一個(gè)消息隊(duì)列,類似于 kafka等消息中間件。它提供了消息的落地存儲功能,并實(shí)現(xiàn)了類似kafka消費(fèi)組和消費(fèi)者的功能。與kafka相比,Redis Stream同樣擁有強(qiáng)大的功能,但因原生Redis無法有效支持大規(guī)模數(shù)據(jù)存儲,成本昂貴,并存在數(shù)據(jù)丟失/不一致風(fēng)險(xiǎn)等原因,導(dǎo)致其未能流行起來。本文將對Stream的常用命令和應(yīng)用場景進(jìn)行介紹,并探討原生Redis Stream消息隊(duì)列的缺陷以及GaussDB(for Redis)提供的解決方案,供大家學(xué)習(xí)和選用。
一、Redis Stream簡介
與Pub/Sub相比,Redis Stream 具有消息的落地存儲功能,每一個(gè)客戶端能訪問任意時(shí)刻的消息,并且能記錄每一個(gè)客戶端的訪問位置,還能保證消息不會丟失。Redis Stream 的結(jié)構(gòu)如下所示,它有一個(gè)消息鏈表,將所有加入的消息都鏈接起來,每個(gè)消息都有唯一的 ID 和對應(yīng)的內(nèi)容。
如圖所示,每一個(gè)Stream隊(duì)列包含多條消息,每條消息由唯一的ID進(jìn)行標(biāo)識,由時(shí)間戳和序列號組成,例如1627849609889-0。每條消息以追加的方式添加到Stream隊(duì)列中。同一個(gè)Stream隊(duì)列可以包含多個(gè)消費(fèi)組(Consumer Group),每個(gè)消費(fèi)組的狀態(tài)都是獨(dú)立的,同一個(gè)Stream隊(duì)列的消息可以被多個(gè)消費(fèi)組重復(fù)消費(fèi)。
同一個(gè)消費(fèi)組又包含多個(gè)消費(fèi)者(Consumer),這些消費(fèi)者之間是競爭關(guān)系,不同消費(fèi)者不會重復(fù)消費(fèi)同一條消息,任意一個(gè)消費(fèi)者讀取了隊(duì)列中的一條消息都會使消費(fèi)組中的游標(biāo)last_delivered_id往前移動。該方式提高了并發(fā)效率,例如,多個(gè)進(jìn)程并發(fā)處理Stream隊(duì)列中的消息。每個(gè)消費(fèi)者中維持一個(gè)狀態(tài)變量pending_ids,簡稱為PEL(Pending Entries List),記錄了當(dāng)前已經(jīng)被客戶端讀取的但尚未被ACK的消息,確保消息被客戶端成功消費(fèi)。
Redis Stream命令可以分為消息隊(duì)列命令和消費(fèi)者命令兩類,如下所示:
以即時(shí)通訊中的聊天室場景為例,使用Redis Stream作為中間件,實(shí)現(xiàn)聊天室的發(fā)言以及信息查看。
使用XADD命令進(jìn)行發(fā)言
使用XLEN命令獲取聊天室發(fā)言的數(shù)量
使用XRANGE獲取消息隊(duì)列的消息
使用XREAD命令讀取消息。可以在不設(shè)置消費(fèi)組和消費(fèi)者的情況下,使用XREAD的命令進(jìn)行消息讀取,此時(shí)Stream隊(duì)列類似于一個(gè)普通的列表(list)。
更多的Redis Stream命令使用請參考官方文檔(https://redis.io/commands/xread)。
二、應(yīng)用場景
由于Redis Stream天然有序,特別適合存儲時(shí)序數(shù)據(jù),應(yīng)用場景包括即時(shí)通訊、智慧醫(yī)療、流量削峰、智慧城市等領(lǐng)域。
(1)即時(shí)通訊:微信、QQ等是我們?nèi)粘I钪谐S玫耐ㄓ嵻浖S玫牧奶旆绞桨c(diǎn)對點(diǎn)通訊和群聊兩種方式。下圖是一個(gè)群聊的模型圖,當(dāng)采用Redis Stream作為通訊的中間件,創(chuàng)建一個(gè)群聊時(shí),在Redis中對應(yīng)地為該群聊創(chuàng)建一個(gè)Stream隊(duì)列。在發(fā)送消息時(shí),將每個(gè)用戶的消息按照時(shí)間順序添加到Stream隊(duì)列中,保證了消息的有序性。由于Stream是一個(gè)持久化的隊(duì)列,無論是在線還是離線狀態(tài),每個(gè)用戶可以多次查看歷史消息,保證了通訊的完整性。
(2)智慧醫(yī)療:醫(yī)療行業(yè)的信息化,可以更好地為服務(wù)于每一個(gè)人。為每一個(gè)人從出生起建立一份健康檔案,記錄相應(yīng)的健康信息,如體檢報(bào)告、診斷報(bào)告、用藥信息、以及智能終端實(shí)時(shí)上傳的健康指標(biāo)。這些信息都是一些時(shí)序數(shù)據(jù),同樣可以采用Redis Stream來實(shí)現(xiàn)智慧醫(yī)療系統(tǒng)。建立起智慧醫(yī)療系統(tǒng)后,使用終端可以查看所有的醫(yī)療信息,并會提示患者按時(shí)吃藥,在終端上傳身體指標(biāo)異常時(shí),會自動報(bào)警并預(yù)約掛號。現(xiàn)階段每個(gè)醫(yī)院都有自己的信息系統(tǒng),不同的醫(yī)院很難查到同一個(gè)患者的醫(yī)療信息,在未來,醫(yī)療上云將有利于解決醫(yī)療信息孤島,更好的幫助每一位患者。
(3)流量削峰:在常見的秒殺活動或團(tuán)購中,如春運(yùn)搶票、商城促銷等,通常短時(shí)間內(nèi)有大量的流量,導(dǎo)致系統(tǒng)崩潰。由于每一個(gè)用戶在請求時(shí)對應(yīng)唯一的時(shí)間戳,所有的請求都有一個(gè)先后順序,同樣可以采用Redis Stream作為中間件,將請求加入到Redis Stream消息隊(duì)列。將消息轉(zhuǎn)存到消息隊(duì)列間接提供給應(yīng)用,而非直接發(fā)送給應(yīng)用,可以防止大流量沖擊導(dǎo)致的系統(tǒng)崩潰。當(dāng)消息隊(duì)列中的請求數(shù)量達(dá)到規(guī)定的最大值時(shí),直接回復(fù)客戶端搶購失敗。
三、原生Redis是否真的適用于以上場景?
如上應(yīng)用場景具有數(shù)據(jù)規(guī)模大、數(shù)據(jù)持續(xù)增長的特點(diǎn),雖然原生Redis有良好的設(shè)計(jì)初衷,但是并不能解決實(shí)際問題。具體體現(xiàn)在:
無法有效應(yīng)對大規(guī)模數(shù)據(jù):原生Redis是一個(gè)基于內(nèi)存的數(shù)據(jù)庫,單個(gè)節(jié)點(diǎn)存儲容量有限,當(dāng)擴(kuò)展至TB級別的集群,將會出現(xiàn)管理困難,運(yùn)維成本高等問題。
集群擴(kuò)容影響業(yè)務(wù)性能:原生Redis在進(jìn)行集群擴(kuò)容時(shí),需要重新劃分hash槽并進(jìn)行數(shù)據(jù)遷移,必定會影響業(yè)務(wù)性能。
數(shù)據(jù)可能會丟失:原生Redis雖然可以采用RDB和AOF的方式對數(shù)據(jù)進(jìn)行持久化,但是并不會實(shí)時(shí)地將每一條命令寫入到硬盤中,當(dāng)出現(xiàn)掉電或集群崩潰的情況,必定會丟失一部分?jǐn)?shù)據(jù),對于類似智慧醫(yī)療場景,是難以忍受的。
除此以外,必須考慮數(shù)據(jù)庫系統(tǒng)的可用性、數(shù)據(jù)一致性、成本和備份恢復(fù)能力等情況:
可用性: 原生Redis若采用一主一備的集群模式,當(dāng)一對主備節(jié)點(diǎn)下線,集群部分?jǐn)?shù)據(jù)將不可用。
數(shù)據(jù)一致性:當(dāng)主節(jié)點(diǎn)宕機(jī),主備節(jié)點(diǎn)切換,數(shù)據(jù)存在沒有完全同步的情況。
成本:原生Redis是一種內(nèi)存型數(shù)據(jù)庫,當(dāng)內(nèi)存容量擴(kuò)展至TB級別,成本將非常昂貴。
備份恢復(fù):需要人工連接數(shù)據(jù)庫執(zhí)行 SAVE或BGSAVE命令,不能支持定期自動備份,在恢復(fù)到新實(shí)例時(shí)需要手動拷貝備份數(shù)據(jù)。
四、是否有更好的解決方案?
在以上場景中,亟需一種能夠存儲和處理大規(guī)模Stream數(shù)據(jù)、魯棒性強(qiáng)、且成本低廉的數(shù)據(jù)庫系統(tǒng)。而GaussDB(for Redis)(下文簡稱高斯Redis)正是以上場景中一種很好的應(yīng)用解決方案。高斯Redis是華為云數(shù)據(jù)庫團(tuán)隊(duì)自主研發(fā)的兼容Redis協(xié)議的云原生數(shù)據(jù)庫,該數(shù)據(jù)庫突破原生Redis的內(nèi)存限制,可輕松擴(kuò)展至PB級存儲,具有秒擴(kuò)容、超可用、強(qiáng)一致和低成本等特點(diǎn)。
五、總結(jié)
Redis Stream可以廣泛應(yīng)用在即時(shí)通訊、智慧醫(yī)療、流量削峰等領(lǐng)域。在面對大規(guī)模的Stream數(shù)據(jù)時(shí),原生Redis存在成本過高、容量太小、可用性差、數(shù)據(jù)不一致等問題,無法適用于海量消息隊(duì)列的場景。與原生Redis相比,高斯Redis具有海量存儲,低成本,可持久化等優(yōu)點(diǎn),可做為比原生Redis更理想的Stream隊(duì)列承載方案。
杭州/西安/深圳簡歷投遞:yuwenlong4@huawei.com
GaussDB(for Redis)產(chǎn)品主頁:
https://www.huaweicloud.com/product/gaussdbforredis.html
更多技術(shù)文章,關(guān)注GaussDB(for Redis)官方博客:
https://bbs.huaweicloud.com/community/usersnew/id_1614151726110813
Redis 云數(shù)據(jù)庫 GaussDB(for Redis) 數(shù)據(jù)庫
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。