1.3 萬(wàn)億條數(shù)據(jù)查詢,如何做到毫秒級(jí)響應(yīng)?

我們的痛點(diǎn)

本節(jié)介紹了我們的 Moneta 應(yīng)用程序的體系結(jié)構(gòu),我們嘗試構(gòu)建的理想體系結(jié)構(gòu),以及數(shù)據(jù)庫(kù)可伸縮性作為我們的主要難點(diǎn)。

系統(tǒng)架構(gòu)要求

知乎的 Post Feed 服務(wù)是一個(gè)關(guān)鍵系統(tǒng),用戶可以通過(guò)該系統(tǒng)接收網(wǎng)站上發(fā)布的內(nèi)容。

后端的 Moneta 應(yīng)用程序存儲(chǔ)用戶已閱讀的帖子,并在知乎的推薦頁(yè)面的帖子流中過(guò)濾掉這些帖子。

Moneta 應(yīng)用程序具有以下特征:

  • 需要高可用性數(shù)據(jù):Post Feed 是第一個(gè)出現(xiàn)的屏幕,它在推動(dòng)用戶流量到知乎方面發(fā)揮著重要作用。
  • 處理巨大的寫入數(shù)據(jù):例如,在高峰時(shí)間每秒寫入超過(guò) 4 萬(wàn)條記錄,記錄數(shù)量每天增加近 30 億條記錄。
  • 長(zhǎng)期存儲(chǔ)歷史數(shù)據(jù):目前,系統(tǒng)中存儲(chǔ)了大約 1.3 萬(wàn)億條記錄。隨著每月累積約 1000 億條記錄并且不斷增長(zhǎng),歷史數(shù)據(jù)將在大約兩年內(nèi)達(dá)到 3 萬(wàn)億條記錄。
  • 處理高吞吐量查詢:在高峰時(shí)間,系統(tǒng)處理平均每秒在 1200 萬(wàn)個(gè)帖子上執(zhí)行的查詢。
  • 將查詢的響應(yīng)時(shí)間限制為 90 毫秒或更短:即使對(duì)于執(zhí)行時(shí)間最長(zhǎng)的長(zhǎng)尾查詢,也會(huì)發(fā)生這種情況。
  • 容忍誤報(bào):這意味著系統(tǒng)可以為用戶調(diào)出許多有趣的帖子,即使有些帖子被錯(cuò)誤地過(guò)濾掉了。

考慮到上述事實(shí),我們需要一個(gè)具有以下功能的應(yīng)用程序架構(gòu):

  • 高可用性:當(dāng)用戶打開知乎的推薦頁(yè)面時(shí),找到大量已經(jīng)閱讀過(guò)的帖子是一種糟糕的用戶體驗(yàn)。
  • 出色的系統(tǒng)性能:我們的應(yīng)用具有高吞吐量和嚴(yán)格的響應(yīng)時(shí)間要求。
  • 易于擴(kuò)展:隨著業(yè)務(wù)的發(fā)展和應(yīng)用程序的發(fā)展,我們希望我們的系統(tǒng)可以輕松擴(kuò)展。

勘探

為了構(gòu)建具有上述功能的理想架構(gòu),我們?cè)谥暗募軜?gòu)中集成了三個(gè)關(guān)鍵組件:

  • 代理:這會(huì)將用戶的請(qǐng)求轉(zhuǎn)發(fā)給可用節(jié)點(diǎn),并確保系統(tǒng)的高可用性。
  • 緩存:這暫時(shí)處理內(nèi)存中的請(qǐng)求,因此我們并不總是需要處理數(shù)據(jù)庫(kù)中的請(qǐng)求。這可以提高系統(tǒng)性能。
  • 存儲(chǔ):在使用 TiDB 之前,我們?cè)讵?dú)立的 MySQL 上管理我們的業(yè)務(wù)數(shù)據(jù)。隨著數(shù)據(jù)量的激增,獨(dú)立的 MySQL 系統(tǒng)還不夠。
    然后我們采用了 MySQL 分片和 Master High Availability Manager( MHA)的解決方案,但是當(dāng)每月有 1000 億條新記錄涌入我們的數(shù)據(jù)庫(kù)時(shí),這個(gè)解決方案是不可取的。

