您好,登錄后才能下訂單哦!
??雖然TSDB被設計為只要有空間就可以存儲原始全分辨率(resolution)的數據,但是對于廣泛的時間范圍或在許多標簽組合之上的查詢可能是相當痛苦的。這樣的查詢可能需要很長時間才能完成,或者在最糟糕的情況下,可能會導致內存不足的異常。從OpenTSDB 2.4開始,一組新的API允許存儲和查詢較低分辨率的數據以更快地回答這樣的查詢。本頁將概述上卷和預聚合是什么,它們如何在TSDB中工作以及如何最好地使用它們。查看API部分的具體實現細節。
注意:
??OpenTSDB本身不計算和存儲上卷或預聚合數據。有多種計算結果的方法,但是根據規模和精度要求,它們都有好處和缺點。請參閱生成上卷和預聚合部分,討論如何創建此數據。
??為了幫助描述較低分辨率的數據,我們來看一些完整的分辨率(也稱為原始數據)的示例數據。第一個表格用快捷標識符定義時間序列。
序列ID | Metric | Tag1 | Tag2 | Tag3 |
---|---|---|---|---|
ts1 | system.if.bytes.out | host=web01 | colo=lga | interface=eth0 |
ts2 | system.if.bytes.out | host=web02 | colo=lga | interface=eth0 |
ts3 | system.if.bytes.out | host=web03 | colo=sjc | interface=eth0 |
ts4 | system.if.bytes.out | host=web04 | colo=sjc | interface=eth0 |
請注意,它們都具有相同metric和interface標記,但不同host和colo標簽。
接下來以15分鐘的時間間隔寫出一些數據:
序列ID | 12:00 | 12:15 | 12:30 | 12:45 | 13:00 | 13:15 | 13:30 | 13: 45 |
---|---|---|---|---|---|---|---|---|
ts1 | 1 | 4 | -3 | 8 | 2 | -4 | 5 | 2 |
ts2 | 7 | 2 | 8 | -9 | 4 | 1 | 1 | |
ts3 | 9 | 3 | -2 | -1 | 6 | 3 | 8 | 2 |
ts4 | 2 | 5 | 2 | 8 | 5 | -4 | 7 |
請注意,有些數據點丟失。有了這些數據集,我們先看看上卷。
??在OpenTSDB中,“上卷”被定義為隨著時間的推移聚合匯總的單個時間序列。它也可以被稱為“基于時間的聚合”。上卷幫助解決在廣泛的時間跨度的問題。例如,如果每60秒寫入一個數據點并查詢一年的數據,則時間序列將返回超過525,000個單獨的數據點。圖表會有很多點并且很可能會相當凌亂。相反,可能需要查看較低分辨率的數據,例如,只需要8k左右1小時數據進行繪圖。然后,可以識別異常并向下鉆取更精細的分辨率數據。
??如果您已經使用OpenTSDB查詢數據,則您可能熟悉將每個時間序列聚合為更小或更低分辨率值的降采樣器。上卷實質上是系統中存儲的降采樣的結果,并隨意調用。每個上卷(或降采樣器)需要兩條信息:
警告
??存儲上卷時,最好避免平均值,中值或偏差等函數(average, median or deviation)。在進一步降采樣或分組聚合時,這些值變得毫無意義。相反,總是存儲總和(sum)和計數(count)要好得多,至少可以在查詢時計算平均值。有關更多信息,請參閱下面的部分。
??上卷數據點的時間戳應該捕捉到(snap to)上卷間隔的頂部。例如,如果匯總間隔是1h那么它包含1小時的數據,并應該快速(snap to)到小時的頂部。(因為所有的時間戳都是用Unix Epoch格式編寫的,定義為UTC時區,所以這將是一個小時UTC時間的開始)。
對于前述給定的數據,使用1h的間隔存儲sum和count。
序列ID | 12:00 | 13:00 |
---|---|---|
ts1 SUM | 10 | 5 |
ts1 COUNT | 4 | 4 |
ts2 SUM | 8 | 6 |
ts2 COUNT | 4 | 3 |
ts3 SUM | 9 | 19 |
ts3 COUNT | 4 | 4 |
ts4 SUM | 9 | 16 |
ts4 COUNT | 3 | 4 |
??請注意,無論間隔“bucket”中的第一個數據點何時出現,所有時間戳都對齊到小時的頂部。另請注意,如果一個數據點在一段時間內不存在,則計數較低。
??在一般情況下,在每個時間序列存儲上卷時,目標應該是計算和存儲MAX,MIN,SUM和COUNT。
??當啟用上卷并且請求使用OpenTSDB 的avg函數的降采樣器時,TSD將掃描存儲中SUM和COUNT值。然后在迭代數據的時候,它會精確地計算平均值。
??COUNT和SUM值的時間戳必須匹配。但是,如果一個SUM的預期計數COUNT值缺失,則SUM將會被踢出結果。從上面的例子中,現在我們丟失了一個計數數據點ts2。
序列ID | 12:00 | 13:00 |
---|---|---|
ts1 SUM | 10 | 5 |
ts1 COUNT | 4 | 4 |
ts2 SUM | 8 | 6 |
ts2 COUNT | 4 |
所得到的一個2h降采樣的avg查詢應該是這樣的:
序列ID | 12:00 |
---|---|
ts1 AVG | 1.875 |
ts2 AVG | 2 |
ts1: (10+5)/8=1.875
ts2: 8/4=2
??雖然上卷可以幫助處理較長時間的查詢,但是如果度量具有較高的基數(即給定度量的唯一時間序列數量),仍然可能遇到小范圍查詢性能問題。在上面的例子中,我們有4臺Web服務器。即使我們有10,000臺服務器。獲取網絡流量(interface traffic)的總和或平均值可能會相當慢。如果用戶經常拉取大量分組集合(或一些將它作為空間集合)的話,存儲聚合和查詢替代很有意義,這樣會獲取更少的數據。
??與上卷不同,預聚合只需要一條額外的信息:
??在OpenTSDB中,預聚合與其他帶有特殊標簽的時間序列不同。默認標簽key是_aggregate(可通過tsd.rollups.agg_tag_key配置)。然后用于生成數據的聚合函數以大寫形式存儲在標簽值中。讓我們看一個例子:
??考慮到頂部的示例,我們可能想要查看colo(數據中心)的總網絡流量。在這種情況下,我們可以通過SUM和COUNT聚合,類似于上卷。結果將是四個伴隨元數據的新的時間序列,如:
序列ID | Metric | Tag1 | Tag2 |
---|---|---|---|
ts1’ | system.if.bytes.out | colo=lga | _aggregate=SUM |
ts2’ | system.if.bytes.out | colo=lga | _aggregate=COUNT |
ts3’ | system.if.bytes.out | colo=sjc | _aggregate=SUM |
ts4’ | system.if.bytes.out | colo=sjc | _aggregate=COUNT |
??請注意,這些時間序列已經丟棄了host和interface標簽。這是因為,聚合過程中,取了host和interface的多個不同的值,已經包裝到這個新的序列,如果再讓他們作為標簽,不會再有意義。另外請注意,我們在存儲的數據中注入了新的標簽_aggregate。現在查詢可以通過指定一個_aggregate值來訪問這些數據。
注意:
??啟用了上卷后,如果您計劃使用預聚合,則可能需要通過讓TSDB自動注入_aggregate=RAW來幫助區分預聚合中的原始數據。只需將tsd.rollups.tag_raw屬性設置為true。
??現在結果數據如下:
序列ID | 12:00 | 12:15 | 12:30 | 12:45 | 13:00 | 13:15 | 13:30 | 13:45 |
---|---|---|---|---|---|---|---|---|
ts1’ | 8 | 6 | 5 | -1 | 6 | -4 | 6 | 3 |
ts2’ | 2 | 2 | 2 | 2 | 2 | 1 | 2 | 2 |
ts3’ | 9 | 5 | 3 | 1 | 14 | 8 | 4 | 9 |
ts4’ | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
??由于我們正在通過聚合(通過colo分組)來執行分組,所以我們為每個時間戳從原始數據集中獲取一個值。在這種情況下,我們不采用降采樣或者上卷。
聚合算法:
??根據colo分組,因此ts1與ts2一組,ts3與ts4一組。
ts1’ => SUM: 1+7=8 4+2=6 …
ts2’ => COUNT: 2 2 …
ts3’ => SUM: 9 3+2=5 …
ts4’ => COUNT: 1 2 …
警告
??和上卷一樣,在編寫預聚合時,最好避免平均值,中值或偏差等函數。只是存儲總和和計數。
??雖然預聚合肯定有助于高基數的指標,但用戶可能仍然希望查詢訪問廣泛的時間跨度,但遇到緩慢的查詢。謝天謝地,可以像原始數據一樣進行上卷預聚合。只要生成預聚合,然后使用上面的信息將其上卷起來。
??目前,TSD不會為您生成上卷數據或預聚合數據。主要原因是意味著OpenTSDB處理大量的時間序列數據,所以單個TSD專注于盡可能快地將數據存儲到存儲中。
??由于TSD的(基本上)無狀態特性,它們可能不具備用于執行預聚合的全套數據。例如,我們的樣本ts1數據可能在寫入TSD_A的同時ts2被寫入TSD_B。不從存儲中讀取數據,也不能執行正確的分組。我們也不知道我們應該在什么時候進行預聚合。我們可以等待1分鐘,然后預先聚合數據,但會錯過那一分鐘后發生的任何事情。或者我們可以等待一個小時,預先聚合的查詢將不會有最后一個小時的數據。如果數據來得太晚,會發生什么?
??此外,對于上卷,根據用戶向TSD寫入數據的方式,對于ts1來說,我們可能會收到TSD_A上12:15的數據點,但是數據在12:30到達了TSD_B,因此整個小時都不需要數據(neither has the data required for the full hour)。時間窗口限制也適用于上卷。
??使用上卷和預聚合需要一些分析和各種權衡之間的選擇。由于一些OpenTSDB用戶已經具備了計算這類數據的方式和手段,我們只需提供API來存儲和查詢。但是,這里有一些關于如何自己計算這些的提示。
??其他時間序列數據庫常用的一種方法是在延遲一段時間后從數據庫中讀取數據,計算出預聚合和上卷,然后寫入數據。這是解決這個問題的最簡單的方法,在小規模下運作良好。但是仍然有一些問題:
改進批處理的一些方法包括:
??某些數據庫使用的另一個選項是將所有數據排列在進程中的內存中,并在經過配置的時間窗口后寫入結果。但是由于TSD是無狀態的,通常用戶在其TSD之前放置一個負載均衡器,所以單個TSD可能無法得到整個上卷或預聚合的所有數據進行計算(如上所述)。為了使這種方法起作用,上游收集器必須將計算所需的所有數據發送到特定的TSD。這不是一個困難的任務,但面臨的問題包括:
??一般來說,在Writer上排隊是一個壞主意。避免痛苦。
??處理上卷和預聚合的一種更好的方法是將數據發送到流處理系統,在那里它可以被近乎實時地處理并寫入到TSD中。它類似于TSD上的排隊選項,但使用無數的流處理框架之一(Storm,Flink,Spark等)來處理消息路由和內存中的存儲。然后,您只需編寫一些代碼來計算聚合,并在窗口過去后將數據吐出。
??這是許多下一代監控解決方案所使用的解決方案,例如雅虎!雅虎正在努力為需要大規模監控的其他人開放流處理系統,并將其整齊地插入到TSDB中。
雖然流處理更好,但您仍然遇到以下問題:
??如果您有計算聚合的工作代碼,請與OpenTSDB組共享。如果您的解決方案是開源的,我們可能會將其納入OpenTSDB生態系統。
??對于Opentsdb 2.4,上卷配置由opentsdb.conf中的Key tsd.rollups.config引用。此鍵的值必須是引號轉義的JSON字符串,不帶換行符,或者最好是包含配置的JSON文件的路徑。文件名必須如rollup_config.json一樣以.json 結尾。
JSON配置應該如下所示:
{
"aggregationIds": {
"sum": 0,
"count": 1,
"min": 2,
"max": 3
},
"intervals": [{
"table": "tsdb",
"preAggregationTable": "tsdb-preagg",
"interval": "1m",
"rowSpan": "1h",
"defaultInterval": true
}, {
"table": "tsdb-rollup-1h",
"preAggregationTable": "tsdb-rollup-preagg-1h",
"interval": "1h",
"rowSpan": "1d"
}]
}
兩個頂級的字段包括:
aggregationIds: 將OpenTSDB聚合函數名稱映射到用于壓縮存儲的數字標識符的映射。
intervals: 包含表名和間隔定義的一個或多個間隔定義的列表。
??aggregation ids映射用于通過將每種類型的上卷數據預先加上數字ID來減少存儲量,而不是拼出完整的匯總函數。例如,如果我們COUNT:為每個值的每個列(或壓縮列)添加6個字節,我們可以使用一個ID保存。
??ID必須是從0到127的整數。這意味著我們可以在每個間隔中存儲多達128個不同的上卷。在map中只能為每個數值提供一個ID,并且只能為每個類型給定一個聚合函數。如果函數名稱沒有映射到OpenTSDB支持的聚合函數,則會在啟動時引發異常。同樣,至少要給定一個聚合,才能啟動TSD。
警告
??一旦開始寫入數據,聚合ID將無法更改。如果更改映射,則可能會返回不正確的數據,或者查詢和寫入操作可能會失敗。您可以隨時添加函數,但不能改變映射。
??每個間隔對象都定義了表格路由,以便上卷和預先聚合的數據寫入并查詢。有兩種類型的間隔:
??應該定義下列字段:
名稱 | 數據類型 | Required | 描述 | 示例 |
---|---|---|---|---|
table | String | Required | 非預先匯總的數據的基礎或上卷表。對于默認表,應該是tsdb或現有的原始數據被寫入的表。對于上卷的數據,它必須與原始數據不同表。 | tsdb-rollup-1h |
preAggregationTable | String | Required | 應該寫入預先聚合的數據和(可選)上卷數據的表。它可能與table值相同,為同一張表。 | tsdb-rollup-preagg-1h |
interval | String | Required | 格式為“<interval><units>”中數據點之間的預期間隔。例如,如果每小時計算一次上卷,則間隔應為1h。如果每10分鐘計算一次,則將其設置為10m。對于默認表,該值將被忽略。 | 1h |
rowSpan | String | Required | 存儲中每行的寬度。此值必須大于interval和interval中定義的數字。 例如,如果interval是1h,rowSpan是1天,則每行會有24個值。 | 1d |
defaultInterval | Boolean | Optional | 是否將配置的時間間隔作為原始未滾動數據的默認值。 | true |
??在存儲中,上卷的編寫類似于原始數據,每行都有一個基準時間戳,每個數據點是相對于基準時間的偏移量。每個偏移量都是基準時間以外的增量,而不是實際的偏移量。例如,如果一行存儲1天of 1小時的數據,則會有多達24個偏移量。偏移0將映射到午夜的行,偏移量5將映射到上午6點。因為上卷偏移量是以14位編碼的,所以如果一行中存儲的間隔太多以便適應14位,TSD啟動時會引發錯誤。
警告
??將數據寫入TSD之后,不要更改上卷間隔的間隔寬度或行跨度。這將導致垃圾數據和可能失敗的查詢。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。