Kamil InfoQ
作者 | Kamil Charłampowicz
譯者 | 王者
策劃 | Tina
使用 Kafka,如何成功遷移 SQL 資料庫中超過 20 億條記錄?我們的一個客戶遇到了一個 MySQL 問題,他們有一張大表,這張表有 20 多億條記錄,而且還在不斷增加。如果不更換基礎設施,就有磁碟空間被耗盡的風險,最終可能會破壞整個應用程式。而且,這麼大的表還存在其他問題:糟糕的查詢效能、糟糕的模式設計,因為記錄太多而找不到簡單的方法來進行資料分析。我們希望有這麼一個解決方案,既能解決這些問題,又不需要引入高成本的維護時間視窗,導致應用程式無法執行以及客戶無法使用系統。在這篇文章中,我將介紹我們的解決方案,但我還想提醒一下,這並不是一個建議:不同的情況需要不同的解決方案,不過也許有人可以從我們的解決方案中得到一些有價值的見解。
雲解決方案會是解藥嗎?
在評估了幾個備選解決方案之後,我們決定將資料遷移到雲端,我們選擇了 Google Big Query。我們之所以選擇它,是因為我們的客戶更喜歡谷歌的雲解決方案,他們的資料具有結構化和可分析的特點,而且不要求低延遲,所以 BigQuery 似乎是一個完美的選擇。經過測試,我們確信 Big Query 是一個足夠好的解決方案,能夠滿足客戶的需求,讓他們能夠使用分析工具,可以在幾秒鐘內進行資料分析。但是,正如你可能已經知道的那樣,對 BigQuery 進行大量查詢可能會產生很大的開銷,因此我們希望避免直接透過應用程式進行查詢,我們只將 BigQuery 作為分析和備份工具。
將資料流到雲端
說到流式傳輸資料,有很多方法可以實現,我們選擇了非常簡單的方法。我們使用了 Kafka,因為我們已經在專案中廣泛使用它了,所以不需要再引入其他的解決方案。Kafka 給了我們另一個優勢——我們可以將所有的資料推到 Kafka 上,並保留一段時間,然後再將它們傳輸到目的地,不會給 MySQL 叢集增加很大的負載。如果 BigQuery 引入失敗(比如執行請求查詢的成本太高或太困難),這個辦法為我們提供了某種退路。這是一個重要的決定,它給我們帶來了很多好處,而開銷很小。
將資料從 MySQL 流到 Kafka
關於如何將資料從 MySQL 流到 Kafka,你可能會想到 Debezium(https://debezium.io)或 Kafka Connect。這兩種解決方案都是很好的選擇,但在我們的案例中,我們沒有辦法使用它們。MySQL 伺服器版本太老了,Debezium 不支援,升級 MySQL 升級也不是辦法。我們也不能使用 Kafka Connect,因為表中缺少自增列,Kafka Connect 就沒辦法保證在傳輸資料時不丟失資料。我們知道有可能可以使用時間戳,但這種方法有可能會丟失部分資料,因為 Kafka 查詢資料時使用的時間戳精度低於表列中定義的精度。當然,這兩種解決方案都很好,如果在你的專案中使用它們不會導致衝突,我推薦使用它們將資料庫裡的資料流到 Kafka。在我們的案例中,我們需要開發一個簡單的 Kafka 生產者,它負責查詢資料,並保證不丟失資料,然後將資料流到 Kafka,以及另一個消費者,它負責將資料傳送到 BigQuery,如下圖所示。
將資料流到 BigQuery
透過分割槽來回收儲存空間
我們將所有資料流到 Kafka(為了減少負載,我們使用了資料過濾),然後再將資料流到 BigQuery,這幫我們解決了查詢效能問題,讓我們可以在幾秒鐘內分析大量資料,但空間問題仍然存在。我們想設計一個解決方案,既能解決現在的問題,又能在將來方便使用。我們為資料表準備了新的 schema,使用序列 ID 作為主鍵,並將資料按月份進行分割槽。對大表進行分割槽,我們就能夠備份舊分割槽,並在不再需要這些分割槽時將其刪除,回收一些空間。因此,我們用新 schema 建立了新表,並使用來自 Kafka 的資料來填充新的分割槽表。在遷移了所有記錄之後,我們部署了新版本的應用程式,它向新表進行插入,並刪除了舊錶,以便回收空間。當然,為了將舊資料遷移到新表中,你需要有足夠的空閒可用空間。不過,在我們的案例中,我們在遷移過程中不斷地備份和刪除舊分割槽,確保有足夠的空間來儲存新資料。
將資料流到分割槽表中
透過整理資料來回收儲存空間
在將資料流到 BigQuery 之後,我們就可以輕鬆地對整個資料集進行分析,並驗證一些新的想法,比如減少資料庫中表所佔用的空間。其中一個想法是驗證不同型別的資料是如何在表中分佈的。後來發現,幾乎 90% 的資料是沒有必要存在的,所以我們決定對資料進行整理。我開發了一個新的 Kafka 消費者,它將過濾掉不需要的記錄,並將需要留下的記錄插入到另一張表。我們把它叫作整理表,如下所示。
經過整理,型別 A 和 B 被過濾掉了:
將資料流入新表
整理好資料之後,我們更新了應用程式,讓它從新的整理表讀取資料。我們繼續將資料寫入之前所說的分割槽表,Kafka 不斷地從這個表將資料推到整理表中。正如你所看到的,我們透過上述的解決方案解決了客戶所面臨的問題。因為使用了分割槽,儲存空間不再是個問題,資料整理和索引解決了應用程式的一些查詢效能問題。最後,我們將所有資料流到雲端,讓我們的客戶能夠輕鬆對所有資料進行分析。由於我們只對特定的分析查詢使用 BigQuery,而來自使用者其他應用程式的相關查詢仍然由 MySQL 伺服器處理,所以開銷並不會很高。另一點很重要的是,所有這些都是在沒有停機的情況下完成的,因此客戶不會受到影響。
總 結
總的來說,我們使用 Kafka 將資料流到 BigQuery。因為將所有的資料都推到了 Kafka,我們有了足夠的空間來開發其他的解決方案,這樣我們就可以為我們的客戶解決重要的問題,而不需要擔心會出錯。