緩存數(shù)據(jù)丟了,原來是Redis持久化沒玩明白
我們都知道Redis是微服務(wù)架構(gòu)中重要的基礎(chǔ)數(shù)據(jù)庫中間件,通過Redis可以將數(shù)據(jù)庫中的數(shù)據(jù)緩存到內(nèi)存中,當(dāng)服務(wù)端有數(shù)據(jù)查詢請求的時候,可以直接從內(nèi)存中獲取數(shù)據(jù)。如此,一方面服務(wù)端可以獲得比較快的數(shù)據(jù)請求響應(yīng),另一方面降低了后端關(guān)系數(shù)據(jù)庫的業(yè)務(wù)請求壓力。但是正所謂尺有所短,寸有所長,Redis最大的優(yōu)勢就是內(nèi)存數(shù)據(jù)也是最大的劣勢,因為一旦服務(wù)器宕機或者服務(wù)器重啟,內(nèi)存中緩存的數(shù)據(jù)也會丟失。針對這樣的場景,Redis提供了三種數(shù)據(jù)持久化機制,分別是AOF、RDB以及混合持久化來應(yīng)對這種異常情況。本文主要從Redis實現(xiàn)持久化遇到的問題出發(fā),站在設(shè)計者的角度思考相關(guān)問題的解決思路。
?
AOF持久化
AOF持久化方式,即Append Only File,Redis通過記錄執(zhí)行修改操作命令這種記小本本的方式進行內(nèi)存數(shù)據(jù)持久化。當(dāng)需要通過AOF日志進行恢復(fù)數(shù)據(jù)時,Redis服務(wù)端啟動后可以從日志文件中回放執(zhí)行命令來實現(xiàn)內(nèi)存數(shù)據(jù)恢復(fù)。當(dāng)然了,AOF日志中記錄的都是修改的命令,查詢命令不會修改數(shù)據(jù)所以不需要進行記錄。
可能大家都比較熟悉WAL(Write Ahead Log),即日志預(yù)寫機制,它是數(shù)據(jù)庫非常常用的確保數(shù)據(jù)操作原子性以及持久性的技術(shù)手段。拿Mysql舉栗子,Mysql的WAL體現(xiàn)在undo log以及redo log等這些日志文件中,數(shù)據(jù)庫在執(zhí)行修改操作的時候并不是立刻將數(shù)據(jù)更新到磁盤上,而是先記錄在日志中,主要目的是如果出現(xiàn)異常,可以直接從redo log中進行數(shù)據(jù)恢復(fù),也就是說讓Mysql知道上次意外發(fā)生的時候操作到底有沒有成功,另外還可以將Mysql的隨機寫轉(zhuǎn)換為順序?qū)懀嵘齀O性能。但是AOF卻不同,它是在Redis將數(shù)據(jù)寫入內(nèi)存之后,再將相關(guān)的操作命令寫入AOF文件中。

那么問題來了,為什么Redis要采取這種獨特的數(shù)據(jù)記錄方式,而不是業(yè)界常用的WAL的方式呢?其實可以從以下兩個層面思考原因。
(1)AOF文件中保存了執(zhí)行緩存的命令,以便于保證在需要恢復(fù)數(shù)據(jù)的時候可以進行命令重放恢復(fù)數(shù)據(jù),因此需要保證執(zhí)行命令的合法性,而通過先緩存數(shù)據(jù)再進行命令追加日志的方式可以確保追加到AOF文件中的的命令都是合法有效的,redis在恢復(fù)數(shù)據(jù)的時候不需要再去檢查命令是否有效,進一步提升內(nèi)存數(shù)據(jù)恢復(fù)的效率。
(2)另外由于是在修改操作命令之后進行日志記錄,日志記錄的時候需要進行磁盤IO操作,因此不會阻塞當(dāng)前的修改命令。
AOF文件內(nèi)容是什么?
在搞清楚Redis為什么采用AOF文件記錄修改命令之后,我們再來看看AOF文件中到底包含了哪些內(nèi)容。
Redis客戶端與服務(wù)端之間采用RESP協(xié)議進行通信,它是一種應(yīng)用層協(xié)議,對于Redis這種以效率為追求目標的中間件,通信協(xié)議必定要簡單高效。就上面一條緩存操作命令來說:set mufeng handsome 對應(yīng)的RESP報文就是*3$3set$6mufeng$8handsome,為了方便查看進行了手動換行。

