1.3萬億條數據查詢如何作到毫秒級響應?

關注微信公衆號「程序員黃小斜」,選擇「置頂或者星標」前端

一塊兒成爲更好的本身!程序員

<figure data-block="true" data-editor="7p19l" data-offset-key="d6t0m-0-0" contenteditable="false">面試

</figure>算法

做者:孫曉光數據庫

出處:http://itindex.net/編程

知乎,在古典中文中意爲「你知道嗎?」,它是中國的 Quora,一個問答網站,其中各類問題由用戶社區建立,回答,編輯和組織。segmentfault

做爲中國最大的知識共享平臺,咱們目前擁有 2.2 億註冊用戶,3000 萬個問題,網站答案超過 1.3 億。後端

隨着用戶羣的增加,咱們的應用程序的數據大小沒法實現。咱們的 Moneta 應用程序中存儲了大約 1.3 萬億行數據(存儲用戶已經閱讀過的帖子)。緩存

因爲每個月累計產生大約 1000 億行數據且不斷增加,這一數字將在兩年內達到 3 萬億。在保持良好用戶體驗的同時,咱們在擴展後端方面面臨嚴峻挑戰。安全

在這篇文章中,我將深刻探討如何在如此大量的數據上保持毫秒級的查詢響應時間,以及 TiDB 是一個開源的 MySQL 兼容的 NewSQL 混合事務/分析處理( HTAP)數據庫,如何爲咱們提供支持得到對咱們數據的實時洞察。

我將介紹爲何咱們選擇 TiDB,咱們如何使用它,咱們學到了什麼,優秀實踐以及對將來的一些想法。

咱們的痛點

<figure data-block="true" data-editor="7p19l" data-offset-key="eedqc-0-0" contenteditable="false">


</figure>

本節介紹了咱們的 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?

<figure data-block="true" data-editor="7p19l" data-offset-key="c5om7-0-0" contenteditable="false">


</figure>

TiDB 平臺是一組組件,當它們一塊兒使用時,它們將成爲具備 HTAP 功能的 NewSQL 數據庫。

<figure data-block="true" data-editor="7p19l" data-offset-key="du8e3-0-0" contenteditable="false">

</figure>

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

<figure data-block="true" data-editor="7p19l" data-offset-key="7hjiu-0-0" contenteditable="false">


</figure>

在本節中,我將向您展現如何在 Moneta 的架構中運行 TiDB 以及 Moneta 應用程序的性能指標。

咱們架構中的 TiDB

<figure data-block="true" data-editor="7p19l" data-offset-key="30l7c-0-0" contenteditable="false">

</figure>

知乎的 Moneta 應用程序中的 TiDB 架構

咱們在系統中部署了 TiDB,Moneta 應用程序的總體架構變爲:

  • 頂層:無狀態和可伸縮的客戶端 API 和代理。這些組件易於擴展。
  • 中間層:軟狀態組件和分層 Redis 緩存做爲主要部分。當服務中斷時,這些組件能夠經過恢復保存在 TiDB 羣集中的數據來自我恢復服務。
  • 底層:TiDB 集羣存儲全部有狀態數據。它的組件高度可用,若是節點崩潰,它能夠自我恢復其服務。

在該系統中,全部組件都是可自我恢復的,整個系統具備全局故障監視機制。而後,咱們使用 Kubernetes 來協調整個系統,以確保整個服務的高可用性。

TiDB 的性能指標

因爲咱們在生產環境中應用了 TiDB,所以咱們的系統具備高可用性和易於擴展性,而且系統性能獲得顯著改善。例如,在 2019 年 6 月爲 Moneta 應用程序採用一組性能指標。

在高峯時間每秒寫入 40,000 行數據:

<figure data-block="true" data-editor="7p19l" data-offset-key="8816l-0-0" contenteditable="false">

</figure>

每秒寫入的數據行(數千)

在高峯時段每秒檢查 30,000 個查詢和 1200 萬個帖子:

<figure data-block="true" data-editor="7p19l" data-offset-key="hvbt-0-0" contenteditable="false">

</figure>

每秒寫入的數據行(數千)

第 99 百分位響應時間約爲 25 毫秒,第 999 百分位響應時間約爲 50 毫秒。實際上,平均響應時間遠遠小於這些數字,即便對於須要穩定響應時間的長尾查詢也是如此。

