Redis有哪些部署方案?了解哨兵機制嗎?
Redis有哪些部署方案?
- 單機版:單機部署,單機Redis能夠承載的 QPS 大概就在上萬到幾萬不等。這種部署方式很少使用。存在的問題:1、內(nèi)存容量有限 2、處理能力有限 3、無法高可用。
- 主從模式:一主多從,主負責寫,并且將數(shù)據(jù)復(fù)制到其它的 slave 節(jié)點,從節(jié)點負責讀。所有的讀請求全部走從節(jié)點。這樣也可以很輕松實現(xiàn)水平擴容,支撐讀高并發(fā)。master 節(jié)點掛掉后,需要手動指定新的 master,可用性不高,基本不用。
- 哨兵模式:主從復(fù)制存在不能自動故障轉(zhuǎn)移、達不到高可用的問題。哨兵模式解決了這些問題。通過哨兵機制可以自動切換主從節(jié)點。master 節(jié)點掛掉后,哨兵進程會主動選舉新的 master,可用性高,但是每個節(jié)點存儲的數(shù)據(jù)是一樣的,浪費內(nèi)存空間。數(shù)據(jù)量不是很多,集群規(guī)模不是很大,需要自動容錯容災(zāi)的時候使用。
- Redis cluster:服務(wù)端分片技術(shù),3.0版本開始正式提供。Redis Cluster并沒有使用一致性hash,而是采用slot(槽)的概念,一共分成16384個槽。將請求發(fā)送到任意節(jié)點,接收到請求的節(jié)點會將查詢請求發(fā)送到正確的節(jié)點上執(zhí)行。主要是針對海量數(shù)據(jù)+高并發(fā)+高可用的場景,如果是海量數(shù)據(jù),如果你的數(shù)據(jù)量很大,那么建議就用Redis cluster,所有主節(jié)點的容量總和就是Redis cluster可緩存的數(shù)據(jù)容量。
主從架構(gòu)
單機的 Redis,能夠承載的 QPS 大概就在上萬到幾萬不等。對于緩存來說,一般都是用來支撐讀高并發(fā)的。因此架構(gòu)做成主從(master-slave)架構(gòu),一主多從,主負責寫,并且將數(shù)據(jù)復(fù)制到其它的 slave 節(jié)點,從節(jié)點負責讀。所有的讀請求全部走從節(jié)點。這樣也可以很輕松實現(xiàn)水平擴容,支撐讀高并發(fā)。
Redis的復(fù)制功能是支持多個數(shù)據(jù)庫之間的數(shù)據(jù)同步。主數(shù)據(jù)庫可以進行讀寫操作,當主數(shù)據(jù)庫的數(shù)據(jù)發(fā)生變化時會自動將數(shù)據(jù)同步到從數(shù)據(jù)庫。從數(shù)據(jù)庫一般是只讀的,它會接收主數(shù)據(jù)庫同步過來的數(shù)據(jù)。一個主數(shù)據(jù)庫可以有多個從數(shù)據(jù)庫,而一個從數(shù)據(jù)庫只能有一個主數(shù)據(jù)庫。
主從復(fù)制的原理?
Redis 的主從復(fù)制是指一個 Redis 實例(主節(jié)點)可以將數(shù)據(jù)復(fù)制到一個或多個從節(jié)點(從節(jié)點),從節(jié)點從主節(jié)點獲取數(shù)據(jù)并保持同步。
- 開始同步:從節(jié)點通過向主節(jié)點發(fā)送PSNC命令發(fā)起同步,
- 全量復(fù)制:如果是第一次連接或之前的連接失效,從節(jié)點會請求全量復(fù)制,主節(jié)點將當前數(shù)據(jù)快照(RDB文件)發(fā)送給從節(jié)點。
- 增量復(fù)制:全量復(fù)制完畢后,主從之間會保持一個長連接,主節(jié)點會通過這個連接將后續(xù)的寫操作傳遞給從節(jié)點執(zhí)行,來保證數(shù)據(jù)的一致。
詳細流程如下:
- 當啟動一個從節(jié)點時,它會發(fā)送一個
PSYNC命令給主節(jié)點; - 全量復(fù)制:如果是從節(jié)點初次連接到主節(jié)點,那么會觸發(fā)一次全量復(fù)制。此時主節(jié)點會啟動一個后臺線程,開始生成一份
RDB快照文件; - 同時還會將從客戶端 client 新收到的所有寫命令緩存在內(nèi)存中。
RDB文件生成完畢后, 主節(jié)點會將RDB文件發(fā)送給從節(jié)點,從節(jié)點會先將RDB文件寫入本地磁盤,然后再從本地磁盤加載到內(nèi)存中; - 接著主節(jié)點會將內(nèi)存中緩存的寫命令發(fā)送到從節(jié)點,從節(jié)點同步這些數(shù)據(jù);
- 增量同步:如果從節(jié)點跟主節(jié)點之間網(wǎng)絡(luò)出現(xiàn)故障,連接斷開了,會自動重連,連接之后主節(jié)點僅會將部分缺失的數(shù)據(jù)同步給從節(jié)點。
主從復(fù)制存在的問題
Redis的主從模式重點在于解決整體的承壓能力,利用從節(jié)點分擔讀取操作的壓力。但是其在容錯恢復(fù)等可靠性層面欠缺明顯,不具備自動的故障轉(zhuǎn)移與恢復(fù)能力:
- 如果slave從節(jié)點宕機,整個redis依舊可以正常提供服務(wù),待slave節(jié)點重新啟動后,可以恢復(fù)從master節(jié)點的數(shù)據(jù)同步、然后繼續(xù)提供服務(wù)。
- 如果master主節(jié)點宕機,則redis功能受損,無法繼續(xù)提供寫服務(wù),直到手動修復(fù)master節(jié)點方可恢復(fù)。
當然,master節(jié)點故障后,也可以手動將其中一個從節(jié)點切換為新的master節(jié)點來恢復(fù)故障。而原先的master節(jié)點恢復(fù)后,需要手動將其降級為slave節(jié)點,對外提供只讀服務(wù)。
實際使用的時候,手動故障恢復(fù)的時效無法得到保證,為了支持自動的故障轉(zhuǎn)移與恢復(fù)能力,Redis在主從模式的基礎(chǔ)上進行優(yōu)化增強,提供了哨兵(Sentinel)架構(gòu)模式。
那么就需要有一個機制,能夠監(jiān)測主節(jié)點是否存活,如果發(fā)現(xiàn)主節(jié)點掛了,就選舉一個從節(jié)點切換為主節(jié)點,并且把新主節(jié)點的相關(guān)信息通知給從節(jié)點和客戶端。這就是哨兵機制。
圖片
Redis 復(fù)制延遲的常見原因有哪些?
Redis 的復(fù)制延遲是指從節(jié)點同步主節(jié)點數(shù)據(jù)時可能出現(xiàn)時間延遲。在讀寫分離場景,這個延遲會導(dǎo)致明明寫入了數(shù)據(jù),但是去從節(jié)點查的時候沒查到。
可能原因如下:
- 網(wǎng)絡(luò)原因:可能是帶寬不足,或者網(wǎng)絡(luò)抖動導(dǎo)致同步的延遲,不過一般內(nèi)網(wǎng)情況下不會產(chǎn)生這個問題。
- 主節(jié)點負載過高主節(jié)點接收到大量的寫操作,在處理客戶端請求的同時,還需向從節(jié)點發(fā)送復(fù)制數(shù)據(jù)。如果主節(jié)點負載較高時,來不及處理從服務(wù)的復(fù)制請求,就會導(dǎo)致復(fù)制延遲。大量寫操作無法避免。但是我們可優(yōu)化下寫入的結(jié)構(gòu),精簡數(shù)據(jù),降低單條數(shù)據(jù)的大小。
- 復(fù)制緩存區(qū)溢出:復(fù)制緩存區(qū)暫存當前主節(jié)點接收到的寫命令,待傳輸給從節(jié)點。如果從節(jié)點處理過慢,寫入的命令又過多,則會導(dǎo)致復(fù)制緩沖區(qū)溢出,此時從節(jié)點就需要重新執(zhí)行全量復(fù)制,導(dǎo)致延遲??赏ㄟ^ client-output-buffer-limit間接控制緩沖區(qū)大小
- 主節(jié)點持久化,無法及時響應(yīng)復(fù)制請求:生成 RDB 快照或 AOF 文件重寫都會占用大量的 CPU 和 I/O 資源,可能會影響復(fù)制的速度。避免在高峰期觸發(fā)持久化動作。
- 從節(jié)點配置太差:因為從節(jié)點需要接收、處理和存儲主節(jié)點發(fā)送的數(shù)據(jù)。如果從節(jié)點性能較低,處理數(shù)據(jù)的速度會慢,從而導(dǎo)致延遲。此時需要升配。
Redis 的哨兵機制是什么?
Redis 的哨兵機制(Sentinel)是一種高可用性解決方案,用于監(jiān)控 Redis 主從集群,自動完成主從切換,以實現(xiàn)故障自動恢復(fù)和通知。主要功能包括:
- 監(jiān)控:哨兵不斷監(jiān)控 Redis 主節(jié)點和從節(jié)點的運行狀態(tài),定期發(fā)送 PING 請求檢查節(jié)點是否正常。
- 自動故障轉(zhuǎn)移:當主節(jié)點發(fā)生故障時,哨兵會選舉一個從節(jié)點提升為新的主節(jié)點,并通知客戶端更新主節(jié)點的地址,從而實現(xiàn)高可用。
- 通知:哨兵可以向系統(tǒng)管理員或其他服務(wù)發(fā)送通知,以便快速處理 Redis 實例的狀態(tài)變化。
哨兵Sentinel工作原理?
- 每個
Sentinel以每秒鐘一次的頻率向它所知道的Master,Slave以及其他Sentinel實例發(fā)送一個PING命令。 - 如果一個實例距離最后一次有效回復(fù)
PING命令的時間超過指定值, 則這個實例會被Sentine標記為主觀下線。 - 如果一個
Master被標記為主觀下線,則正在監(jiān)視這個Master的所有Sentinel要以每秒一次的頻率確認Master是否真正進入主觀下線狀態(tài)。 - 當有足夠數(shù)量的
Sentinel(大于等于配置文件指定值)在指定的時間范圍內(nèi)確認Master的確進入了主觀下線狀態(tài), 則Master會被標記為客觀下線 。若沒有足夠數(shù)量的Sentinel同意Master已經(jīng)下線,Master的客觀下線狀態(tài)就會被解除。 若Master重新向Sentinel的PING命令返回有效回復(fù),Master的主觀下線狀態(tài)就會被移除。 - 哨兵節(jié)點會選舉出哨兵 leader,負責故障轉(zhuǎn)移的工作。
- 哨兵 leader 會推選出某個表現(xiàn)良好的從節(jié)點成為新的主節(jié)點,然后通知其他從節(jié)點更新主節(jié)點信息。
Redis cluster實現(xiàn)原理?
哨兵模式解決了主從復(fù)制不能自動故障轉(zhuǎn)移、達不到高可用的問題,但還是存在主節(jié)點的寫能力、容量受限于單機配置的問題。而cluster模式實現(xiàn)了Redis的分布式存儲,每個節(jié)點存儲不同的內(nèi)容,解決主節(jié)點的寫能力、容量受限于單機配置的問題。
Redis cluster集群節(jié)點最小配置6個節(jié)點以上(3主3從),其中主節(jié)點提供讀寫操作,從節(jié)點作為備用節(jié)點,不提供請求,只作為故障轉(zhuǎn)移使用。
Redis cluster采用虛擬槽分區(qū),所有的鍵根據(jù)哈希函數(shù)映射到0~16383個整數(shù)槽內(nèi),每個節(jié)點負責維護一部分槽以及槽所映射的鍵值數(shù)據(jù)。
圖片
工作原理:
- 通過哈希的方式,將數(shù)據(jù)分片,每個節(jié)點均分存儲一定哈希槽(哈希值)區(qū)間的數(shù)據(jù),默認分配了16384 個槽位
- 每份數(shù)據(jù)分片會存儲在多個互為主從的多節(jié)點上
- 數(shù)據(jù)寫入先寫主節(jié)點,再同步到從節(jié)點(支持配置為阻塞同步)
- 同一分片多個節(jié)點間的數(shù)據(jù)不保持一致性
- 讀取數(shù)據(jù)時,當客戶端操作的key沒有分配在該節(jié)點上時,redis會返回轉(zhuǎn)向指令,指向正確的節(jié)點
- 擴容時時需要需要把舊節(jié)點的數(shù)據(jù)遷移一部分到新節(jié)點
在 Redis cluster 架構(gòu)下,每個 redis 要放開兩個端口號,比如一個是 6379,另外一個就是 加1w 的端口號,比如 16379。
16379 端口號是用來進行節(jié)點間通信的,也就是 cluster bus 的東西,cluster bus 的通信,用來進行故障檢測、配置更新、故障轉(zhuǎn)移授權(quán)。cluster bus 用了另外一種二進制的協(xié)議,gossip 協(xié)議,用于節(jié)點間進行高效的數(shù)據(jù)交換,占用更少的網(wǎng)絡(luò)帶寬和處理時間。
優(yōu)點:
- 無中心架構(gòu),支持動態(tài)擴容。
- 數(shù)據(jù)按照
slot存儲分布在多個節(jié)點,節(jié)點間數(shù)據(jù)共享,可動態(tài)調(diào)整數(shù)據(jù)分布。 - 高可用性。部分節(jié)點不可用時,集群仍可用。集群模式能夠?qū)崿F(xiàn)自動故障轉(zhuǎn)移(failover),節(jié)點之間通過
gossip協(xié)議交換狀態(tài)信息,用投票機制完成Slave到Master的角色轉(zhuǎn)換。
缺點:
- 不支持批量操作(pipeline)。
- 數(shù)據(jù)通過異步復(fù)制,不保證數(shù)據(jù)的強一致性。
- 事務(wù)操作支持有限,只支持多
key在同一節(jié)點上的事務(wù)操作,當多個key分布于不同的節(jié)點上時無法使用事務(wù)功能。 key作為數(shù)據(jù)分區(qū)的最小粒度,不能將一個很大的鍵值對象如hash、list等映射到不同的節(jié)點。- 不支持多數(shù)據(jù)庫空間,單機下的Redis可以支持到16個數(shù)據(jù)庫,集群模式下只能使用1個數(shù)據(jù)庫空間。
- 只能使用0號數(shù)據(jù)庫。
Redis Cluster 模式與 Sentinel 模式的區(qū)別是什么?
- Redis Cluster 是 Redis 集群,提供自動分片功能,將數(shù)據(jù)自動分布在多個節(jié)點上,支持自動故障轉(zhuǎn)移。如果一個節(jié)點失敗,集群會自動重新配置和平衡,不需要外部介入,因為它內(nèi)置了哨兵邏輯。
- Sentinel是哨兵,主要用于管理多個 Redis 服務(wù)器實例來提高數(shù)據(jù)的高可用性。當主節(jié)點宕機,哨兵會將從節(jié)點提升為主節(jié)點,它并不提供數(shù)據(jù)分片功能。如果需要處理大量數(shù)據(jù)并進行數(shù)據(jù)分片,應(yīng)選擇 Redis Cluster,它支持水平擴展,適用于大規(guī)模數(shù)據(jù)、高吞吐量場景。
如果只是為了提高 Redis 實例的可用性,并不需要數(shù)據(jù)分片,應(yīng)選擇 主從+Sentinel,它主要關(guān)注故障轉(zhuǎn)移和實例高可用,適用于高可用性、讀寫分離場景。
Redis 集群會出現(xiàn)腦裂問題嗎?
Redis 集群存在腦裂問題的風險,特別是在網(wǎng)絡(luò)分區(qū)的情況下,可能會導(dǎo)致同一集群內(nèi)出現(xiàn)多個主節(jié)點,導(dǎo)致數(shù)據(jù)不一致。
Redis 中如何避免腦裂問題的發(fā)生呢?
這里需要了解兩個參數(shù):
- min-slaves-to-write:設(shè)置主節(jié)點在至少有指定數(shù)量的從節(jié)點確認寫操作的情況下才執(zhí)行寫操作。
- min-salves-max-lag:設(shè)置從節(jié)點的最大延遲(以秒為單位),如果從節(jié)點的延遲超過這個值,則該從節(jié)點不會被計入 min-slaves-to-write 的計數(shù)中 舉個例子:當 min-slaves-to-write設(shè)置為2,min-slaves-max-lag設(shè)置為 10 秒時,主節(jié)點只有在至少有2 個從節(jié)點延遲不超過 10 秒的情況下才會接受寫操作,這兩個參數(shù)就使得發(fā)生腦裂的時候,如果某個主節(jié)點跟隨的從節(jié)點數(shù)量不夠或延遲較大,就無法被寫入,這樣就能避免腦裂導(dǎo)致的數(shù)據(jù)不一致。建議集群部署奇數(shù)個節(jié)點,例如集群數(shù)為5,那么可以設(shè)置 min-slaves-to-write為3,min-slaves-max-lag為 5-10 秒。
腦裂問題能完全避免嗎?
并不能。即使配置了以上兩個參數(shù)也可能會因為腦裂導(dǎo)致數(shù)據(jù)不一致。
舉個例子,假設(shè)某個主節(jié)點臨時出了問題,哨兵判斷它主觀下線,然后開始發(fā)起選舉。在選舉進行的時候,主節(jié)點恢復(fù)了,此時它還是跟著很多從節(jié)點,假設(shè) min-slaves-max-log 配置了10s,可能此時從節(jié)點和主節(jié)點延遲的時間才 6s,因此此時主節(jié)點還是可以被寫入。而等選舉完畢了,選出新的主節(jié)點,舊的主節(jié)點被哨兵操作需要 salveof 新主,此時選舉時間內(nèi)寫入的數(shù)據(jù)會被覆蓋,因此就導(dǎo)致了數(shù)據(jù)不一致的問題
哈希分區(qū)算法有哪些?
- 節(jié)點取余分區(qū)。 使用特定的數(shù)據(jù),如Redis的鍵或用戶ID,對節(jié)點數(shù)量N取余:hash(key)%N計算出哈希值,用來決定數(shù)據(jù)映射到哪一個節(jié)點上。
優(yōu)點是簡單性。擴容時通常采用翻倍擴容,避免數(shù)據(jù)映射全部被打亂導(dǎo)致全量遷移的情況。
- 一致性哈希分區(qū)。
為系統(tǒng)中每個節(jié)點分配一個token,范圍一般在0~232,這些token構(gòu)成一個哈希環(huán)。數(shù)據(jù)讀寫執(zhí)行節(jié)點查找操作時,先根據(jù)key計算hash值,然后順時針找到第一個大于等于該哈希值的token節(jié)點。
這種方式相比節(jié)點取余最大的好處在于加入和刪除節(jié)點只影響哈希環(huán)中相鄰的節(jié)點,對其他節(jié)點無影響。
- 虛擬Hash槽分區(qū)
所有的鍵根據(jù)哈希函數(shù)映射到0~16383整數(shù)槽內(nèi),計算公式:slot=CRC16(key)&16383。每一個節(jié)點負責維護一部分槽以及槽所映射的鍵值數(shù)據(jù)。Redis Cluser采用虛擬槽分區(qū)算法。
為什么Redis集群采用“hash槽”來解決數(shù)據(jù)分配問題,而不采用“一致性hash”算法呢?
- 一致性哈希的節(jié)點分布基于圓環(huán),無法很好的手動控制數(shù)據(jù)分布,比如有些節(jié)點的硬件差,希望少存一點數(shù)據(jù),這種很難操作(還得通過虛擬節(jié)點映射,總之較繁瑣)。
- 而redis集群的槽位空間是可以用戶手動自定義分配的,類似于 windows 盤分區(qū)的概念,可以手動控制大小。
- 其實,無論是 “一致性哈希” 還是 “hash槽” 的方式,在增減節(jié)點的時候,都會對一部分數(shù)據(jù)產(chǎn)生影響,都需要我們遷移數(shù)據(jù)。當然,redis集群也提供了相關(guān)手動遷移槽數(shù)據(jù)的命令。
為什么 Redis 集群的最大槽數(shù)是 16384 個?
Redis Cluster 采用數(shù)據(jù)分片機制,定義了 16384個 Slot槽位,集群中的每個Redis 實例負責維護一部分槽以及槽所映射的鍵值數(shù)據(jù)。
Redis每個節(jié)點之間會定期發(fā)送ping/pong消息(心跳包包含了其他節(jié)點的數(shù)據(jù)),用于交換數(shù)據(jù)信息。
Redis集群的節(jié)點會按照以下規(guī)則發(fā)ping消息:
- 每秒會隨機選取5個節(jié)點,找出最久沒有通信的節(jié)點發(fā)送ping消息。
- 每100毫秒都會掃描本地節(jié)點列表,如果發(fā)現(xiàn)節(jié)點最近一次接受pong消息的時間大于cluster-node-timeout/2 則立刻發(fā)送ping消息。
心跳包的消息頭里面有個myslots的char數(shù)組,是一個bitmap,每一個位代表一個槽,如果該位為1,表示這個槽是屬于這個節(jié)點的。
接下來,解答為什么 Redis 集群的最大槽數(shù)是 16384 個,而不是65536 個。
- 如果采用 16384 個插槽,那么心跳包的消息頭占用空間 2KB (16384/8);如果采用 65536 個插槽,那么心跳包的消息頭占用空間 8KB (65536/8)。可見采用 65536 個插槽,發(fā)送心跳信息的消息頭達8k,比較浪費帶寬。
- 一般情況下一個Redis集群不會有超過1000個master節(jié)點,太多可能導(dǎo)致網(wǎng)絡(luò)擁堵。
- 哈希槽是通過一張bitmap的形式來保存的,在傳輸過程中,會對bitmap進行壓縮。bitmap的填充率越低,壓縮率越高。其中bitmap 填充率 = slots / N (N表示節(jié)點數(shù))。所以,插槽數(shù)越低, 填充率會降低,壓縮率會提高。
在 Redis 集群中,如何根據(jù)鍵定位到對應(yīng)的節(jié)點?
Redis 集群將數(shù)據(jù)分布到 16384 個哈希槽(sots),每個鍵通過哈希函數(shù)計算出一個槽位編號,然后根據(jù)槽位編號定位到縣體的節(jié)點,具體是使用 CRC16 哈希函數(shù)計算鍵的哈希值,然后對 16384 取模, 得到哈希槽編號(范圍是0到16383)。
Redis集群會有寫操作丟失嗎?為什么?
在Redis集群中,由于采用了主從復(fù)制模型的異步復(fù)制機制,寫操作有一定的丟失風險。
當客戶端向主節(jié)點發(fā)送寫操作時,主節(jié)點會立即返回成功響應(yīng),而不等待所有從節(jié)點執(zhí)行復(fù)制。如果主節(jié)點在執(zhí)行完寫操作后出現(xiàn)故障或網(wǎng)絡(luò)問題,導(dǎo)致從節(jié)點無法及時接收到復(fù)制操作,那么這些未復(fù)制的寫操作將會丟失。
為了減少寫操作丟失的可能性,可以采取以下措施:
- 定期監(jiān)測集群狀態(tài),確保主從節(jié)點之間的復(fù)制正常進行;
- 設(shè)置合理的持久化策略,將數(shù)據(jù)寫入磁盤或使用AOF模式以便數(shù)據(jù)恢復(fù);
- 在應(yīng)用程序?qū)訉嵤?shù)據(jù)確認機制,檢查寫操作是否成功。
Redis 中如何保證緩存與數(shù)據(jù)庫的數(shù)據(jù)一致性?
- 先更新緩存,再更新數(shù)據(jù)庫
- 先更新數(shù)據(jù)庫存,再更新緩存
- 先刪除緩存,再更新數(shù)據(jù)庫,后續(xù)等查詢把數(shù)據(jù)庫的數(shù)據(jù)回種到緩存中
- 先更新數(shù)據(jù)庫,再刪除緩存,后續(xù)等查詢把數(shù)據(jù)庫的數(shù)據(jù)回種到緩存中
- 緩存雙刪策略。更新數(shù)據(jù)庫之前,刪除一次緩存;更新完數(shù)據(jù)庫后,再進行一次延遲刪除
- 使用 Binlog 異步更新緩存,監(jiān)聽數(shù)據(jù)庫的 Binlog 變化,通過異步方式更新 Redis 緩存
以上就是實現(xiàn)數(shù)據(jù)庫與緩存一致性的六種方式,這里前面三種都不太推薦使用,后面三種需要根據(jù)實際場景選擇:
- 如果是要考慮實時一致性的話,先寫 MySQL,再刪除 Redis 應(yīng)該是較為優(yōu)的方案,雖然短期內(nèi)數(shù)據(jù)可能不一致,不過其能盡量保證數(shù)據(jù)的一致性。
- 如果考慮最終一致性的話,推薦的是使用 binlog + 消息隊列的方式,這個方案其有重試和順序消費,能夠最大限度地保證緩存與數(shù)據(jù)庫的最終一致性:。

