MySQL Sharding 和 MHA 的缺點(diǎn)

MySQL 分片和 MHA 不是一個(gè)好的解決方案,因?yàn)?MySQL 分片和 MHA 都有它們的缺點(diǎn)。

MySQL 分片的缺點(diǎn):

  • 應(yīng)用程序代碼變得復(fù)雜且難以維護(hù)。
  • 更改現(xiàn)有的分片鍵很麻煩。
  • 升級(jí)應(yīng)用程序邏輯會(huì)影響應(yīng)用程序的可用性。

MHA 的缺點(diǎn):

  • 我們需要通過(guò)編寫腳本或使用第三方工具來(lái)實(shí)現(xiàn)虛擬 IP(VIP)配置。
  • MHA 僅監(jiān)視主數(shù)據(jù)庫(kù)。
  • 要配置 MHA,我們需要配置無(wú)密碼安全 Shell( SSH)。這可能會(huì)導(dǎo)致潛在的安全風(fēng)險(xiǎn)。
  • MHA 不為從屬服務(wù)器提供讀取負(fù)載平衡功能。
  • MHA 只能監(jiān)視主服務(wù)器(而不是從主服務(wù)器)是否可用。

在我們發(fā)現(xiàn) TiDB 并將數(shù)據(jù)從 MySQL 遷移到 TiDB 之前,數(shù)據(jù)庫(kù)可伸縮性仍然是整個(gè)系統(tǒng)的弱點(diǎn)。

什么是 TiDB?

TiDB 平臺(tái)是一組組件,當(dāng)它們一起使用時(shí),它們將成為具有 HTAP 功能的 NewSQL 數(shù)據(jù)庫(kù)。


image.png

在 TiDB 平臺(tái)內(nèi)部,主要組件如下:

  • TiDB 服務(wù)器是一個(gè)無(wú)狀態(tài)的 SQL 層,它處理用戶的 SQL 查詢,訪問(wèn)存儲(chǔ)層中的數(shù)據(jù),并將相應(yīng)的結(jié)果返回給應(yīng)用程序。它與 MySQL 兼容并且位于 TiKV 之上。
  • TiKV 服務(wù)器是數(shù)據(jù)持久存在的分布式事務(wù)鍵值存儲(chǔ)層。它使用 Raft 共識(shí)協(xié)議進(jìn)行復(fù)制,以確保強(qiáng)大的數(shù)據(jù)一致性和高可用性。
  • TiSpark 集群也位于 TiKV 之上。它是一個(gè) Apache Spark 插件,可與 TiDB 平臺(tái)配合使用,支持商業(yè)智能(BI)分析師和數(shù)據(jù)科學(xué)家的復(fù)雜在線分析處理(OLAP)查詢。
  • 放置驅(qū)動(dòng)程序(PD)服務(wù)器是由 etcd 支持的元數(shù)據(jù)集群,用于管理和調(diào)度 TiKV。

除了這些主要組件之外,TiDB 還擁有一個(gè)工具生態(tài)系統(tǒng),例如用于快速部署的 Ansible 腳本,用于從 MySQL 遷移的 Syncer 和 TiDB 數(shù)據(jù)遷移。

以及用于收集對(duì) TiDB 群集進(jìn)行的邏輯更改并提供增量備份的 TiDB Binlog。復(fù)制到下游(TiDB,Kafka 或 MySQL)。

