mysql 同步數據到 ElasticSearch 的方案
MySQL Binlog
要通過 MySQL binlog 將 MySQL 的數據同步給 ES, 我們只能使用 row 模式的 binlog。如果使用 statement 或者 mixed format,我們在 binlog 裏面只能知道對應的 query 語句,完全沒法知道這條語句到底改了啥數據,所以要從 binlog 裏面得到實際的數據,只能用 row 模式。
Row 模式還可以設置 full,noblob 以及 minimal 三種 image 模式,後面兩種主要是為了減少空間占用,默認是 full。個人其實最喜歡 full 模式,這樣數據最全,而且也覺得空間占用對於現在的硬盤來說不是特別大的問題,畢竟我們還有定期清理 binlog 的機制。
同步 MySQL binlog 就很簡單了,按照 MySQL replication 的協議,自己寫一個客戶端,模擬成 MySQL slave,註冊給 MySQL master 就可以了。MySQL master 會實時的將數據的更新通過 binlog event 發送給 slave,然後我們自己解析 event 之後就能得到實際的數據了。
具體實現這裏不做過多說明,大家可以參考 MySQL Client/Server Protocol 細致的了解 MySQL 的 protocol,binlog events 等相關知識。其中在 go-mysql 項目裏面實現了相關的 replication 功能。
MySQL dump
如果是一個新建 MySQL,我們當然可以通過 binlog 的方式方便的同步數據。但如果我們想同步一個已經運行一段時間的 MySQL ,就可能會有問題了。因為這時候早期的 binlog 文件已經被刪除,如果直接開始同步,我們就可能會缺失一部分早期更新的數據。
要解決這個辦法也比較容易,參考 MySQL 通用的 backup 方式,我們可以先使用 mysqldump 獲取當前 MySQL 的整個 snapshot,直接解析生成的 dump 文件,就能得到當前所有的數據。然後在從這個 snapshot 對應的 binlog position 位置開始同步。
整個這套流程也在 go-mysql 的 canal 裏面實現。
另外一種方式
可以使用 mtime 時間戳進行控制,增加一個輔助標量 flag(標記是否刪除),這樣在索引系統中定時通過 mtime 過濾數據,在通過 flag 標誌位指示是否已經被刪除的數據;這裏就會有兩種方案去處理: 1. 當 flag 標記為刪除,則在執行索引的時候使用 delete 直接將 ElasticSearch 中的數據刪除掉 2. 不區分 flag 標簽,直接索引到 ElasticSearch 中去,在搜索的時候將 flag 為刪除的數據過濾掉
mysql 同步數據到 ElasticSearch 的方案