我們來拆解下報文中各個屬性的含義,“*3”代表本次操作命令將由三個分布組成,每一部分都是通過"$數(shù)字"的形式作為起始,后面為對應(yīng)的命令、鍵或者值。如此處的"$6"就表示后面的命令是一個6個字節(jié)的鍵值。所以,appenonly.aof文件中實際保存的就是這種格式的內(nèi)容。

AOF有沒有丟數(shù)據(jù)的風(fēng)險?
上文說到Redis通過AOF文件實現(xiàn)內(nèi)存數(shù)據(jù)持久化,那么是不是就代表緩存數(shù)據(jù)保存就萬無一失了?這樣的持久化方式還有沒有數(shù)據(jù)丟失的風(fēng)險呢?大家可以設(shè)想一下假設(shè)在操作完Redis之后,還沒來得及將命令寫入AOF文件就宕機了,那么這個操作命令就會丟失,對應(yīng)的緩存數(shù)據(jù)最新值也會丟失。因為即便宕機異常恢復(fù)之后,也沒辦法從AOF文件中執(zhí)行丟失的操作命令了。因此,寫入AOF緩沖區(qū)的數(shù)據(jù)什么時候進行持久化落盤,直接決定著AOF持久化方式緩存數(shù)據(jù)丟失的風(fēng)險大小。
三種AOF落盤策略
針對AOF緩存中的數(shù)據(jù)在什么時機寫入磁盤,Redis提供了三種AOF日志寫入策略供用戶進行選擇,通過后臺線程執(zhí)行不同時機的AOF文件數(shù)據(jù)同步操作,在redis.conf配置文件中的配置項appendfsync可以進行配置。
【appendfsync:no】?
Redis不用管AOF緩沖區(qū)的數(shù)據(jù)什么時候?qū)懭氪疟P,將AOF緩沖區(qū)同步數(shù)據(jù)的操作權(quán)交給操作系統(tǒng),操作系統(tǒng)決定什么時候?qū)⒕彌_區(qū)的數(shù)據(jù)寫入磁盤中。
【appendfsync:everysec】
當(dāng)Redis將數(shù)據(jù)寫入AOF緩沖區(qū)后,每隔1s將緩沖區(qū)的數(shù)據(jù)進行磁盤寫入。
【appendfsync:always】?
每執(zhí)行一個修改命令,都需要將修改的命令進行落盤操作。
雖然Redis提供了這三種AOF日志落盤策略供用戶進行選擇,但是這三種策略實際上各有優(yōu)缺點。
【appendfsync:no】
如果設(shè)置了由操作系統(tǒng)進行AOF緩沖區(qū)數(shù)據(jù)寫入,那么就相當(dāng)于寫數(shù)據(jù)的時機完全交由操作系統(tǒng)來決定,此時redis對于緩沖區(qū)數(shù)據(jù)并不可以控制。
【appendfsync:everysec】
如果設(shè)置成每隔一秒進行緩存數(shù)據(jù)寫入,雖然不會像同步寫入那樣存在一定的性能消耗,但是由于存在一秒的時間間隔,如果在此期間出現(xiàn)服務(wù)器宕機,那么就會損失這一秒的緩存數(shù)據(jù)。
【appendfsync:always】
雖然可以基本實現(xiàn)數(shù)據(jù)不丟失,但是由于每次進行內(nèi)存數(shù)據(jù)修改都要進行落盤操作,因此在一定程度上會影響主線程性能。
具體采取怎樣的配置策略還是要根據(jù)實際的業(yè)務(wù)場景來決定,一般推薦使用第二種配置策略【appendfsync:everysec】,在可靠性以及性能方面相對平衡一點。
AOF文件會越來越大嗎?
在了解了AOF日志磁盤寫入時機之后,我們繼續(xù)來思考下一個問題。無論采取什么樣的同步數(shù)據(jù)策略,最終都是要將修改命令寫入AOF文件中,因此隨著時間的推移,這個文件必定會越來越大。那么如果文件變得很大之后,無論是文件數(shù)據(jù)新寫入還是Redis通過AOF文件進行數(shù)據(jù)恢復(fù),大文件的操作都會造成IO性能損耗。假如你是Redis的設(shè)計者,如果遇到這種情況你會怎么進行設(shè)計優(yōu)化呢?我想無非有兩個優(yōu)化思路,一個是化整為零,一個是想辦法縮小大文件。
化整為零
當(dāng)單個文件過大時,我們很容易想到的優(yōu)化方法就是將這個大文件拆分為若干個小文件。這就好比系統(tǒng)中一旦出現(xiàn)過千萬數(shù)據(jù)庫表的時候,我們就要結(jié)合實際的業(yè)務(wù)場景考慮要不要進行分庫分表了。所以如果單個AOF文件太大,那么是不是可以考慮將其按照固定大小進行拆分,這樣可以避免單個AOF文件過大的問題。那么Redis小于7.0版本為什么沒有采用這種方案呢?主要是這種方案并不符合Redis追求簡單高效的設(shè)計思想。假設(shè)采用了這種數(shù)據(jù)分塊的方式,那必定需要實現(xiàn)文件大小檢測、文件創(chuàng)建、文件索引維護等等一系列技術(shù)細節(jié)問題,對于低版本的Redis來說這些都太繁瑣了,還不如一個AOF文件來的爽快。
PS:在最新的Redis 7.0版本中,Redis已經(jīng)支持多AOF文件分片機制,原始的單個AOF文件會被拆分為一個基礎(chǔ)文件以及多個增量文件。新版本中之所以開始支持多文件存儲,我想也是隨著業(yè)務(wù)發(fā)展內(nèi)存數(shù)據(jù)可能會很龐大,Redis設(shè)計者發(fā)現(xiàn)如果還是使用單文件存儲,大AOF文件操作以及數(shù)據(jù)恢復(fù)都是一個挑戰(zhàn)。