TiDB 的主要功能包括:

  • 水平可擴(kuò)展性。
  • MySQL 兼容的語(yǔ)法。
  • 具有強(qiáng)一致性的分布式事務(wù)。
  • 云原生架構(gòu)。
  • 使用 HTAP 進(jìn)行最小提取,轉(zhuǎn)換,加載( ETL)。
  • 容錯(cuò)和 Raft 恢復(fù)。
  • 在線架構(gòu)更改。

我們?nèi)绾问褂?TiDB

在本節(jié)中,我將向您展示如何在 Moneta 的架構(gòu)中運(yùn)行 TiDB 以及 Moneta 應(yīng)用程序的性能指標(biāo)。

我們架構(gòu)中的 TiDB

image.png

我們?cè)谙到y(tǒng)中部署了 TiDB,Moneta 應(yīng)用程序的整體架構(gòu)變?yōu)椋?/strong>

  • 頂層:無(wú)狀態(tài)和可伸縮的客戶端 API 和代理。這些組件易于擴(kuò)展。
  • 中間層:軟狀態(tài)組件和分層 Redis 緩存作為主要部分。當(dāng)服務(wù)中斷時(shí),這些組件可以通過(guò)恢復(fù)保存在 TiDB 群集中的數(shù)據(jù)來(lái)自我恢復(fù)服務(wù)。
  • 底層:TiDB 集群存儲(chǔ)所有有狀態(tài)數(shù)據(jù)。它的組件高度可用,如果節(jié)點(diǎn)崩潰,它可以自我恢復(fù)其服務(wù)。

在該系統(tǒng)中,所有組件都是可自我恢復(fù)的,整個(gè)系統(tǒng)具有全局故障監(jiān)視機(jī)制。然后,我們使用 Kubernetes 來(lái)協(xié)調(diào)整個(gè)系統(tǒng),以確保整個(gè)服務(wù)的高可用性。

TiDB 的性能指標(biāo)

由于我們?cè)谏a(chǎn)環(huán)境中應(yīng)用了 TiDB,因此我們的系統(tǒng)具有高可用性和易于擴(kuò)展性,并且系統(tǒng)性能得到顯著改善。例如,在 2019 年 6 月為 Moneta 應(yīng)用程序采用一組性能指標(biāo)。

在高峰時(shí)間每秒寫入 40,000 行數(shù)據(jù):


image.png

在高峰時(shí)段每秒檢查 30,000 個(gè)查詢和 1200 萬(wàn)個(gè)帖子:


image.png

第 99 百分位響應(yīng)時(shí)間約為 25 毫秒,第 999 百分位響應(yīng)時(shí)間約為 50 毫秒。實(shí)際上,平均響應(yīng)時(shí)間遠(yuǎn)遠(yuǎn)小于這些數(shù)字,即使對(duì)于需要穩(wěn)定響應(yīng)時(shí)間的長(zhǎng)尾查詢也是如此。


我們學(xué)到了什么

我們遷移到 TiDB 并非順利,在這里,我們想分享一些經(jīng)驗(yàn)教訓(xùn)。

更快地導(dǎo)入數(shù)據(jù)

我們使用 TiDB 數(shù)據(jù)遷移(DM)來(lái)收集 MySQL 增量 Binlog 文件,然后使用 TiDB Lightning 將數(shù)據(jù)快速導(dǎo)入 TiDB 集群。

令我們驚訝的是,將這 1.1 萬(wàn)億條記錄導(dǎo)入 TiDB 只用了四天時(shí)間。如果我們邏輯地將數(shù)據(jù)寫入系統(tǒng),可能需要一個(gè)月或更長(zhǎng)時(shí)間。如果我們有更多的硬件資源,我們可以更快地導(dǎo)入數(shù)據(jù)。

減少查詢延遲

完成遷移后,我們測(cè)試了少量的讀取流量。當(dāng) Moneta 應(yīng)用程序首次上線時(shí),我們發(fā)現(xiàn)查詢延遲不符合我們的要求。為解決延遲問(wèn)題,我們與 PingCap 工程師合作調(diào)整系統(tǒng)性能。

