(四) MdbCluster分散式記憶體資料庫——業務訊息處理
離上次更新文章已有快5個月,我還是有點懶。但我們系統的研發並沒有因此停下來。下面先簡單介紹下MdbCluster最近的一些進展。
1. 提供了java語言的jdbc驅動。做這個目的是想將業務側的現有自動化測試案例跑起來,以此擴大系統的測試場景。
2. 提供SQL命令列介面,解決日常分片資料查詢操作問題。對於分片資料庫,如果運算元據要到每一片去執行操作語句顯然是不合適的。
3. 多業務接入。最早MdbCluster只接入一個業務系統,隨著測試的深入我們接入了更多的業務系統。並在此基礎上優化了線上擴縮容的能力。
下面我們繼續討論第二節中提到的最後一個問題:業務訊息是如何校驗、錯誤訊息如何重定向、超時訊息如何處理?
我們先回顧下業務訊息的大概處理流程:在MdbClient、MdbAgent、MdbRWNode都會儲存一份完整的SlotList列表,以標明每個資料分片對應的節點。當業務訊息從App通過dbc驅動發給MdbClient後,MdbClient會根據partitionid來計算資料的所屬分片。並根據計算結果將訊息轉發給不同分片節點的 MdbAgent,其會對收到資料進行第一次較驗。如果有錯,會將訊息返回,並帶上正確的分片資訊。MdbClient收到分片錯誤回覆後,會進行訊息重定向。如果沒錯,訊息會傳給本節點的MdbRWNode進行執行,如果是Insert操作,MdbRWNode則會再次較檢資料是否正確。
1. 業務訊息如何校驗,為什麼需要校驗?
上面提到了訊息的校驗過程。MdbClient進行的第一次較驗是為了找到正確的分片資訊。MdbAgent進行第二次較驗是為了保證收到的資料都是歸屬本分片的。在插入操作時,MdbRWNode進行第三次較驗,雙重較驗保證本分片的新增資料不會出錯。
之所以設計這個看上去冗餘的較驗流程,主要是考慮線上擴縮容的場景下,MdbClient、MdbAgent、MdbRWNode三者的SlotList列表並非一直是一致的。當出現前兩者(MdbClient和MdbAgent)不一致場景時,MdbAgent的較驗保證分片節點入口資料的準確。而MdbRWNode除了接收MdbAgent的訊息,還會收到其它程序的訊息請求,因此需要增加校驗保證不會往某個分片插入非本分片的資料(否則可能出現髒資料,這點是不可接受的)。
2. 錯誤訊息如何重定向?
當進行擴縮容的資料遷移時,MdbAgent會最先收到某個slot的更新資訊。MdbClient則最後才能收到。在MdbClient收到slot更新前,其所發出的關於這個slot的訊息,都屬於錯誤訊息。考慮最大程度減少擴縮容時對正常業務的影響,MdbAgent在返回錯誤時,會帶上正確分片的資訊。MdbClient收到重定向訊息時,會進行訊息重定向,以繼續正常流程。
3. 超時訊息如何處理?
首先要討論一下超時訊息是如何產生的。當進行擴縮容操作,對某個slot進行資料遷移時,MdbAgent會對這個slot的資料進行鎖定(可讀不可寫)。當資料遷移完畢後,才會放開。關於一個slot的鎖定時間長短和庫的大小成線性關係。假設庫大小在163W條時,每個slot的鎖定期大概為0.5秒(可以優化)。MdbClient在收到鎖定期資料返回時,當然可以進行重試。但MdbAgent和MdbClient之間可能出現迴圈的訊息風暴。並且App和MdbClient之間會有最大值為一個鎖定期的訊息佇列堵塞(可能有300-500條堵塞訊息)。對於一個實時系統來說這是不可接受的。由於線上訊息剛好碰到某個slot鎖定的概率(1/16384)較低,即當TPS壓力為16384時每秒會遇到一條。因此,對於鎖定訊息,MdbClient會直接返回給App,由App進行相關處理。
4. 多分片訊息處理
當一個查詢為全表掃描或者涉及多個分片的資料操作時,MdbClient會分解這些操作,並將這些操作分別發向對應的分片節點。假設對一個有5個分片節點的庫進行一次全表查詢。MdbClient會給5個分片分別傳送一條查詢資訊,在分別收到5條返回結果時,MdbClient會轉發這5條訊息給App的dbc驅動。由App的dbc驅動進行資料的彙總。最終,App會收到完整的資料。兩個問題:
a) 分片資訊對App是隔離的,App的dbc驅動是如何知道要等待多少條返回資訊? 訣竅在於,MdbClient在拆分訊息時,會將拆分條數放在請求訊息裡面。訊息返回時,拆分條數也會跟著帶回。dbc驅動根據這個條數就知道需要等待的訊息數。
b) 為什麼是dbc驅動等待,而不是MdbClient等待?由於dbc驅動的操作是同步的,MdbClient是非同步的。所以放在dbc驅動進行訊息等待並不會影響系統的效率。
下一章我們會討論一下線上擴縮容的架構設計,以及遷移資料的狀態控制。