目錄
1、Master-Slave架構
2、非同步日誌持久化機制
3、檢查點機制:定時持久化全量資料
4、引入檢查點節點
5、總結 & 思考
“這篇文章,給大家來聊一個生產級的中介軟體系統的架構設計實踐,希望給對中介軟體系統感興趣的同學一點啟發。
(1)Master-Slave架構
這個中介軟體系統的本質是希望能夠用分散式的方式來處理一些資料,但是具體的作用涉及到核心技術,所以這裡不能直接說明。
但是他的核心思想,就是把資料分發到很多臺機器上來處理,然後需要有一臺機器來控制N多臺機器的分散式處理,大概如下圖所示。
那麼既然是分散式的處理,就肯定涉及到在Master中要維護這個叢集的一些核心後設資料。
比如說資料的分發處理是如何排程的,處理的具體過程現在什麼進度了,還有就是對叢集裡存放資料進行描述的一些核心後設資料。
這些核心後設資料肯定會不斷的頻繁的修改,大家此時可以想,無論你是基於外部的檔案還是資料庫,或者是zookeeper來存放這些後設資料的話,其實都會導致他的後設資料更新效能降低,因為要訪問外部依賴。
何況這種複雜的後設資料其實還不一定能通過zk或者資料庫來存放,因為他可能是非格式化的。
所以這裡一個核心的設計,就是將核心後設資料直接存放在Master的記憶體裡,這樣可以保證高併發更新後設資料的時候,他的效能是極高的,而且直接基於記憶體來提供對外的更新服務。
如果Master部署在高配置物理機上,比如32核128GB的那種,每秒支援10萬+的請求都沒問題。
(2)非同步日誌持久化機制
但是這裡有一個問題,假如說Master程式重啟,或者是突然當機了,那麼記憶體裡的資料不就丟失了麼?
對,所以針對這個問題,既然已經否決掉了基於外部儲存來寫入後設資料,那麼這裡就可以採取非同步持久化日誌的機制,來通過非同步化的方式把後設資料的更新日誌寫入磁碟檔案。
每次Master收到一個請求,在記憶體裡更新後設資料之後,就需要生成一條後設資料的更新日誌,把這個更新日誌需要寫入到一個記憶體緩衝裡去。
然後等記憶體緩衝滿了之後,由一個後臺執行緒把這裡的資料重新整理到磁碟上去,如下圖。
肯定會有人說,那如果一條更新日誌剛寫入緩衝區,結果Master當機了,此時不是還是會丟失少量資料嗎?因為還沒來得及刷入磁碟。
沒錯啊,這個為了保證高併發請求都是由記憶體來處理的,你必須得用非同步持久化磁碟的模式,所以必然要容忍極端當機情況下,可能丟失比如幾秒鐘的資料。
那麼如果是正常的Master重啟呢?
那簡單,必須先把日誌緩衝區清空刷入磁碟,然後才能正常重啟Master,保證資料都在磁碟上不會丟失。
接著重啟的時候,從磁碟上讀取更新日誌,每一條都依次回訪到記憶體裡,恢復出來核心後設資料即可。
(3)檢查點機制:定時持久化全量資料
但是這裡又有一個問題了,那個磁碟上的日誌檔案越來越大,因為後設資料不斷的在更新,不斷在產生最新的變更日誌寫入磁碟檔案。
那麼系統執行一段時間以後,每次重啟都需要從磁碟讀取歷史全部日誌,一條一條回放到記憶體來恢復核心後設資料嗎?
不可能,所以這裡一定要配合引入檢查點機制。
也就是說,每隔一段時間,就需要開啟一個後臺執行緒,把記憶體裡的全部核心後設資料序列化後寫入磁碟上的後設資料檔案,作為這個時間的一個快照檔案,同時清空掉日誌檔案,這個叫做檢查點操作。
下次重啟,只要把後設資料檔案讀取出來直接反序列化後方入記憶體,然後把上次檢查點之後的變更日誌從日誌檔案裡讀出來回放到記憶體裡,就可以恢復出來完整的後設資料了。
這種方式,可以讓Master重啟很快,因為大部分資料都是在檢查點寫入的那個後設資料檔案裡。
整個過程,如下圖所示:
(4)引入檢查點節點
但是這個時候又有一個問題了。
大家可以想一下,Master記憶體裡的後設資料需要高併發的被人訪問和修改,同時每隔一段時間還要檢查點寫入磁碟。
那麼在檢查點過程中,是不是需要把記憶體資料全部加鎖,不允許別人修改?
在加鎖的時候,把不會變動的資料寫入磁碟檔案中,但是這個過程是很慢的,意味著此時別人高併發的寫入操作都需要等待核心後設資料的鎖。
因為此時別人鎖住了,你無法加鎖去寫資料進去,這會導致系統在幾秒內出現卡頓無法響應請求的問題。
所以此時需要在架構設計裡引入一個檢查點節點,專門負責同步Master的變更日誌。
然後在自己記憶體裡維護一份一模一樣的核心後設資料,每隔一段時間由檢查點節點來負責將記憶體資料寫入磁碟,接著上傳傳送給Master。
這樣做,就不需要Master自己執行檢查點的時候對自己記憶體資料進行加鎖了,如下圖。
在這樣的一個架構下,對Master來說,他只需要一個後臺執行緒負責接收Checkpoint程式定時傳送過來的後設資料檔案快照然後寫入本地磁碟就可以了,完全規避掉了對自己記憶體後設資料的鎖衝突的問題。
(5)總結 & 思考
總結一下這個架構設計,其實就是Master基於記憶體維護後設資料,這樣一臺物理機可以支撐每秒10萬+的高併發請求。
每次後設資料出現更新,寫一條日誌到記憶體緩衝區,然後後臺執行緒去重新整理日誌到日誌檔案裡去,同時需要傳送一條日誌到Checkpoint節點去。
Checkpoint節點會在自己記憶體裡維護一份一模一樣的後設資料,然後每隔一段時間執行checkpoint檢查點寫一份後設資料檔案快照。
接著上傳給Master節點後清空掉他的日誌檔案。然後Master節點每次重啟的時候直接讀取本地後設資料檔案快照,加上回放上次checkpoint之後的日誌即可。
這裡可能大家會提幾個問題,比如說Master節點突然當機會如何?
那很簡單,直接影響就是他記憶體緩衝裡的那些日誌丟了,導致少量資料丟失,這個在我們的場景下可以容忍。
如果Checkpoint節點當機怎麼辦?
那不要緊,因為他之前上傳過後設資料檔案的快照,所以對Master而言最多就是無法同步資料過去。
但是Master重啟,還是可以讀取最近一次的後設資料快照,然後回放日誌即可。
等Checkpoint節點恢復了,可以繼續接著上一次同步日誌,然後繼續執行checkpoint操作。
一大波微服務、分散式、高併發、高可用的原創系列文章正在路上,
歡迎關注公眾號:石杉的架構筆記
週一至週五早八點半!精品技術文章準時送上!!!
十餘年BAT架構經驗傾囊相授