在此過(guò)程中,我們積累了寶貴的數(shù)據(jù)和數(shù)據(jù)處理知識(shí):

  • 有些查詢對(duì)查詢延遲很敏感,有些則不然。我們部署了一個(gè)單獨(dú)的 TiDB 數(shù)據(jù)庫(kù)來(lái)處理對(duì)延遲敏感的查詢。(其他非延遲敏感的查詢?cè)诓煌?TiDB 數(shù)據(jù)庫(kù)中處理。)
    這樣,大型查詢和對(duì)延遲敏感的查詢?cè)诓煌臄?shù)據(jù)庫(kù)中處理,前者的執(zhí)行不會(huì)影響后者。
  • 對(duì)于沒(méi)有理想執(zhí)行計(jì)劃的查詢,我們編寫了 SQL 提示來(lái)幫助執(zhí)行引擎選擇最佳執(zhí)行計(jì)劃。
  • 我們使用低精度時(shí)間戳 Oracle( TSO)和預(yù)處理語(yǔ)句來(lái)減少網(wǎng)絡(luò)往返。

評(píng)估資源

在我們嘗試 TiDB 之前,我們沒(méi)有分析我們需要多少硬件資源來(lái)支持 MySQL 端的相同數(shù)據(jù)量。

為了降低維護(hù)成本,我們?cè)趩沃鳈C(jī) - 單從機(jī)拓?fù)渲胁渴鹆?MySQL。相反,在 TiDB 中實(shí)現(xiàn)的 Raft 協(xié)議至少需要三個(gè)副本。

因此,我們需要更多的硬件資源來(lái)支持 TiDB 中的業(yè)務(wù)數(shù)據(jù),我們需要提前準(zhǔn)備機(jī)器資源。

一旦我們的數(shù)據(jù)中心設(shè)置正確,我們就可以快速完成對(duì) TiDB 的評(píng)估。

對(duì) TiDB 3.0 的期望

在知乎,反垃圾郵件和 Moneta 應(yīng)用程序的架構(gòu)相同。我們?cè)谟糜谏a(chǎn)數(shù)據(jù)的反垃圾郵件應(yīng)用程序中嘗試了 TiDB 3.0(TiDB 3.0.0-rc.1 和 TiDB 3.0.0-rc.2)的候選版本中的 Titan 和 Table Partition。

①Titan 縮短了延遲

反垃圾郵件應(yīng)用程序一直受到嚴(yán)重的查詢和寫入延遲折磨。

我們聽說(shuō) TiDB 3.0 將引入 Titan,一種鍵值存儲(chǔ)引擎,用于在使用大值時(shí)減少 RocksDB(TiKV 中的底層存儲(chǔ)引擎)的寫入放大。為了嘗試這個(gè)功能,我們?cè)?TiDB 3.0.0-rc.2 發(fā)布后啟用了 Titan。

下圖分別顯示了與 RocksDB 和 Titan 相比的寫入和查詢延遲:


image.png

統(tǒng)計(jì)數(shù)據(jù)顯示,在我們啟用 Titan 后,寫入和查詢延遲都急劇下降。這真是太驚人了!當(dāng)我們看到統(tǒng)計(jì)數(shù)據(jù)時(shí),我們無(wú)法相信自己的眼睛。

②表分區(qū)改進(jìn)了查詢性能

我們還在反垃圾郵件應(yīng)用程序中使用了 TiDB 3.0 的表分區(qū)功能。使用此功能,我們可以按時(shí)將表分成多個(gè)分區(qū)。

當(dāng)查詢到來(lái)時(shí),它將在覆蓋目標(biāo)時(shí)間范圍的分區(qū)上執(zhí)行。這大大提高了我們的查詢性能。

讓我們考慮一下如果我們將來(lái)在 Moneta 和反垃圾郵件應(yīng)用程序中實(shí)施 TiDB 3.0 會(huì)發(fā)生什么。