AOF重寫
既然進行文件切割太繁瑣了,那么就單個AOF文件來說怎么才能減小文件大小呢?那就要從AOF文件的記錄內(nèi)容入手,通過上文我們了解到AOF文件中實際存儲了修改內(nèi)存數(shù)據(jù)的操作命令,因此我們在分析完這些操作命令之后發(fā)現(xiàn),當(dāng)多條命令操作同一個key的時候,實際我們需要的是最新的一條操作命令,除此之外的歷史操作命令我們并不需要關(guān)心。比如【set mufeng handsome】、【set mufeng cool】,如果先后執(zhí)行了這兩個命令,那么在最終恢復(fù)數(shù)據(jù)的時候,只要恢復(fù)【set mufeng cool】即可。因此AOF重寫的本質(zhì)就是合并命令,也就是說將多條對同一key進行操作的命令進行合并,實際就是使用最新的key值操作命令來代替之前所有關(guān)于這個key值的命令。
Redis通過fork子進程來完成AOF文件重寫,因此在講AOF重寫過程之前,我們需要先了解下什么是fork子進程的原理,這樣更加有利于我們后面了解AOF文件重寫的過程。
什么是fork?
fork函數(shù)是linux內(nèi)核提供給用戶創(chuàng)建進程的API,應(yīng)用程序通過調(diào)用fork函數(shù)創(chuàng)建子進程,這個子進程可以和原來父進程干同樣的事情,也可以和原來主進程干不同的事情,這主要取決于對應(yīng)的參數(shù)。這個過程就好比孫悟空拔了一根自己的猴毛變出來一個和自己一模一樣的孫悟空。
因此在fork子進程的過程之中,子進程復(fù)制了父進程的代碼段、數(shù)據(jù)段、堆棧、頁表等,同時子進程擁有獨立的虛擬內(nèi)存空間(當(dāng)然是從父進程那里復(fù)制過來的)。如下所示,實際上fork()最終調(diào)用的是內(nèi)核copy_process方法復(fù)制進程。?

父進程fork子進程的時候,子進程擁有獨立的虛擬內(nèi)存空間,那么對應(yīng)的物理內(nèi)存空間是不是也是獨立的呢?我們都知道在計算機中,內(nèi)存屬于非常寶貴的系統(tǒng)資源,所以大佬們在設(shè)計的時候都盡可能的減少內(nèi)存空間占用從而提高系統(tǒng)資源利用率。fork子進程過程中用到的Copy-On-Write就是典型的內(nèi)存資源管理優(yōu)化機制,如果子進程只是讀取數(shù)據(jù)不進行任何的數(shù)據(jù)寫入,那么就和父進程公用內(nèi)存空間。當(dāng)子進程需要進行數(shù)據(jù)寫入的時候,發(fā)現(xiàn)沒有內(nèi)控空間可以寫入,此時會觸發(fā)一個系統(tǒng)中斷來分配內(nèi)存空間給子進程進行數(shù)據(jù)寫入。

