天天看點

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

本文将通過對時序資料的基本概念、應用場景以及京東智聯雲時序資料庫HoraeDB的介紹,為大家揭秘HoraeDB的核心技術架構和解決方案。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

首先我們來了解下時序資料庫的基本概念。時序資料庫全稱時間序列資料庫,主要用于處理帶時間标簽的資料,帶時間标簽的資料也稱為時序資料。

時序資料庫是一種高性能、低成本、穩定可靠的線上時序時空資料庫服務,提供高效讀寫、高壓縮比存儲、時序資料插值及聚合計算等服務,廣泛應用于服務和伺服器監控系統、物聯網(IoT)裝置監控系統、生産安全監控系統和電力檢測系統等行業場景。此外,它還能提供時空場景的查詢和分析能力。

時序資料庫中存儲的是時序資料,時序資料的結構特點和簡單舉例如下:

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

上圖展示的是一個服務和時間點緊密關聯的流量變化資料,資料如下:

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

Metric:時序資料的名額名稱;

Tags:對時序資料名額進行補充描述的标簽,描述清楚資料是什麼、來源等,友善後期對資料進行篩選和聚合計算等;

Dps:時序資料的資料點,是一系列随着時間變化的值,分為時間戳和具體的value兩個部分。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

證券交易:可以用時序資料庫來儲存随着時間波動的交易價格等資料;

氣溫變化情況:可以用時序資料庫存儲氣溫變化的資料,便于記錄和分析某個地區的氣溫變化波動規律;

伺服器監控:通過對大規模應用叢集和機房裝置的資料采集,存儲到時序資料庫中,就可以實時關注裝置運作狀态、資源使用率和業務趨勢,實作資料化營運和自動化開發運維;

物聯網傳感器:物聯網裝置無時無刻不在産生海量的裝置狀态資料和業務消息資料,這些資料有助于進行裝置監控、業務分析預測和故障診斷;

網站/服務監控資料:通過日志或者其他方式對原始名額資料進行采集和實時計算,最後将實時計算的結果資料存儲到時序資料庫,實作對網站和服務的監控和分析。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

時序資料的寫入:每秒需要有百萬至千萬量級的時序資料點寫入,并且寫入流量沒有低峰期和高峰期的區分,是以時序資料庫需要解決好如何7*24小時支援好百萬甚至上千萬級的時序資料寫入問題;

時序資料的讀取:如何低延遲解決好單個請求讀取百萬級資料點的查詢以及幾十萬級别資料計算和聚合問題;

成本問題:時序資料資料量級較大,且在業務上可能至少需要存儲一年以上的曆史資料,以便于後期來對資料進行分析和處理,是以時序資料庫需要解決好存儲成本的問題。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

HoraeDB是京東智聯雲自研的一款時序資料庫,在資料的寫入協定上完全相容OpenTSDB,資料的查詢上相容OpenTSDB restful API和PromQL。

HoraeDB主要有以下特點:

高性能:支援資料批量異步寫入,高并發查詢以及強大的資料計算和聚合能力;

高可用:資料存儲分布式架構,副本數和資料的一緻性級别靈活可調;可以根據需要,對資料的寫入做多AZ雙寫和HA查詢等;

使用成本低:豐富的資料類型,REST接口、資料寫入查詢均使用json格式,并且接口和協定上完全相容OpenTSDB和PromQL,曆史服務前移學習成本較低;

相容開源生态:相容OpenTSDB和PromQL協定以及開源的Kibana元件,可以友善的使用開源生态中已存在的工具群組件對時序資料進行查詢、分析和展示等。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密
輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

HoraeDB在整體架構上從上往下進行分層,大概可以分為以下幾層:

Http-Server層:主要負責HTTP服務端口的監聽、接收以及響應使用者的請求;

協定處理層:這層是負責對接各種已有的開源元件的協定。主要是包括OpenTSDB-Parser、Prometheus-Adapter、Remote-Read、Remote-Write等幾個元件:

◆OpenTSDB-Parser:負責對目前開源的OpenTSDB的請求協定進行解析和處理,包括查詢請求和響應請求;

◆ Prometheus-Adapter:對PromQL查詢文法進行解析,解析成HoraeDB内部标準的查詢協定;

◆ Remote-Read:實作Prometheus的Remote-Read模式,可以使用Prometheus來查詢HoraeDB中的資料,具體配置使用方式可以參考Prometheus配置說明;

◆ Remote-Writer:實作Prometheus的Remote-Write模式,可以在生産環境中将HoraeDB作為Prometheus的分布式叢集存儲解決方案,将Prometheus中采集到的資料寫入到HoraeDB。具體配置使用方式可以參考Prometheus配置說明。