<figure data-block="true" data-editor="7p19l" data-offset-key="1miq1-0-0" contenteditable="false">

</figure>

第 99 百分位響應時間

<figure data-block="true" data-editor="7p19l" data-offset-key="gomv-0-0" contenteditable="false">

</figure>

第 999 百分位響應時間

咱們學到了什麼

<figure data-block="true" data-editor="7p19l" data-offset-key="eq27g-0-0" contenteditable="false">


</figure>

咱們遷移到 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 的指望

<figure data-block="true" data-editor="7p19l" data-offset-key="2uing-0-0" contenteditable="false">


</figure>

在知乎,反垃圾郵件和 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 相比的寫入和查詢延遲:

<figure data-block="true" data-editor="7p19l" data-offset-key="9mlmd-0-0" contenteditable="false">

</figure>

在 RocksDB 和 Titan 中編寫和查詢延遲

統計數據顯示,在咱們啓用 Titan 後,寫入和查詢延遲都急劇降低。這真是太驚人了!當咱們看到統計數據時,咱們沒法相信本身的眼睛。

②表分區改進了查詢性能

咱們還在反垃圾郵件應用程序中使用了 TiDB 3.0 的表分區功能。使用此功能,咱們能夠按時將表分紅多個分區。

當查詢到來時,它將在覆蓋目標時間範圍的分區上執行。這大大提升了咱們的查詢性能。

讓咱們考慮一下若是咱們未來在 Moneta 和反垃圾郵件應用程序中實施 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 邏輯,所以咱們能夠用更少的節點管理應用程序。

之前,咱們使用了七個物理節點,但如今咱們只須要五個。即便咱們使用商用硬件,這些功能也可提高性能。

下一步是什麼

<figure data-block="true" data-editor="7p19l" data-offset-key="ba36t-0-0" contenteditable="false">


</figure>

TiDB 是一個與 MySQL 兼容的數據庫,所以咱們能夠像使用 MySQL 同樣使用它。

因爲 TiDB 的橫向可擴展性,如今咱們能夠自由擴展咱們的數據庫,即便咱們有超過一萬億的記錄來應對。

到目前爲止,咱們已經在咱們的應用程序中使用了至關多的開源軟件。咱們還學到了不少關於使用 TiDB 處理系統問題的知識。

咱們決定參與開發開源工具,並參與社區的長期發展。基於咱們與 PingCAP 的共同努力,TiDB 將變得更增強大。

做者:孫曉光 簡介:知乎搜索後端負責人,目前承擔知乎搜索後端架構設計以及工程團隊的管理工做。曾多年從事私有云相關產品開發工做,關注雲原生技術,TiKV 項目 Committer。 出處: http://itindex.net/ 原文連接: https://dzone.com/articles/le...

關注微信公衆號【程序員黃小斜】回覆「2019」領取我這兩年整理的學習資料

涵蓋自學編程、求職面試、Java技術、計算機基礎和考研等8000G資料合集。

微信公衆號

我的公衆號:程序員黃小斜

微信公衆號【程序員黃小斜】新生代青年彙集地,程序員成長充電站。做者黃小斜,職業是阿里程序員,身份是斜槓青年,但願和更多的程序員交朋友,一塊兒進步和成長!專一於分享技術、面試、職場等成長乾貨,這一次,咱們一塊兒出發。

關注公衆號後回覆「2019」領取我這兩年整理的學習資料,涵蓋自學編程、求職面試、算法刷題、Java技術學習、計算機基礎和考研等8000G資料合集。

技術公衆號:程序員江湖

微信公衆號【程序員江湖】英雄不問出處,編程不看出身。這裏是自學編程愛好者的彙集地,也是程序員IT學習資源的藏經閣。點擊關注,一塊兒成爲更優秀的程序員!

關注公衆號【程序員江湖】後回覆「Java」、「Python」、「C++」、「大數據」、「算法」、「AI」、「Android」、「前端」、「iOS」、「BAT」、「校招」、「筆試」、「面試」、「計算機基礎」、「LeetCode」 等關鍵字能夠獲取對應的免費程序員學習資料。

相關文章
相關標籤/搜索