什么時機觸發(fā)AOF重寫?
執(zhí)行bgrewriteaof 命令
當(dāng)我們在客戶端手動執(zhí)行bgrewriteaof 命令后,可以觸發(fā)AOF文件進行重寫,對應(yīng)Redis源碼中進行重寫的bgrewriteaofCommand 函數(shù)會檢測檢測是否滿足進行重寫的條件,主要檢測以下兩個條件:
【Condition1】:檢測當(dāng)前是否存在已經(jīng)在執(zhí)行的AOF重寫子進程,如果存在的話Redis將不再執(zhí)行AOF文件重寫。
【Condition2】:檢測當(dāng)前是否存在已經(jīng)在創(chuàng)建RDB文件的子進程,如果存在的話Redis將AOF文件重寫任務(wù)置為待調(diào)度狀態(tài),后續(xù)如果滿足了重寫條件,則繼續(xù)執(zhí)行AOF文件重寫任務(wù)。
也就是說,Redis檢測到當(dāng)前既沒有AOF重寫子進程也沒有RDB文件創(chuàng)建子進程,那么就可以進行AOF文件重寫。對應(yīng)源碼如下:
超出配置閾值
如果Redis實例開啟了AOF配置,同時配置了auto-aof-rewrite-percentage以及auto-aof-rewrite-min-size,如果超出了閾值會觸發(fā)AOF重寫。
aof_rewrite_scheduled被設(shè)置為待調(diào)度狀態(tài)
在bgrewriteaofCommand函數(shù)中,如果當(dāng)前正在執(zhí)行RDB dump操作,那么對應(yīng)的aof待調(diào)度aof_rewrite_scheduled狀態(tài)就會被置為1,當(dāng)前RDB dump完成之后,會繼續(xù)執(zhí)行AOF重寫操作。?
AOF重寫過程是怎樣的?
通過上文的描述,我們知道了Redis觸發(fā)AOF重寫的時機,那么當(dāng)觸發(fā)重寫之后的具體業(yè)務(wù)是怎樣的呢?我們一起看下AOF重寫的大致流程:
(1)Redis主進程首先檢查是不是存在rdb dump進程或者aof重寫進程正在運行,如果不存在Redis主進程fork子進程進行aof文件重寫;
(2)fork出來的子進程和原來的Redis主進程擁有同樣的內(nèi)存數(shù)據(jù),子進程遍歷此時的內(nèi)存數(shù)據(jù)同時將內(nèi)存數(shù)據(jù)寫入到臨時的AOF文件中;
(3)主進程此時仍然可以接收客戶端請求,同時將新的緩存操作寫入aof_buf以及aof_rewrite_buf中,根據(jù)對應(yīng)的同步策略,將buf中的數(shù)據(jù)分別寫入舊AOF文件以及臨時AOF文件中;
(4)重寫完成之后,臨時AOF文件將替換原有的老的AOF文件,從而完成整個AOF重寫。

