對于ES,我并沒有在實際項目中應(yīng)用(自己研究過,沒有實戰(zhàn)過);我們項目使用的是MongoDB;由于項目的特殊性,我們研究了很多關(guān)于A->B的數(shù)據(jù)同步方案,包括DB2/Mysql到MongoDB,MongoDB到MongoDB等等。
MySQL數(shù)據(jù)同步到ES的方案
把MySQL的數(shù)據(jù)實時同步到ES,這樣可以實現(xiàn)在ES中低延遲的檢索,有些公司的項目做了分庫,可以單獨搭建一套ES來放全量的數(shù)據(jù)(或全量數(shù)據(jù)的部分字段,達到全量檢索的效果),常用的數(shù)據(jù)同步實現(xiàn)方案有這些:
MySQLBinlog:MySQL的Binlog日志可以用于數(shù)據(jù)庫的主從復(fù)制、數(shù)據(jù)恢復(fù),也可以將MySQL的數(shù)據(jù)同步給ES;這里需要注意,Binlog的日志模式只能使用ROW模式(另外兩種模式是STATEMENT和MIXED);解析Binlog日志中的內(nèi)容,執(zhí)行ESDocumentAPI,這樣就可以將數(shù)據(jù)同步到ES中; MySQLdump:如果是新建的項目,使用Binlog做數(shù)據(jù)同步是沒有問題的,但如果MySQL已經(jīng)運行了一段時間,項目架構(gòu)中后增加的ES,那么歷史數(shù)據(jù)的遷移就要額外處理了,因為Binlog可能已經(jīng)被覆蓋了。這時候歷史數(shù)據(jù)的同步,可以使用mysqldump對現(xiàn)有數(shù)據(jù)導出,之后再使用Binlog的方式; 開源工具:前兩種方式都是在數(shù)據(jù)庫日志這個級別做文章,我們還可以使用一些開源工具,比如go-mysql-elasticsearch;它可以幫助我們完成第一次全量數(shù)據(jù)同步,后續(xù)增量數(shù)據(jù)同步的工作(底層也是解析Binlog日志);又或者mypipe,它支持將Binlog日志內(nèi)容解析后推送到Kafka,如果要寫入到ES中,還需要寫額外的代碼從Kafka中消費數(shù)據(jù)寫入ES。
我們項目中的實現(xiàn)方案
上面提過,我們項目中是將關(guān)系型數(shù)據(jù)庫DB2/Mysql中的數(shù)據(jù)同步到MongoDB中,Mysql尚且還能使用Binlog日志,DB2想要把變化的數(shù)據(jù)實時通知出來,實現(xiàn)起來比較困難(寫程序部署到DB2服務(wù)器上,要和數(shù)據(jù)庫做關(guān)聯(lián)配置,當數(shù)據(jù)發(fā)生變化,程序發(fā)送MQ通知給外圍系統(tǒng)),先不說性能是否能保證,就是“自己寫一個通知程序部署到數(shù)據(jù)庫所在服務(wù)器上(有侵入)”,這一點至少在我們公司是無法做到的。
我們采用了一個非常low的方式來解決這個問題,就是Java程序掃描DB2表中的時間戳,讀取最近變化的數(shù)據(jù),加工到MongoDB中;
雖然實現(xiàn)方案比較low,但是效果還不錯,因為我們在從關(guān)系型數(shù)據(jù)到MongoDB的數(shù)據(jù)同步過程中,可以自有地做數(shù)據(jù)加工;相當于按照一定的數(shù)據(jù)維度,比如按照客戶維度,把幾十張表做關(guān)聯(lián),加工后行程一個document保存到MongoDB中;再對外提供服務(wù)的時候,查詢效率提升的很明顯,因為表關(guān)聯(lián)已經(jīng)提前完成了(接口響應(yīng)大多數(shù)時候都是毫秒級,超過50ms就算慢了)。
缺點也很明顯,數(shù)據(jù)從關(guān)系型數(shù)據(jù)庫到MongoDB的延遲很高,我們項目幾經(jīng)優(yōu)化,也需要20分鐘左右;所以一定要結(jié)合著業(yè)務(wù)場景考慮是否使用這種方案。