③Moneta 應(yīng)用程序中的 TiDB 3.0

TiDB 3.0 具有諸如 gRPC 中的批處理消息,多線程 Raftstore,SQL 計(jì)劃管理和 TiFlash 等功能。我們相信這些將為 Moneta 應(yīng)用增添光彩。

④gRPC 和多線程 Raftstore 中的批處理消息

Moneta 的寫入吞吐量超過(guò)每秒 4 萬(wàn)次交易(TPS),TiDB 3.0 可以批量發(fā)送和接收 Raft 消息,并且可以在多個(gè)線程中處理 Region Raft 邏輯。我們相信這些功能將顯著提高我們系統(tǒng)的并發(fā)能力

⑤SQL 計(jì)劃管理

如上所述,我們編寫了大量 SQL 提示,以使查詢優(yōu)化器選擇最佳執(zhí)行計(jì)劃。

TiDB 3.0 添加了一個(gè) SQL 計(jì)劃管理功能,可以直接在 TiDB 服務(wù)器中將查詢綁定到特定的執(zhí)行計(jì)劃。使用此功能,我們不需要修改查詢文本以注入提示。

⑥TiFlash

在 TiDB DevCon 2019 上,我第一次聽說(shuō) TiFlash 是 TiDB 的擴(kuò)展分析引擎。

它使用面向列的存儲(chǔ)技術(shù)來(lái)實(shí)現(xiàn)高數(shù)據(jù)壓縮率,并在數(shù)據(jù)復(fù)制中應(yīng)用擴(kuò)展的 Raft 一致性算法以確保數(shù)據(jù)安全性。

由于我們擁有高寫入吞吐量的海量數(shù)據(jù),因此我們無(wú)法每天使用 ETL 將數(shù)據(jù)復(fù)制到 Hadoop 進(jìn)行分析。但是對(duì)于 TiFlash,我們樂(lè)觀地認(rèn)為我們可以輕松分析我們龐大的數(shù)據(jù)量。

⑦反垃圾郵件應(yīng)用程序中的 TiDB 3.0

與 Moneta 應(yīng)用程序的巨大歷史數(shù)據(jù)大小相比,反垃圾郵件應(yīng)用程序具有更高的寫入吞吐量。

但是,它僅查詢過(guò)去 48 小時(shí)內(nèi)存儲(chǔ)的數(shù)據(jù)。在此應(yīng)用程序中,數(shù)據(jù)每天增加 80 億條記錄和 1.5 TB。

由于 TiDB 3.0 可以批量發(fā)送和接收 Raft 消息,并且它可以在多個(gè)線程中處理 Region Raft 邏輯,因此我們可以用更少的節(jié)點(diǎn)管理應(yīng)用程序。

以前,我們使用了七個(gè)物理節(jié)點(diǎn),但現(xiàn)在我們只需要五個(gè)。即使我們使用商用硬件,這些功能也可提升性能。

下一步是什么

TiDB 是一個(gè)與 MySQL 兼容的數(shù)據(jù)庫(kù),因此我們可以像使用 MySQL 一樣使用它。

由于 TiDB 的橫向可擴(kuò)展性,現(xiàn)在我們可以自由擴(kuò)展我們的數(shù)據(jù)庫(kù),即使我們有超過(guò)一萬(wàn)億的記錄來(lái)應(yīng)對(duì)。

到目前為止,我們已經(jīng)在我們的應(yīng)用程序中使用了相當(dāng)多的開源軟件。我們還學(xué)到了很多關(guān)于使用 TiDB 處理系統(tǒng)問(wèn)題的知識(shí)。

我們決定參與開發(fā)開源工具,并參與社區(qū)的長(zhǎng)期發(fā)展。基于我們與 PingCAP 的共同努力,TiDB 將變得更加強(qiáng)大。

來(lái)源:http://itindex.net

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評(píng)論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,343評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容