有三個 ES 索引: trade_state, trade_buyer, trade_seller ,各自同時監聽 trade_order 消息,經過幾乎同樣的處理邏輯,更新索引裏的訂單數據。 又一個索引對比任務,會在訂單消息延遲 10 分鐘後將該條消息從新放入,去比較這三個索引的訂單狀態數據。 發現少數訂單的 trade_buyer 在比較的時候老是狀態有些滯後,親自去查的時候,狀態又是對的,甚是奇怪。日誌
因爲數據對比不一致任務可以及早發現問題和發出警告,而這個彷佛屬於「誤報軍情」,所以甚爲干擾。若是不是問題,須要找出其中的緣由並消除它。索引
經過日誌發現 : 假設時刻 T 訂單狀態更新爲 state = 3,時刻 T+20s 更新爲 state = 6, 那麼時刻 T+10min ,對比查詢到的 trade_buyer 的訂單狀態依然是 state = 3。怕是有什麼環節有梗,我打出了對比查詢時的 trade_buyer 索引裏的全部數據, state = 3 !搜索
查看 trade_buyer 的寫入日誌,明明在時刻 T+20s 已經成功寫入 state = 6 的日誌啊,應該覆寫了 state = 3 的數據纔對,怎麼會又出現 state = 3 ? ES 同窗懷疑是否是 state = 6 的訂單數據又被覆寫了。 然而,訂單狀態更新是有嚴格遞增的版本號更新控制的,不會從 state = 6 倒退到 state = 3(除非從新強制更新 DB 裏的訂單狀態,但線上是不會有這種狀況的);並且,在 T+20s - T+10min 時刻之間,並無 trade_buyer state = 3 的寫入日誌,這個 state = 3 到底是從哪裏來的 ? 真使人百思不得其解。程序
繼續仔細閱讀日誌內容,忽然發現,查詢時的 trade_buyer 的 buyer_id 與寫入時的 buyer_id 不同。不會吧 ? 因而我根據這兩個不一樣的 buyer_id 去 trade_buyer 索引裏搜索這個訂單, 居然兩個都有 ! 其中必有蹊蹺。 因而,我去諮詢爲何訂單的 buyer_id 會變化,確實有這樣的下單場景。方法
訂單的 buyer_id 會變化,就能夠講通了: trade_buyer 是根據 buyer_id 分片的,根據不一樣的 buyer_id 及訂單號,查到的是不一樣的兩條訂單數據。 假設在 T 時刻狀態更新爲 state = 3 , buyer_id = x , 而在 T+20s 時刻,buyer_id 已經變爲了 y ,那麼, T+20s 更新的是 buyer_id = y 的那條訂單數據,而不是 buyer_id = x 的那條,也就是: buyer_id = y && state = 6, buyer_id = x && state = 3。 在 T+10min 延遲後的那條消息與 T 的消息是同樣的, buyer_id = x ,這樣,在 T+10min 進行對比查詢時拿到的是 buyer_id = x 的那條數據,也就是未更新的髒數據。真相大白 !數據
解決方法也比較簡單:在對比查詢時,取最新的 buyer_id 而不是原來的那條消息裏的 buyer_id 。
查詢
其實,對比程序也報告了 buyer_id 的不一致。但我總以爲難以置信,所以有意忽略了。沒想到,這不起眼的細節,正是解開問題的關鍵鑰匙 ! 可見,細節不可忽視啊 !消息
經此一事,我明白了:奇怪之事必有原因 ! 若是發現了難以置信的事情,也許已經離真相很近了。再走近一步步。 此外,不可放過不起眼的細節。
閱讀