HoraeDB協定層:包括HoraeDB-PutReq和HoraeDB-QueryReq,這一層主要是定義好HoraeDB自身寫入的資料的結構和查詢請求的結構;

處理引擎層:包括了write-engine和query-engine,這層是分别進行資料寫入和查詢的處理邏輯;

資料隊列:這一層主要是針對資料寫入而言的,資料要寫入到底層存儲,會先寫到隊列中,然後消費端根據配置檔案的指定的後端,進行資料的處理;

存儲Client層:适配各種各樣的三方存儲元件,負責資料的持久化存儲處理,目前實作了ES-Client、Cassandra-Client、Cache-Client、Local-Storage:

◆ ES-Client:負責将時序資料中的Meta部分資訊寫入到ES進行存儲;

◆ Cassandra-Client:負責将時序資料中的資料點寫入到Cassandra中進行持久化存儲;

◆ Cache-Client:将新寫入的熱點時序資料寫入到高速緩存元件,對熱點資料進行Cache。

資料存儲層

◆ Cassandra:存儲時序資料中的資料點;

◆ ES:存儲時序資料中的Meta資訊;

◆ TS-Cache:自研的時序資料Cache系統,内部使用delta-delta和XOR編碼方式對時序資料的時間戳和值進行壓縮,可以存儲最近三小時的熱點時序資料。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密
輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

HoraeDB在底層資料存儲将時序資料拆分成兩部分進行存儲,一部分是meta資料,這部分資料主要是對時序資料進行描述的,描述了一條時間序列是什麼,來自于哪裡;另外一部分是時序資料點,包括時間戳和具體的值,這部分資料是會随着時間變化,周期性上報的部分。例如下面一條資料:

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

Meta部分包括了name、tags、additionTag等三個部分,對一條時間線進行了描述;

資料點部分包括了timeStamp和value,是具體的時序資料點。

它們各自的特點如下:

Meta

◆ 寫入後,基本不會有變更;

◆ 需要支援多元度,多種方式進行資料篩選,比如Tag精确比對,字首搜尋、正則比對等多種搜尋;

◆ 資料量相對小。

時序資料點

◆ 周期性彙報;

◆ 和時間戳強關聯;

◆ 需要支援按照時間範圍進行資料篩選;

◆ 資料量大。

根據以上特點,我們在資料持久化存儲中,針對Meta和時序資料點,分别選擇了Elasticsearch和Cassandra來進行資料存儲。

Elasticsearch

Elasticsearch是一個基于RESTful web接口并且建構在Apache Lucene之上的開源分布式搜尋引擎。

同時ES還是一個分布式文檔資料庫,其中每個字段均可被索引,而且每個字段的資料均可被搜尋,能夠橫向擴充至數以百計的伺服器存儲以及處理PB級的資料。可以在極短的時間記憶體儲、搜尋和分析大量的資料。

Cassandra

Cassandra是一套開源分布式NoSQL資料庫系統。具有以下特點:

線性擴充,輕松應對速度、多樣性和複雜性問題:Cassandra是線性擴充,可以根據前台資料流量輕松确定叢集規模;

架構簡單,運維成本低:Cassandra不依賴外部元件,所有必須的操作都內建在Cassandra内部了。同時,由于它是P2P對等架構,無主,環上的節點都是對等的,極度簡化部署及後續運維工作,适合大規模部署;

高可用:Cassandra采用了許多容錯機制。由于Cassandra是無主的,是以沒有單點故障,可以做到不停服滾動更新。這是因為Cassandra可以支援多個節點的臨時失效(取決于群集大小),對叢集的整體性能影響可以忽略不計。Cassandra提供多地域容災,允許您将資料複制到其他資料中心,并在多個地域保留多副本。

HoraeDB在Cassandra中的Schema定義:

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

行定位:uuid + partitionKey來唯一定位到一行資料,uuid是根據name + 排序後的Tag來計算出來的,唯一可以表示單個時間序列的ID, partitionKey是由程式來定義的劃分行的字元串,比如按照天來劃分行,那麼我們就可以傳入資料時間戳的當天日期;

列定位:每列由資料的時間戳來表示,每個時序點占一列,每列中包含value和createTime字段。value是經過編碼後的資料,createTime是由時序資料點到來的時間計算出的timeUUID來表示,用于支援多版本的特性。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

