Hulu如何擴(kuò)展InfluxDB使其支持每秒百萬TPS
導(dǎo)讀:InfluxDB是最常用的時間序列數(shù)據(jù)庫之一,大家廣泛使用其開源版本。然而其開源版本缺乏一些高可用相關(guān)的特性,本文介紹Hulu在使用InfluxDB的過程中碰見的問題和解決方案,十分值得一讀。
隨著Hulu的持續(xù)增長,時間序列數(shù)據(jù)庫已成為公司監(jiān)控系統(tǒng)的關(guān)鍵部分。 這可以像機(jī)器性能指標(biāo)或應(yīng)用程序本身的數(shù)據(jù)一樣簡單處理。 由于我們擁有的數(shù)據(jù)量很大,因此創(chuàng)建一個支持冗余和可擴(kuò)展的體系結(jié)構(gòu)至關(guān)重要。
為什么時間序列數(shù)據(jù)很重要?
時間序列數(shù)據(jù)使我們能夠評估趨勢,以便發(fā)現(xiàn)問題并采取措施。
下圖用于確定最近的內(nèi)存泄漏,該問題會影響在特定數(shù)據(jù)中心運(yùn)行的應(yīng)用程序版本。
Graphite 架構(gòu)
最初,每個開發(fā)團(tuán)隊都有自己的時間序列數(shù)據(jù)解決方案。 由于大多數(shù)團(tuán)隊都有類似的需求,這種情況無疑是浪費(fèi)資源的。 為了解決這個問題,我們建立了原始的時間序列數(shù)據(jù)管道,該管道為整個工程團(tuán)隊提供了時間序列數(shù)據(jù)庫。
該管道基于Graphite,并將數(shù)據(jù)存儲到OpenTSDB。 在高峰時,該Graphite集群的吞吐量為每秒140萬個指標(biāo)。 在維持這一流程的同時,我們遇到了許多問題,這些問題隨著我們繼續(xù)增長而變得越來越常見。
其中許多問題源于為Hulu所有開發(fā)團(tuán)隊提供數(shù)據(jù)管道共享服務(wù), 這樣就需要支持巨大吞吐量和基數(shù),其他問題是來自于可伸縮性的固有問題。
數(shù)據(jù)管道遇到的挑戰(zhàn)
使用方經(jīng)常且無意間會在其標(biāo)準(zhǔn)名稱空間中發(fā)送唯一數(shù)據(jù),例如時間戳或另一個唯一標(biāo)識符。 例如:
- stats.application.dc1.1557471341.count 1 1557471341
- stats.application.dc1.1557471345.count 1 1557471345
- stats.application.dc1.1557471346.count 1 1557471346
這導(dǎo)致了命名空間中基數(shù)爆炸式增長,從而影響了接收速度和整個管道的穩(wěn)定性。盡管可以阻止這些行為,但是這樣做非常困難,因為需要匹配有問題的指標(biāo),而不能影響合法指標(biāo)。
由于吞吐量的限制,我們在創(chuàng)建規(guī)則的復(fù)雜性和數(shù)量方面受到限制,因為必須針對接收到的每個指標(biāo)使用所有規(guī)則進(jìn)行評估。這需要在指標(biāo)數(shù)據(jù)涉及的許多節(jié)點上以滾動的方式完成。因此通常很少會添加條件來阻止有問題的指標(biāo),一般傾向于讓應(yīng)用程序停止發(fā)送指標(biāo)。不幸的是,在大多數(shù)情況下,花費(fèi)的時間導(dǎo)致數(shù)據(jù)丟失。
檢索數(shù)據(jù)時,許多用戶會無意中運(yùn)行很長時間或占用大量資源的查詢,這最終將導(dǎo)致為其提供數(shù)據(jù)的后端超時并宕機(jī)。沒有叫停這種行為的限制,這也影響了整個系統(tǒng)的穩(wěn)定性。
發(fā)送的指標(biāo)也是有問題的。由于格式并沒有標(biāo)準(zhǔn)化,因此找出哪個服務(wù)正在發(fā)送特定指標(biāo)需要進(jìn)行大量猜測,而在我們實際需要這樣做時非常困難。
最后,由于我們的設(shè)置,所有指標(biāo)都被發(fā)送到了兩個數(shù)據(jù)中心之一。如果發(fā)生故障,則整個數(shù)據(jù)中心的指標(biāo)將無法訪問。此外,由于我們只有一個統(tǒng)一的接口來檢索這些指標(biāo),因此我們優(yōu)先于一個數(shù)據(jù)中心。這是有問題的,因為如果用戶向第一個優(yōu)先級數(shù)據(jù)中心發(fā)送了一個指標(biāo),但隨后決定使用另一個數(shù)據(jù)中心,由于第一個數(shù)據(jù)中心已經(jīng)存在命名空間,因此將無法訪問他們的新指標(biāo),從而導(dǎo)致問題。
InfluxDB初始架構(gòu)
為了解決這些問題,我們決定基于InfluxDB從頭開始重新構(gòu)建統(tǒng)計數(shù)據(jù)管道。 對于我們的第一次嘗試,我們創(chuàng)建了兩個集群,在兩個主要數(shù)據(jù)中心(DC1和DC2)中各有一個。 兩個群集將包含相同的數(shù)據(jù)。
在此基礎(chǔ)上構(gòu)建了一個指標(biāo)中繼群集。 所有指標(biāo)都將發(fā)送到中繼群集。 該集群的唯一目的是將收到的所有指標(biāo)推送到兩個InfluxDB集群中。 這樣就可以從任何數(shù)據(jù)中心檢索所有指標(biāo),從而完全消除了在Graphite體系結(jié)構(gòu)中遇到的指標(biāo)可用性問題。 我們在每個數(shù)據(jù)中心都有指標(biāo)中繼層。
在此指標(biāo)中繼層上,我們還實現(xiàn)了必需標(biāo)簽,這是Hulu中每個應(yīng)用程序的唯一標(biāo)識符。這使我們可以輕松地追溯每個指標(biāo)的來源。沒有此必需標(biāo)簽的所有指標(biāo)都會被刪除。
Hulu的所有機(jī)器上都運(yùn)行了Telegraf守護(hù)程序(https://github.com/influxdata/telegraf)。 我們已將該守護(hù)程序配置為報告所有計算機(jī)統(tǒng)計信息,并且還監(jiān)聽localhost上的指標(biāo)。我們鼓勵所有開發(fā)人員將指標(biāo)發(fā)送到localhost,因為我們已將Telegraf配置為自動為其接收的所有指標(biāo)添加標(biāo)準(zhǔn)標(biāo)簽。這些標(biāo)簽包括原始數(shù)據(jù)中心,計算機(jī)名稱和計算機(jī)ID。
此設(shè)置效果很好。我們測試過大于每秒200萬個指標(biāo)的吞吐量,沒有任何問題。然而我們很快遇到了一個問題,導(dǎo)致我們重新評估了當(dāng)前設(shè)置。
具體來說,我們的一個集群在一段時間內(nèi)不可用,導(dǎo)致所有指標(biāo)僅被推送到單個(在線)數(shù)據(jù)中心,然后在被復(fù)制到另一個集群之前被丟棄。一旦有問題的群集再次可用,數(shù)據(jù)就會出現(xiàn)差異,需要手動重新同步群集。我們意識到我們需要一種方法來更優(yōu)雅地解決此類問題,并減少人工干預(yù)。
InfluxDB改進(jìn)架構(gòu)
我們在設(shè)計中創(chuàng)建了兩個新層,其中包括每個數(shù)據(jù)中心內(nèi)的Kafka隊列,以及一個InfluxDB writer層以解決此問題。
指標(biāo)仍會發(fā)送到原始中繼群集,但不再從那里直接路由到InfluxDB群集。而是將其發(fā)送到數(shù)據(jù)中心內(nèi)的Kafka隊列。
InfluxDB writer層是在InfluxDB群集所在的每個數(shù)據(jù)中心中創(chuàng)建的。該層的唯一目的是連接到所有數(shù)據(jù)中心中的Kafka隊列,并將它們寫入其本地InfluxDB集群。如果其中一個InfluxDB集群發(fā)生故障,則該數(shù)據(jù)中心內(nèi)的writer將停止向該集群寫入數(shù)據(jù),但另一個數(shù)據(jù)中心將繼續(xù)提取其指標(biāo)。一旦有問題的群集重新聯(lián)機(jī)后,該數(shù)據(jù)中心內(nèi)的writer將繼續(xù)工作,并寫入本地的群集。最終兩個群集將再次處于一致狀態(tài)。
這種設(shè)計還使我們能夠完全禁用大部分基礎(chǔ)設(shè)施(甚至整個數(shù)據(jù)中心),并將它們路由到另一個數(shù)據(jù)中心,而對最終用戶沒有任何影響。
雖然此設(shè)計解決了我們的許多問題,但是依然有兩個問題沒有解決。
查詢限制
我們?nèi)匀挥龅介L時間運(yùn)行的查詢或者說有問題查詢的問題。 使用者有時會進(jìn)行很長時間的查詢(通常是偶然的),這會導(dǎo)致其他用戶使用時的性能下降。 我們?yōu)榇四康膭?chuàng)建了一個新的微服務(wù)Influx Imposer。
該應(yīng)用程序登錄到我們的兩個InfluxDB集群,并每分鐘檢查一次正在運(yùn)行的查詢。 如果超過某些閾值(例如60秒)或是危險/資源密集型查詢,則將其殺死。 我們還實現(xiàn)了終止查詢的日志記錄,并且已經(jīng)大大提高了系統(tǒng)穩(wěn)定性。
阻止/過濾“不良”指標(biāo)
使用者可能仍會在命名空間中發(fā)送帶有時間戳的指標(biāo),或者發(fā)送一些可能導(dǎo)致數(shù)據(jù)集基數(shù)非常大的數(shù)據(jù)。 為了解決這個特定問題,我們創(chuàng)建了另一個名為Barricade的微服務(wù)。
Barricade是由數(shù)據(jù)庫支持的API,其中包含動態(tài)黑名單。 如果任何時候需要將標(biāo)簽,指標(biāo)或幾乎任何其他信息列入黑名單,都會將其添加到此數(shù)據(jù)庫中。數(shù)據(jù)庫更改將同步到InfluxDB writer上的所有本地配置。 這些機(jī)器不斷輪詢Barricade以獲取其更新的黑名單規(guī)則。 如果檢測到更改,則writer將重新生成其本地備用配置。 之所以在InfluxDB writer層執(zhí)行此操作,是因為該層上的任何更改都不會導(dǎo)致指標(biāo)獲取中斷,因此添加新的黑名單對上層查詢是沒有影響的。
時間序列數(shù)據(jù)一直是并將繼續(xù)是Hulu評估趨勢并對之做出反應(yīng)的能力的重要組成部分。 我們能夠解決先前管道中的所有問題,現(xiàn)在正在將所有用戶移出舊平臺。 在撰寫本文時,我們的新統(tǒng)計信息流已經(jīng)處理超過每秒一百萬個指標(biāo),并且這個數(shù)據(jù)每天都在增長。