背景:
需要把mysql的資料同步到es中。由於沒有維護canal集群, 我們選擇了通過記錄最後一次同步資料的update_time來進行資料同步。
具體的做法,當有資料變更的時候,發個訊息,表示需要進行資料同步。
訊息的監聽者加鎖序列執行, 從要同步資料的表中獲取上一次update_time之後的資料,並且把最後一條記錄的update_time更新回去。
比如說有使用者表
user
id:int
name:varchar
update_time:datetime
sync_log
syc_table_name
last_update_time
從sync_log中獲取last_update_time, 執行sql: select * from user where update_time>=last_update_time.
問題:我們當時限制了一次取一千條出來,發現在有db工單執行,批量更新資料出現了死迴圈,
導致所有mq消費執行緒被占用,其他訊息無法消費,產生了訊息堆積,因為寫了一段**
結果集=select * from user where update_time>=last_update_time limit 1000
while(非空結果集合){
同步資料
結果集=select * from user where update_time>=last_update_time limit 1000
一般情況是不會有問題的,當一秒有大量更新的時候,比如說一秒有2000條更新記錄就有問題了。
問題的核心就在於,如何進行分頁。
因為當你進行同步資料的時候,可能這一秒還會有資料進行產生。
情景:last_update_time為03/11 08:00:00
在08:00:00這一秒有2000條資料被更新,
那麼當所有的資料都處理完以後last_update_time還是03/11 08:00:00, 因為要防止這次同步完成以後08:00:00還有資料
如果每一次取出來所有資料,不進行分頁可以處理,但是同步的資料量大要進行分頁怎麼辦?
解決方案
每次進行資料獲取(1000條), 拿到最後一條記錄的update_time, count(update_time) 如果數量》=1000
則sleep(1s)之後再次處理這一秒的所有資料,並且把last_update_time更新為update_time+1s跳出這1秒
另外可以加乙個死迴圈跳出的判斷,比方說一秒不可能產生1w的記錄,那麼迴圈10次以後就進行跳出。
其他坑:
1. 當有異常的時候進行重試,或者放棄。
2. 如果一次同步時間過長,其他的消費執行緒會進行等待,也可能會造成其他mq主題消費阻塞,可以限制消費執行緒等待的最大時間,如果最大時間還沒有被執行,丟入延遲佇列,或者直接拋棄(這種造成延遲同步,需要等到下一次變動觸發更新)
3. 當程式刷資料的時候,變更的mq傳送量會非常大,可以做一些處理,比方說1秒鐘內超過了5個變更,那麼sleep幾秒(或者傳送延遲佇列)再進行訊息傳送,這x秒內變更直接拋棄。
ES踩坑記錄
1.wildcardquerybuilder querybuilder1 querybuilders.wildcardquery mac value 在es中使用wildcardquery後發現並不能匹配大寫,需要先把搜尋的字段先進行小寫的轉化!同理,使用fuzzyquery 糾錯查詢 和 rege...
ES踩坑筆記
現在開始在業務上使用es,記錄一些踩坑經歷,做點筆記.2018 11 13 排查了一會兒.找不出原因.後來要到了乙個高許可權的賬號去kibana看了眼.發現 能獲取的fields為空.emmmmm.設定為 後解決 2018 11 16 get analyze 然後在 裡使用的是termquery s...
mybatis LocalCache踩坑記錄
上週週三下午,準備去吃飯的時候,值班突然找過來說使用者操作時爆出訂單不存在的問題,因為之前做了分表連續很長一段時間都沒問題,而且當時找過來的都是一些因為產品或者qa操作不當找不到記錄的情況,就沒有在意這些,當時以為幾分鐘就能搞定,但是沒想到居然是線上日誌爆出的問題,經過驗證訂單確實不存在!心想完了,...