AOF模式優(yōu)點
1、AOF的持久化策略更加豐富些,可以根據(jù)實際業(yè)務(wù)需要進行配置,因此相對來說在數(shù)據(jù)可靠性方面要更加有優(yōu)勢一點。
2、AOF文件內(nèi)容比較好理解,更加方便理解業(yè)務(wù)緩存數(shù)據(jù)。
AOF模式缺點
1、通常情況下,同樣的緩存數(shù)據(jù),AOF文件比RDB文件大小要大一些。
2、在文件恢復(fù)場景下,AOF要比DRB恢復(fù)數(shù)據(jù)慢一些。
RDB持久化
RDB(Redis Data Base),所謂的Redis內(nèi)存數(shù)據(jù)快照就是某一時刻Redis存于內(nèi)存中的所有緩存數(shù)據(jù),這就好比用手機相機拍照,記錄當(dāng)時的美好畫面。Redis可以實現(xiàn)在固定時間間隔后將內(nèi)存中的緩存數(shù)據(jù)持久化保存起來。這樣即便是服務(wù)器宕機或者重啟了,只要RDB快照文件還存在,快照文件中對應(yīng)的緩存數(shù)據(jù)就不會丟失,Redis重新啟動后會重新加載RDB文件到內(nèi)存中,快速恢復(fù)緩存數(shù)據(jù),通過這樣的方式保障了緩存數(shù)據(jù)的可靠性。
RDB文件生成過程
我們以bgsave為例子來看下Redis生成RDB文件的大致過程是怎樣的。
(1)Redis主進程首先判斷當(dāng)前是否存在已經(jīng)在執(zhí)行的aof重寫子進程以及rdb文件生成子進程,如果存在的話則直接進行返回。為什么要進行這樣的判斷呢?主要還是從服務(wù)器性能方面進行考量,如果服務(wù)器有多個子線程在進行RDB持久化操作,那么必定會對磁盤造成比較大的IO壓力,如果服務(wù)器中還部署了其他服務(wù)甚至?xí)绊懫渌?wù)的正常運行。
(2)Redis主進程fork子進程進行RDB文件生成操作,在fork的過程中,此時的Redis主進程是阻塞的,不能響應(yīng)客戶端請求,子進程fork完成之后可以繼續(xù)響應(yīng)客戶端請求。
(3)fork出來的子進程遍歷內(nèi)存數(shù)據(jù)進行RDB文件生成操作。
(4)如果此時客戶端的請求需要修改緩存數(shù)據(jù),那么如上面fork子進程的原理,通過COW機制,操作系統(tǒng)會開辟新的內(nèi)存空間給Redis主進程進行新的緩存數(shù)據(jù)寫入。
(5)子進程快照數(shù)據(jù)生成完成之后,替換原來老的RDB文件。

RDB觸發(fā)時機
Redis主要支持兩種持久化操作來生成RDB文件,分別是save、bsave命令方式手動生成以及在配置文件中配置時間間隔自動進行RDB文件生成。
手動命令觸發(fā)
客戶端連接到redis之后我們可以通過save以及bsave命令進行RDB文件的立即創(chuàng)建,兩者的區(qū)別如下:
save:通過主線程觸發(fā),會阻塞Redis業(yè)務(wù),如果內(nèi)存數(shù)據(jù)比較多的話,會導(dǎo)致長時間不能響應(yīng)外部請求;
bsave:客戶端執(zhí)行bsave命令進行RDB持久化,Redis主線程會fork子線程出來進行RDB文件持久化操作,這樣避免了主線程的阻塞即便正在持久化操作依然可以響應(yīng)外部數(shù)據(jù)緩存請求。
不過這里值得注意的是,雖然fork子進程之后不會阻塞主進程,但是在fork的過程中會阻塞主進程,尤其是在內(nèi)存數(shù)據(jù)比較大的時候,阻塞主進程的時間會更長。
配置自動觸發(fā)
另外在Redis的配置文件redis.conf中,我們可以配置按照一定的時間間隔來進行RDB持久化操作。如下配置:
save 900 1
save 300 10
save 60 10000?
其他的觸發(fā)RDB文件生成的操作這里不再贅述了,像從節(jié)點執(zhí)行全量數(shù)據(jù)同步的時候,也會觸發(fā)主節(jié)點生成RDB文件發(fā)送給從節(jié)點。
RDB有沒有丟數(shù)據(jù)的風(fēng)險?
大家不妨思考下通過RDB文件進行緩存數(shù)據(jù)持久化會有什么問題?存不存在丟失緩存數(shù)據(jù)的風(fēng)險?這種方式看上去是個還不錯的持久化解決方案,但是實際上隱藏著一些丟失緩存數(shù)據(jù)的風(fēng)險。為什么這么說呢?通過分析RDB文件生成的機制我們可以發(fā)現(xiàn)有兩個地方存在緩存數(shù)據(jù)丟失的可能性。
場景1:
由于Redis保存RDB快照文件的策略是按照配置的時間間隔進行持久化保存,也就是每隔一個時間間隔Redis就會保存一個RDB文件。因此在內(nèi)存數(shù)據(jù)有更新但是RDB保存時間尚未到來的這段時間如果存在服務(wù)器宕機或者服務(wù)器重啟的情況,此時內(nèi)存的數(shù)據(jù)就會存在丟失的風(fēng)險,因為Redis還沒來得及將數(shù)據(jù)持久化到RDB文件中。
場景1中最大的問題就RDB文件持久化存在時間間隔,而這個時間間隔導(dǎo)致了新增的緩存數(shù)據(jù)存在丟失的風(fēng)險。那么是不是將時間間隔降低到最小就可以了,比如一秒鐘,即使在這一秒鐘期間出現(xiàn)異常情況,那緩存數(shù)據(jù)也只是丟掉這一秒鐘的緩存數(shù)據(jù),相對來說數(shù)據(jù)丟失的情況可控一點。但是問題是如果真的每隔1s就保存一個RDB文件到服務(wù)器磁盤中,那不論是對Redis本身還是Redis所在的服務(wù)器磁盤IO都是一種負擔(dān)。

