知乎,在古典中文中意為“你知道嗎?”,它是中國的 Quora,一個問答網站,其中各種問題由使用者社群建立,回答,編輯和組織。作為中國最大的知識共享平臺,我們目前擁有 2.2 億註冊使用者,3000 萬個問題,網站答案超過 1.3 億。
隨著使用者群的增長,我們的應用程式的資料大小無法實現。我們的 Moneta 應用程式中儲存了大約 1.3 萬億行資料(儲存使用者已經閱讀過的帖子)。
由於每月累計產生大約 1000 億行資料且不斷增長,這一數字將在兩年內達到 3 萬億。在保持良好使用者體驗的同時,我們在擴充套件後端方面面臨嚴峻挑戰。
在這篇文章中,我將深入探討如何在如此大量的資料上保持毫秒級的查詢響應時間,以及 TiDB 是一個開源的 MySQL 相容的 NewSQL 混合事務/分析處理( HTAP)資料庫,如何為我們提供支援獲得對我們資料的實時洞察。
我將介紹為什麼我們選擇 TiDB,我們如何使用它,我們學到了什麼,優秀實踐以及對未來的一些想法。
我們的痛點
本節介紹了我們的 Moneta 應用程式的體系結構,我們嘗試構建的理想體系結構,以及資料庫可伸縮性作為我們的主要難點。
系統架構要求
知乎的 Post Feed 服務是一個關鍵系統,使用者可以通過該系統接收網站上釋出的內容。
後端的 Moneta 應用程式儲存使用者已閱讀的帖子,並在知乎的推薦頁面的帖子流中過濾掉這些帖子。
Moneta 應用程式具有以下特徵:
需要高可用性資料:Post Feed 是第一個出現的螢幕,它在推動使用者流量到知乎方面發揮著重要作用。處理巨大的寫入資料:例如,在高峰時間每秒寫入超過 4 萬條記錄,記錄數量每天增加近 30 億條記錄。長期儲存歷史資料:目前,系統中儲存了大約 1.3 萬億條記錄。隨著每月累積約 1000 億條記錄並且不斷增長,歷史資料將在大約兩年內達到 3 萬億條記錄。處理高吞吐量查詢:在高峰時間,系統處理平均每秒在 1200 萬個帖子上執行的查詢。將查詢的響應時間限制為 90 毫秒或更短:即使對於執行時間最長的長尾查詢,也會發生這種情況。容忍誤報:這意味著系統可以為使用者調出許多有趣的帖子,即使有些帖子被錯誤地過濾掉了。考慮到上述事實,我們需要一個具有以下功能的應用程式架構:
高可用性:當用戶開啟知乎的推薦頁面時,找到大量已經閱讀過的帖子是一種糟糕的使用者體驗。出色的系統性能:我們的應用具有高吞吐量和嚴格的響應時間要求。易於擴充套件:隨著業務的發展和應用程式的發展,我們希望我們的系統可以輕鬆擴充套件。勘探
為了構建具有上述功能的理想架構,我們在之前的架構中集成了三個關鍵元件:
代理:這會將使用者的請求轉發給可用節點,並確保系統的高可用性。快取:這暫時處理記憶體中的請求,因此我們並不總是需要處理資料庫中的請求。這可以提高系統性能。儲存:在使用 TiDB 之前,我們在獨立的 MySQL 上管理我們的業務資料。隨著資料量的激增,獨立的 MySQL 系統還不夠。然後我們採用了 MySQL 分片和 Master High Availability Manager( MHA)的解決方案,但是當每月有 1000 億條新記錄湧入我們的資料庫時,這個解決方案是不可取的。MySQL Sharding 和 MHA 的缺點
MySQL 分片和 MHA 不是一個好的解決方案,因為 MySQL 分片和 MHA 都有它們的缺點。
MySQL 分片的缺點:
應用程式程式碼變得複雜且難以維護。更改現有的分片鍵很麻煩。升級應用程式邏輯會影響應用程式的可用性。MHA 的缺點:
我們需要通過編寫指令碼或使用第三方工具來實現虛擬 IP(VIP)配置。MHA 僅監視主資料庫。要配置 MHA,我們需要配置無密碼安全 Shell( SSH)。這可能會導致潛在的安全風險。MHA 不為從屬伺服器提供讀取負載平衡功能。MHA 只能監視主伺服器(而不是從主伺服器)是否可用。在我們發現 TiDB 並將資料從 MySQL 遷移到 TiDB 之前,資料庫可伸縮性仍然是整個系統的弱點。
什麼是 TiDB?
TiDB 平臺是一組元件,當它們一起使用時,它們將成為具有 HTAP 功能的 NewSQL 資料庫。
TiDB 平臺架構
在 TiDB 平臺內部,主要元件如下:
TiDB 伺服器是一個無狀態的 SQL 層,它處理使用者的 SQL 查詢,訪問儲存層中的資料,並將相應的結果返回給應用程式。它與 MySQL 相容並且位於 TiKV 之上。TiKV 伺服器是資料持久存在的分散式事務鍵值儲存層。它使用 Raft 共識協議進行復制,以確保強大的資料一致性和高可用性。TiSpark 叢集也位於 TiKV 之上。它是一個 Apache Spark 外掛,可與 TiDB 平臺配合使用,支援商業智慧(BI)分析師和資料科學家的複雜線上分析處理(OLAP)查詢。放置驅動程式(PD)伺服器是由 etcd 支援的元資料叢集,用於管理和排程 TiKV。除了這些主要元件之外,TiDB 還擁有一個工具生態系統,例如用於快速部署的 Ansible 指令碼,用於從 MySQL 遷移的 Syncer 和 TiDB 資料遷移。
以及用於收集對 TiDB 群集進行的邏輯更改並提供增量備份的 TiDB Binlog。複製到下游(TiDB,Kafka 或 MySQL)。
TiDB 的主要功能包括:
水平可擴充套件性。MySQL 相容的語法。具有強一致性的分散式事務。雲原生架構。使用 HTAP 進行最小提取,轉換,載入( ETL)。容錯和 Raft 恢復。線上架構更改。我們如何使用 TiDB
在本節中,我將向您展示如何在 Moneta 的架構中執行 TiDB 以及 Moneta 應用程式的效能指標。
我們架構中的 TiDB
知乎的 Moneta 應用程式中的 TiDB 架構
我們在系統中部署了 TiDB,Moneta 應用程式的整體架構變為:
頂層:無狀態和可伸縮的客戶端 API 和代理。這些元件易於擴充套件。中間層:軟狀態元件和分層 Redis 快取作為主要部分。當服務中斷時,這些元件可以通過恢復儲存在 TiDB 群集中的資料來自我恢復服務。底層:TiDB 叢集儲存所有有狀態資料。它的元件高度可用,如果節點崩潰,它可以自我恢復其服務。在該系統中,所有元件都是可自我恢復的,整個系統具有全域性故障監視機制。然後,我們使用 Kubernetes 來協調整個系統,以確保整個服務的高可用性。
TiDB 的效能指標
由於我們在生產環境中應用了 TiDB,因此我們的系統具有高可用性和易於擴充套件性,並且系統性能得到顯著改善。例如,在 2019 年 6 月為 Moneta 應用程式採用一組效能指標。
在高峰時間每秒寫入 40,000 行資料:
每秒寫入的資料行(數千)
在高峰時段每秒檢查 30,000 個查詢和 1200 萬個帖子:
每秒寫入的資料行(數千)
第 99 百分位響應時間約為 25 毫秒,第 999 百分位響應時間約為 50 毫秒。實際上,平均響應時間遠遠小於這些數字,即使對於需要穩定響應時間的長尾查詢也是如此。
第 99 百分位響應時間
第 999 百分位響應時間
我們學到了什麼
我們遷移到 TiDB 並非順利,在這裡,我們想分享一些經驗教訓。
更快地匯入資料
我們使用 TiDB 資料遷移(DM)來收集 MySQL 增量 Binlog 檔案,然後使用 TiDB Lightning 將資料快速匯入 TiDB 叢集。
令我們驚訝的是,將這 1.1 萬億條記錄匯入 TiDB 只用了四天時間。如果我們邏輯地將資料寫入系統,可能需要一個月或更長時間。如果我們有更多的硬體資源,我們可以更快地匯入資料。
減少查詢延遲
完成遷移後,我們測試了少量的讀取流量。當 Moneta 應用程式首次上線時,我們發現查詢延遲不符合我們的要求。為解決延遲問題,我們與 PingCap 工程師合作調整系統性能。
在此過程中,我們積累了寶貴的資料和資料處理知識:
有些查詢對查詢延遲很敏感,有些則不然。我們部署了一個單獨的 TiDB 資料庫來處理對延遲敏感的查詢。(其他非延遲敏感的查詢在不同的 TiDB 資料庫中處理。)這樣,大型查詢和對延遲敏感的查詢在不同的資料庫中處理,前者的執行不會影響後者。對於沒有理想執行計劃的查詢,我們編寫了 SQL 提示來幫助執行引擎選擇最佳執行計劃。我們使用低精度時間戳 Oracle( TSO)和預處理語句來減少網路往返。評估資源
在我們嘗試 TiDB 之前,我們沒有分析我們需要多少硬體資源來支援 MySQL 端的相同資料量。
為了降低維護成本,我們在單主機 - 單從機拓撲中部署了 MySQL。相反,在 TiDB 中實現的 Raft 協議至少需要三個副本。
因此,我們需要更多的硬體資源來支援 TiDB 中的業務資料,我們需要提前準備機器資源。
一旦我們的資料中心設定正確,我們就可以快速完成對 TiDB 的評估。
對 TiDB 3.0 的期望
在知乎,反垃圾郵件和 Moneta 應用程式的架構相同。我們在用於生產資料的反垃圾郵件應用程式中嘗試了 TiDB 3.0(TiDB 3.0.0-rc.1 和 TiDB 3.0.0-rc.2)的候選版本中的 Titan 和 Table Partition。
①Titan 縮短了延遲
反垃圾郵件應用程式一直受到嚴重的查詢和寫入延遲折磨。
我們聽說 TiDB 3.0 將引入 Titan,一種鍵值儲存引擎,用於在使用大值時減少 RocksDB(TiKV 中的底層儲存引擎)的寫入放大。為了嘗試這個功能,我們在 TiDB 3.0.0-rc.2 釋出後啟用了 Titan。
下圖分別顯示了與 RocksDB 和 Titan 相比的寫入和查詢延遲:
在 RocksDB 和 Titan 中編寫和查詢延遲
統計資料顯示,在我們啟用 Titan 後,寫入和查詢延遲都急劇下降。這真是太驚人了!當我們看到統計資料時,我們無法相信自己的眼睛。
②表分割槽改進了查詢效能
我們還在反垃圾郵件應用程式中使用了 TiDB 3.0 的表分割槽功能。使用此功能,我們可以按時將表分成多個分割槽。
當查詢到來時,它將在覆蓋目標時間範圍的分割槽上執行。這大大提高了我們的查詢效能。
讓我們考慮一下如果我們將來在 Moneta 和反垃圾郵件應用程式中實施 TiDB 3.0 會發生什麼。
TiDB 3.0 具有諸如 gRPC 中的批處理訊息,多執行緒 Raftstore,SQL 計劃管理和 TiFlash 等功能。我們相信這些將為 Moneta 應用增添光彩。
④gRPC 和多執行緒 Raftstore 中的批處理訊息
Moneta 的寫入吞吐量超過每秒 4 萬次交易(TPS),TiDB 3.0 可以批量傳送和接收 Raft 訊息,並且可以在多個執行緒中處理 Region Raft 邏輯。我們相信這些功能將顯著提高我們系統的併發能力。
⑤SQL 計劃管理
如上所述,我們編寫了大量 SQL 提示,以使查詢優化器選擇最佳執行計劃。
TiDB 3.0 添加了一個 SQL 計劃管理功能,可以直接在 TiDB 伺服器中將查詢繫結到特定的執行計劃。使用此功能,我們不需要修改查詢文字以注入提示。
⑥TiFlash
在 TiDB DevCon 2019 上,我第一次聽說 TiFlash 是 TiDB 的擴充套件分析引擎。
它使用面向列的儲存技術來實現高資料壓縮率,並在資料複製中應用擴充套件的 Raft 一致性演算法以確保資料安全性。
由於我們擁有高寫入吞吐量的海量資料,因此我們無法每天使用 ETL 將資料複製到 Hadoop 進行分析。但是對於 TiFlash,我們樂觀地認為我們可以輕鬆分析我們龐大的資料量。
⑦反垃圾郵件應用程式中的 TiDB 3.0
與 Moneta 應用程式的巨大歷史資料大小相比,反垃圾郵件應用程式具有更高的寫入吞吐量。
但是,它僅查詢過去 48 小時記憶體儲的資料。在此應用程式中,資料每天增加 80 億條記錄和 1.5 TB。
由於 TiDB 3.0 可以批量傳送和接收 Raft 訊息,並且它可以在多個執行緒中處理 Region Raft 邏輯,因此我們可以用更少的節點管理應用程式。
以前,我們使用了七個物理節點,但現在我們只需要五個。即使我們使用商用硬體,這些功能也可提升效能。
下一步是什麼
TiDB 是一個與 MySQL 相容的資料庫,因此我們可以像使用 MySQL 一樣使用它。
由於 TiDB 的橫向可擴充套件性,現在我們可以自由擴充套件我們的資料庫,即使我們有超過一萬億的記錄來應對。
到目前為止,我們已經在我們的應用程式中使用了相當多的開源軟體。我們還學到了很多關於使用 TiDB 處理系統問題的知識。
我們決定參與開發開源工具,並參與社群的長期發展。基於我們與 PingCAP 的共同努力,TiDB 將變得更加強大。