業務對于監控資料的使用需求多種多樣,有查最新資料的異常告警,也有檢視一整年名額資料的趨勢圖展示,資料量越大查詢耗時就越久,如果放在浏覽器端處理也要耗費大量的記憶體。這不但對系統造成了很大的壓力,也給使用者帶來了難以忍受的查詢體驗。鑒于此,我們引入了多級的降采樣機制來應對不同跨度的資料查詢。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

如上圖所示,提前降低采樣算法就是将連續不斷流入的時序資料點來進行分桶,計算出這個桶内的均值、最大值、最小值、總和等,這樣使用者在查詢資料的時候,直接傳回合适的采樣資料即可。

為了提供多種粒度的資料,HoraeDB支援對原始資料進行多級降采樣,比如可以将原始資料降采樣成10m和1h粒度的資料。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

流式抽樣的核心處理思想如上圖所示:在HoraeDB的記憶體中儲存了每個時間序列。每個序列上都維護了目前這個序列的cnt、sum、max、min、last等值,随着時間的推移,時序資料點源源不斷的流入,相應序列上的cnt、sum、max、last都會進行累加或者值更新,當到達設定的時間視窗,比如10分鐘,就會将計算後的結果存入到Cassandra中。

流式抽樣中需要解決的難點主要有兩個:資料遲到問題和時間視窗到達後對底層Cassandra的壓力沖擊。HoraeDB對這些問題的解決方案如下:

資料遲到問題:為了解決資料遲到問題,HoraeDB的資料抽樣器對每個時間序列的抽樣結果暫存一個周期,等待遲到的資料到來,然後再存入到底層Cassandra;

時間視窗到達,對底層尖峰流量:資料發送使用了令牌桶算法來進行資料的發送,控制資料發送頻率。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

在時序的場景下,我們經常會有一些大批量資料分析計算的需求。比如需要計算10萬個伺服器30分鐘内的cpu變化趨勢。這樣的查詢會很慢,同時也會導緻我們的時序存儲服務不穩定。

為了應該對這種業務場景,我們做了預聚合計算方案,預聚合計算分為流式聚合計算和批量計算。如下圖所示:

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

流式聚合計算

對于大規模時序資料分析場景,我們采用流式聚合計算,如上圖所示,資料上報到kafka。我們的Flink Job會根據使用者提前配置好的聚合規則,對流入的資料進行聚合計算,計算完成後,寫回到我們的存儲中,流式聚合計算有以下的特點:

◆ 計算性能強,可橫向擴充;

◆ 計算支援靈活性相對較弱;

◆ 需要部署單獨的計算等元件。

批量聚合計算

批量聚合計算使用的是拉模式進行資料聚合計算,核心邏輯是HoraeDB根據使用者建立的聚合規則,設定一些定時計算任務,計算任務會定時向底層存儲層發起資料拉取和計算,計算結果寫回到存儲中,批量聚合計算有以下的特點:

◆ 計算靈活性強;

◆ 無需單獨部署計算元件和消息隊列;

◆ 支援到5w線左右,對底層存儲開銷高。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密
輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

HoraeDB原有架構下,做一些大批量資料查詢和計算時存在以下問題:

聚合性能低:原有引擎在執行聚合運算的時候,也和傳統資料庫所通常采用的iterative執行模式一樣,疊代執行聚合運算。問題在于每次iteration執行,傳回的是一個時間點。Iterative 執行每次傳回一條時間點,但對HoraeDB查詢有可能需要通路大量時間線資料,這樣的執行方式效率上并不可取;

查詢速度慢

◆ 從Cassandra查詢資料是一個比較耗時的過程,會耗費比較長的時間在資料準備上;

◆ 整個計算過程需要等Cassandra中的資料全加載到記憶體中,才開始計算。

記憶體和CPU資源消耗高

◆ HoraeDB有可能在短時間内下發太多Cassandra讀請求,一個查詢涉及到的Cassandra讀請求同時異步送出,有可能在很短時間内向Cassandra下發大量的讀請求。這樣,一個大查詢就有可能把底層的Cassandra打爆;

◆ 同時拉取大量的資料點到記憶體中,會導緻HoraeDB記憶體打爆。

新的查詢引擎針對老的查詢計算引擎進行了優化:

借鑒傳統資料庫執行模式,引入Pipeline的執行模式。Pipeline包含不同的執行計算算子(operator),一個查詢被實體計劃生成器解析分解成一個Query Plan, 由不同的執行算子組成,DAG上的root operator負責驅動查詢的執行,并将查詢結果傳回調用者。在執行層面,采用的是top-down需求驅動的方式,從root operator驅動下面operator的執行。這樣的執行引擎架構具有如下優點:

這種架構方式被很多資料庫系統采用并證明是有效的;

