NoSQL同步方案比較
申明:此文並非本人編寫,而是多年前從其他博主文章中搬運整理過到 OneNote 中的,當時沒有記錄轉載處,請見諒!!
第1種:同步雙寫:
這是一種最為簡單的方式,在將資料寫到mysql時,同時將資料寫到ES,實現資料的雙寫
優點:
- 業務邏輯簡單。
缺點:
硬編碼:
- 有需要寫入mysql的地方都需要新增寫入ES的程式碼;
- 業務強耦合;存在雙寫失敗丟資料風險;
- 效能較差:本來mysql的效能就不是很高,再加寫一個ES,系統的效能必然會下降。
說明:
上面第3點講到的雙寫失敗風險,包括以下3種:
ES系統不可用;應用系統和ES之間的網路故障;應用系統重啟,導致系統來不及寫入ES等。針對這種情況,有資料強一致性要求的,就必須雙寫放到事物中來處理,但是一旦用上事物,則效能下降更加明顯。
第2種:非同步雙寫(MQ方式)
針對第一種同步雙寫的效能和資料丟失問題,可以考慮引入MQ,從而形成了非同步雙寫的方案,如下圖所示:
由於MQ的效能基本比mysql高出一個數量級,所以效能可以得到顯著的提高。
優點:
- 效能高;
- 不存在丟資料問題。
缺點:
- 硬編碼問題:依然存在
- 業務強耦合:依然存在
- 複雜度增加:系統中增加了mq的程式碼;
可能存在時延問題:程式的寫入效能提高了,但是由於MQ的消費可能由於網路或其它原因導致使用者寫入的資料不一定可以馬上看到,造成延時。
第3種:非同步雙寫(Worker方式)
上面兩種方案中都存在硬編碼問題,也就是有任何對mysq進行增刪改查的地方要麼植入ES程式碼,要麼替換為MQ程式碼,程式碼的侵入性太強。
如果對實時性要求不高的情況下,可以考慮用定時器來處理,
具體步驟如下:
- 資料庫的相關表中增加一個欄位為timestamp的欄位,任何crud操作都會導致該欄位的時間發生變化;
- 原來程式中的CURD操作不做任何變化;
- 增加一個定時器程式(京東內部叫Worker),讓該程式按一定的時間週期掃描指定的表,把該時間段內發生變化的資料提取出來;
- 逐條寫入到ES中。
下圖所示:
優點:
- 不改變原來程式碼,沒有侵入性、沒有硬編碼;
- 沒有業務強耦合;
- 不改變原來程式的效能;
- Worker程式碼編寫簡單不需要考慮增刪改查。
缺點:
- 時效性較差,由於定時器工作週期不可能設在秒級,所以實時性沒有上面2中好;
對資料庫有一定的輪詢壓力,一種改進方法是將輪詢放到壓力不大的重庫上。
第四種:Binlog 同步方式
本人整合了 binlog 方案,可以跳轉前往檢視:https://www.cnblogs.com/Alay/p/15115543.html
上面三種方案要麼有程式碼侵入,要麼有硬編碼,要麼有時延,第4中方案,可以利用mysql的binlog來進行同步
具體步驟如下:
- 讀取mysql的binlog日誌,獲取指定表的日誌資訊;
- 將讀取的資訊轉為MQ;
- 編寫一個MQ消費程式;
- 不斷消費MQ,每消費完一條訊息,將訊息寫入到ES中。
優點:
- 沒有程式碼侵入、沒有硬編碼;
- 原有系統不需要任何變化,沒有感知;
- 效能高;
- 業務解耦,不需要關注原來系統的業務邏輯。
缺點:
- 構建Binlog系統複雜;
- 也像方案二,存在MQ延時的風險。
總結:
也不能說哪一種是最好的,開發中需要根據需求二選擇,沒有最好的,只有合適的