場景2:
?隨著業(yè)務(wù)的不斷發(fā)展,內(nèi)存中的數(shù)據(jù)必定會越來越大,因此在fork子進程來生成RDB文件的過程中,需要復(fù)制的數(shù)據(jù)會同樣越來越多,耗費的時間也會越來越多,進而阻塞主進程的時間也會越來越多。如果出現(xiàn)長時間阻塞主進程的情況,那么Redis實例必定無法響應(yīng)客戶端的數(shù)據(jù)操作請求,最終導(dǎo)致內(nèi)存數(shù)據(jù)沒有進行及時更新,從而出現(xiàn)丟失緩存數(shù)據(jù)的風(fēng)險。
RDB模式優(yōu)點
1、相比AOF在恢復(fù)數(shù)據(jù)的時候需要一條條回放操作命令,通過RDB文件恢復(fù)數(shù)據(jù)效率更高;
2、適合全量備份內(nèi)存數(shù)據(jù)場景。
3、同樣規(guī)模的內(nèi)存數(shù)據(jù),RDB文件數(shù)據(jù)更加緊湊,磁盤空間占用更小。
4、可以根據(jù)不同的時間間隔保存RDB文件,在恢復(fù)數(shù)據(jù)的時候可以更加靈活地選擇對應(yīng)版本數(shù)據(jù)進行恢復(fù)。
RDB模式缺點
1、由于RDB數(shù)據(jù)保存存在一定的時間間隔,因此存在丟失緩存數(shù)據(jù)的風(fēng)險;
2、fork子進程進行RDB文件生成,由于是一次性生成一個內(nèi)存快照文件,對于服務(wù)器磁盤IO以及Redis本身來說都屬于重操作,可能會對服務(wù)器的磁盤IO造成壓力。
混合持久化
既然AOF以及RDB持久化都有這樣或者那樣的不足,那么有沒有一種持久化方案可以兼顧二者的優(yōu)點來揚長避短呢?從4.0版本開始,Redis支持混合持久化的方式來兼顧效率以及數(shù)據(jù)可靠性。在Redis配置文件redis.conf中配置混合持久化:
如果配置了混合持久化,那么Redis主進程在fork子進程進行持久化操作的時候,原先的將內(nèi)存數(shù)據(jù)轉(zhuǎn)換為操作命令的過程將替換為使用進行AOF重寫時對應(yīng)的RDB文件內(nèi)容直接放入到重寫后的臨時文件中,后面再有新的操作命令,都追加到臨時aof文件中,重寫完成后使用臨時aof文件替換舊的文件。

混合持久化模式優(yōu)點
1、同時擁有RDB以及AOF機制的優(yōu)點,在數(shù)據(jù)可靠性以及數(shù)據(jù)恢復(fù)效率上面達到了很好的平衡。?
混合持久化模式缺點
1、由于Redis從4.0版本才開始支持混合持久化,如果當(dāng)前平臺中的Redis版本低于4.0,那么就無法使用這個持久化機制,因此兼容性不夠友好;
總結(jié)
本文主要分析了Redis AOF、RDB以及混合持久化的內(nèi)存數(shù)據(jù)持久化的機制原理,同時分析了兩種持久化方式的優(yōu)點以及缺點。我想只有理解了中間件的特性機制原理,知道了特性的長處以及不足我們才能設(shè)計適合我們平臺的緩存數(shù)據(jù)持久化策略,從而提升平臺的穩(wěn)定性。
另外在一些優(yōu)秀中間件的學(xué)習(xí)和使用過程中,我們不能僅僅停留在會用的層面,更應(yīng)該深入底層領(lǐng)會其架構(gòu)和實現(xiàn)機制的設(shè)計思路,只有搞明白設(shè)計思路,時刻站在設(shè)計者的角度來看待遇到的問題,那么在我們的實際工作中,如果遇到類似的問題我們可以借鑒這些優(yōu)秀中間件的解決思路來進行問題分析。



