接口定義清晰,不同的執行計算算子可以獨立優化,而不影響其他算子;

易于擴充:通過增加新的計算算子,很容易實作擴充功能。比如目前查詢協定裡隻定義了tag上的查詢條件。如果要支援名額值上的查詢條件(cpu.usage >= 70% and cpu.usage <=90%),可以通過增加一個新的ValueFilterOp來實作。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

時序資料中,一般情況下,最近三個小時的資料是被查詢比較多的熱點資料,在HoraeDB中,為了加速這部分資料的通路,我們把最近三小時的資料放到自研的分布式緩存元件-TS-Cache中去。

TS-Cache是一個分布式的資料緩存系統,資料通過Hash算法均勻的分布在各個TS-Cache節點中。因為TS-Cache是個緩存元件,對資料的穩定性要求并沒有那麼高,是以我們的時序資料在TS-Cache中儲存的是單副本。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

資料在記憶體中的組織如上圖所示,資料的頂層是一個SharedMap,它其實就是一個數組,目的是用來在内部對時序資料進行分片,降低gc對服務性能的影響,以及适當的減小鎖的粒度,提升服務的讀寫性能。資料中的一個項就是SeriesMap,用來儲存時序資料項和它的時序資料點的值,其内部的核心資料結構是一個跳表,跳表中的每一項對應的是一個時序資料中的一個項,在這邊用SeriesData來進行表示。

SeriesData中有兩個核心的資料結構,一個是cs,一個是blocks,cs是我們的一個流式壓縮序列,這個流式壓縮需要時根據上面所述的壓縮算法來進行實作的,時序資料寫入系統後,會直接寫到這個壓縮序列cs中,每隔一定時間,會把壓縮序列中的資料導出,形成一個block資料塊,寫到blocks數組中。

為了用更少的記憶體來存儲更多的資料,在TS-Cache中的資料是壓縮成為block後進行存儲,放到了上圖的blocks數組中進行存儲;資料壓縮算法使用的是Gorilla這篇論文所提出的資料壓縮算法,Gorilla引入了對timestamp和value的高壓縮比算法,可大幅降低資料存儲的大小。

Timestamp根據時間關聯的條目進行內插補點計算、以及內插補點的內插補點計算得到占用位元組數非常小的數值并進行儲存。同樣Value使用XOR算法進行計算得到占用存儲更小的數值進行儲存。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

時間戳壓縮:時序資料的産生大部分情況下都是有周期性的,可能是30s、1m等,是以在存儲時間戳的時候,我們隻需要存儲時間戳直接的內插補點;

值壓縮:通過對曆史資料進行分析,發現大部分相鄰時間的時序資料的值比較接近,而如果Value的值比較接近,則在浮點二進制表示的情況下,相鄰資料的Value會有很多相同的位。整數型資料的相同位會更多。相同位比較多,意味着如果進行XOR運算的話會有很多位都為0,那麼我們将目前值與前序值取XOR(異或)運算,儲存XOR運算結果。

輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密
輕松支撐百萬級資料點寫入 京東智聯雲時序資料庫HoraeDB架構解密

HoraeDB作為一個海量時序資料的存儲系統,經常會遇到一些突發性的流量高峰或者一些不合理的大查詢、慢查詢,如何保障HoraeDB的穩定性便成了一個要攻破的技術難點。

為了保障HoraeDB的穩定性,我們做了以下幾個方面的工作:

服務隔離;

HoraeDB讀寫分離:讀寫分别部署不同執行個體,避免大查詢慢查詢影響資料寫入;

計算處理層和存儲層分離:資料寫入和查詢處理邏輯在HoraeDB層做,底層資料存儲放到存儲層進行;

機房隔離:HoraeDB部署上支援多寫,底層存儲可以配置不同機房,實作資料多寫互備,查詢支援多機房HA查詢;

限流

◆ 在HTTP接口層支援接口調用頻率進行限流;

◆ 針對寫入,HoraeDB内部通過寫入隊列來感覺目前寫入負載,當隊列滿,即丢棄資料,保護HoraeDB正常工作;

◆ 查詢上,基于查詢時間跨度、時間線條數、資料點規模等進行了限制,避免大查詢影響系統穩定性。

查詢負載管理:因為在我們的時序資料查詢場景中,80%以上的情況都是查詢最近三小時内的資料,都是一些查詢和計算量比較小的查詢任務,是以在查詢上我們根據查詢請求進行計算量簡單預估,分為慢查詢和快查詢,分别放入到對應的查詢任務隊列,避免慢查詢影響快查詢;

綜合全面的服務監控名額,HoraeDB的問題可以快速被發現和定位。