OpenTSDB寫資料(一)
寫在前面
寫入的一些配置和設計會對OpenTSDB資料庫效能產生影響,所以這不單單是簡單的資料輸入,第一部分主要是對資料的寫規入規範。
寫資料(Writing Data)
您可能希望直接進入並開始將資料投入TSD,但要真正利用OpenTSDB的強大功能和靈活性,您可能需要暫停並考慮您的命名模式。完成此操作後,您可以繼續通過Telnet或HTTP API推送資料,或使用具有OpenTSDB支援的現有工具,例如'tcollector'。
命名架構(Naming Schema)
許多度量管理員習慣於為其時間序列提供單個名稱。例如,用於RRD風格系統的系統管理員可以命名他們的時間序列webserver01.sys.cpu.0.user
0
on 使用者空間的時間量webserver01
。如果您想稍後在該特定Web伺服器上僅檢索該cpu核心的使用者時間,則此方法很有用。
但是,如果Web伺服器有64個核心並且您希望獲得所有核心的平均時間,該怎麼辦?某些系統允許您指定萬用字元,例如webserver01.sys.cpu.*.user
讀取所有64個檔案並彙總結果的萬用字元。或者,您可以記錄一個名為webserver01.sys.cpu.user.all
相同聚合的新時間序列,但您現在必須編寫'64 + 1'個不同的時間序列。如果您有一千個Web伺服器並且您想要所有伺服器的平均CPU時間,該怎麼辦?您可以製作一個外卡查詢*.sys.cpu.*.user
webservers.sys.cpu.user.all
。
OpenTSDB通過引入“標籤”的概念來處理事情。每個時間序列仍然具有“度量”名稱,但它更通用,可以由許多獨特的時間序列共享。相反,唯一性來自標記鍵/值對的組合,允許使用非常快速的聚合進行靈活查詢。
注意
每次OpenTSDB中的系列必須至少有一個標籤。
以前面的度量標準示例為例webserver01.sys.cpu.0.user
。在OpenTSDB中,這可能會成為。現在,如果我們想要單個核心的資料,我們可以製作一個類似的查詢。如果我們想要所有核心,我們只需刪除cpu標記並要求。這將為我們提供所有64個核心的彙總結果。如果我們想要所有1,000臺伺服器的結果,我們只需要求。底層資料模式將儲存彼此相鄰的所有時間序列,以便聚合各個值非常快速和高效。OpenTSDB旨在儘可能快地進行這些聚合查詢,因為大多數使用者都是從較高級別開始,然後深入瞭解詳細資訊。sys.cpu.userhost=webserver01, cpu=0``sum:sys.cpu.user{host=webserver01,cpu=42}``sum:sys.cpu.user{host=webserver01}``sum:sys.cpu.user``sys.cpu.user
聚合
雖然標記系統很靈活,但如果您不瞭解OpenTSDB的查詢方面,可能會出現一些問題,因此需要一些預先考慮。就拿上面的例子中查詢:sum:sys.cpu.user{host=webserver01}
。我們webserver01
為每個CPU核心記錄了64個唯一的時間序列,一個時間序列。當我們發出該查詢時,sys.cpu.user
帶有標記的度量標準的所有時間序列host=webserver01
都被檢索,平均,並作為一系列數字返回。假設結果平均值是50
時間戳1356998400
。現在我們正在從另一個系統遷移到OpenTSDB,並且有一個預先聚合所有64個核心的程序,以便我們可以快速獲得平均值並簡單地編寫一個新的時間序列。如果我們執行相同的查詢,我們將獲得值atsys.cpu.user host=webserver01``100``1356998400
。發生了什麼?OpenTSDB彙總了所有64個時間序列和預先聚合的時間序列,以達到100個。在儲存中,我們會有這樣的事情:
SYS 。cpu 。user host = webserver01 1356998400 50 sys 。cpu 。user host = webserver01 ,cpu = 0 1356998400 1 sys 。cpu 。user host = webserver01 ,cpu = 1 1356998400 0 sys 。cpu 。user host = webserver01 ,cpu = 2 1356998400 2 SYS 。cpu 。user host = webserver01 ,cpu = 3 1356998400 0 ... sys 。cpu 。user host = webserver01 ,cpu = 63 1356998400 1
如果沒有給出標記,OpenTSDB將自動聚合查詢中度量的所有時間序列。如果定義了一個或多個標記,則聚合將“包括”與該標記匹配的所有時間序列,而不管其他標記。與查詢sum:sys.cpu.user{host=webserver01}
,我們將包括和,和。這個例子的寓意是:小心你的命名模式。sys.cpu.user host=webserver01,cpu=0``sys.cpu.userhost=webserver01,cpu=0,manufacturer=Intel``sys.cpu.user host=webserver01,foo=bar``sys.cpu.user host=webserver01,cpu=0,datacenter=lax,department=ops
時間序列基數(Time Series Cardinality)
任何命名方案的一個關鍵方面是考慮時間序列的基數。基數定義為集合中唯一專案的數量。在OpenTSDB的情況下,這意味著與度量相關聯的專案數,即所有可能的標記名稱和值組合,以及唯一度量標準名稱,標記名稱和標記值的數量。基數由於下面列出的兩個原因很重要。
有限的唯一ID(UID)
為每個指標,標記名稱和標記值分配的數量有限。預設情況下,每種型別只有超過1600萬個可能的ID。例如,如果您執行非常流行的Web服務並嘗試將客戶端的IP地址作為標記進行跟蹤,例如,您可能很快就會遇到UID分配限制,因為有超過40億個可能的IP版本4地址。此外,這種方法會導致建立一個非常稀疏的時間序列,因為地址處的使用者可能只是零星地使用您的應用程式,或者可能永遠不會再使用該特定地址。web.app.hits clientip=38.26.34.10``38.26.34.10
對於標籤很少更改的小型安裝(例如,庫存符號或一組固定的感測器),UID大小可能不是問題。為標記值分配一個與其標記名稱完全取消關聯的UID。如果對標記值使用數字識別符號,則會為該編號分配一次UID,並且可以與許多標記名稱一起使用。例如,如果我們分配一個UID與數2
,我們可以儲存時間序列與所述標籤對cpu=2
,interface=2
,hdd=2
和fan=2
同時僅消耗1標記值UID( 2
)和4周標記名稱的UID( ,,cpu
和)。interface``hdd``fan
如果您認為UID限制可能會影響您,請首先考慮您要執行的查詢。如果我們檢視web.app.hits
上面的示例,您可能只關心服務的總點選次數,很少需要深入到特定的IP地址。在這種情況下,您可能希望將IP地址儲存為註釋。這樣您仍然可以從低基數中受益,但如果需要,您可以使用外部指令碼搜尋特定IP的結果。
當儲存資料為做高或改變基數源(如多克群),那麼你可以通過設定改變UID寬度tsd.storage.uid.width.metric
,tsd.storage.uid.width.tagk
或tsd.storage.uid.width.tagv
。您只能在建立新的TSDB安裝時執行此操作。
警告
您的情況可能需要增加此值。如果選擇修改此值,則必須從新資料和新UID表開始。使用期望3位元組UID編碼的TSD寫入的任何資料都將與此更改不相容,因此請確保所有TSD都以相同的配置執行,並且在進行此更改之前儲存在OpenTSDB中的所有資料都已匯出到可以通過外部工具操縱的位置。
查詢速度
基數也會大大影響查詢速度,因此請考慮您將經常執行的查詢並優化您的命名架構。OpenTSDB每小時每個時間序列建立一個新行。如果我們有一個主機有一個核心,它發出一個時間序列,每秒寫入資料1天,那將導致24行資料或86,400個數據點。但是,如果我們為該主機提供8個可能的CPU核心,那麼現在我們有192行和691,200個數據點。這看起來不錯,因為我們可以通過發出類似的查詢輕鬆獲得所有核心的CPU使用量的總和或平均值。查詢將遍歷所有192行並將資料聚合到單個時間序列中。sys.cpu.userhost=webserver01,cpu=0``start=1d-ago&m=avg:sys.cpu.user{host=webserver01}
但是,如果我們有20,000個主機,每個主機有8個核心呢?現在,由於主機值的高基數,我們每天將有380萬行和17.28億個資料點。對主機上平均核心使用情況的查詢webserver01
速度較慢,因為它必須從380萬行中挑出192行。(但是對於OpenTSDB 2.2,您可以使用顯式標記功能進行指定cpu=*
,模糊過濾器將啟動以幫助更快地跳過這些不必要的行。)
此架構的好處是您的資料具有非常深的粒度,例如,基於每個核心儲存使用量指標。您還可以輕鬆地建立查詢以獲得所有主機的所有核心的平均使用率:start=1d-ago&m=avg:sys.cpu.user
。但是,針對該特定指標的查詢將花費更長時間,因為需要篩選更多行。這在所有資料庫中都很常見,並不僅僅是OpenTSDB的問題。
以下是處理基數的一些常用方法:
預聚合 - 在上面的示例中sys.cpu.user
,您通常關心主機的平均使用情況,而不是每個核心的使用情況。雖然資料收集器可以使用上面的標記模式為每個核心傳送單獨的值,但收集器也可以傳送一個額外的資料點,例如。現在你有一個完全獨立的時間序列,每天只有24行,有20K主機,只有480K行可以篩選。對於每個主機的平均值,查詢響應速度要快得多,並且您仍然可以將每個核心資料分別向下鑽取。sys.cpu.user.avg host=webserver01
轉換為指標 - 如果您真的只關心特定主機的指標而不需要跨主機聚合,該怎麼辦?在這種情況下,您可以將主機名轉換為指標。我們之前的例子成了。針對此模式的查詢速度非常快,因為度量標準每天只有192行。但是,要跨主機聚合,您必須執行多個查詢並在OpenTSDB之外進行聚合。(未來的工作將包括此功能)。sys.cpu.user.websvr01 cpu=0
命名規範
在設計命名模式時,請記住以下建議:
-
與您的命名保持一致以減少重複。始終對度量標準,標記名稱和值使用相同的大小寫。
-
為每個指標使用相同數量和型別的標記。例如,不要儲存和。
my.metric host=foo``my.metric datacenter=lga
-
考慮一下您將要執行的最常見查詢,並針對這些查詢優化架構
-
想一想在查詢時如何向下鑽取
-
不要使用太多標籤,將其保持在相當小的數量,通常最多4或5個標籤(預設情況下,OpenTSDB最多支援8個標籤)。
資料規範(Data Specification)
每次系列資料點都需要以下資料:
-
指標-的時間等系列的通用名稱
sys.cpu.user
,stock.quote
或env.probe.temp
。 -
timestamp - 一個Unix / POSIX紀元時間戳,以秒或毫秒為單位,定義為自1970年1月1日00:00:00 UTC時間以來經過的秒數。目前僅支援正時間戳。
-
value - 要在時間系列的給定時間戳儲存的數值。這可以是整數或浮點值。
-
tag(s) - 由
tagk
(鍵)和tagv
(值)組成的鍵/值對。每個資料點必須至少有一個標記。
時間戳
可以使用秒或毫秒解析度將資料寫入OpenTSDB。時間戳必須是整數且不超過13位數(請參見下面的[注]]。毫秒時間戳必須是1364410924250
最後三位代表毫秒的格式。在提交之前,生成時間戳超過13位(即大於毫秒解析度)的應用程式必須四捨五入到最多13位數,否則將生成錯誤。
具有第二解析度的時間戳儲存在2個位元組上,而毫秒解析度儲存在4個位元組上。因此,如果您不需要毫秒解析度或所有資料點都在1秒邊界上,我們建議您為第二個解析度提交10位數的時間戳,以便你可以節省儲存空間。避免在給定時間序列中混合使用秒和毫秒時間戳也是一個好主意。這樣做會減慢查詢速度,因為跨混合時間戳的迭代比僅記錄一種型別或另一種型別需要更長的時間。OpenTSDB將儲存您提供的任何內容。
注意
當寫入telnet介面時,可以選擇以表格形式寫入時間戳1364410924.250
,其中表示毫秒的三位數位於句點之後。/api/put
通過HTTP 傳送到端點的時間戳必須是整數,並且可能沒有句點。解析度為毫秒的資料目前只能通過/api/query
端點或CLI命令提取。有關詳細資訊,請參閱query / index。
注意
提供毫秒解析度並不一定意味著OpenTSDB在許多時間序列中支援每毫秒1個數據點的寫入速度。雖然單個TSD可能能夠處理每秒幾千次寫入,但如果您嘗試每毫秒儲存一個點,則只能覆蓋幾個時間序列。相反,OpenTSDB旨在提供更高的測量精度,通常應避免以這樣的速度記錄資料,特別是對於長時間執行的系列。
指標和標籤
以下規則適用於指標和標記值:
-
字串區分大小寫,即“Sys.Cpu.User”將與“sys.cpu.user”分開儲存
-
不允許有空格
-
只有允許使用以下字元:
a
到z
,A
到Z
,0
到9
,-
,_
,.
,/
或Unicode字母(按照規範)
度量和標籤的長度不受限制,但您應該儘量保持這些值非常短。
整數值
如果put
解析了命令中的值而沒有小數點(.
),則將其視為有符號整數。整數儲存,無符號,具有可變長度編碼,因此資料點可能只佔用1個位元組的空間或最多8個位元組。這意味著資料點的最小值可以是-9,223,372,036,854,775,808,最大值可以是9,223,372,036,854,775,807(含)。整數不能有逗號或除數字和短劃線以外的任何字元(對於負值)。例如,為了儲存最大值,必須在表單中提供9223372036854775807
。
浮點值
如果put
使用小數點(.
)解析命令中的值,則將其視為浮點值。目前,所有浮點值都儲存在4個位元組,單精度,在2.4及更高版本中支援8位元組雙精度。浮點數以IEEE 754浮點“單一格式”儲存,具有正值和負值支援。不支援Infinity和Not-a-Number值,如果提供給TSD,則會丟擲錯誤。有關詳細資訊,請參閱Wikipedia和Java文件。
注意
由於OpenTSDB僅支援浮點值,因此不適合儲存需要貨幣等精確值的測量。這就是為什麼,當儲存像15.2
資料庫這樣的值時可能會返回15.199999809265137
。
排序
與其他解決方案不同,OpenTSDB允許以您想要的任何順序編寫給定時間序列的資料。這使得將資料寫入TSD具有很大的靈活性,允許從系統中填充當前資料,然後在以後匯入歷史資料。
重複的資料點
在原始寫入的一小時內,在OpenTSDB中寫入資料點通常是冪等的。這意味著您可以42
在時間戳寫入值1356998400
然後寫入42
同時又一次沒有壞事發生。但是,如果在壓縮資料行之後啟用了壓縮以減少儲存消耗並寫入相同的資料點,則在查詢該行時可能會返回異常。如果嘗試使用相同的時間戳寫入兩個不同的值,則在查詢時可能會丟擲重複的資料點異常。這是由於在1,2,4或8位元組和浮點數上編碼整數的差異。如果第一個值是整數而第二個值是浮點,則將始終丟擲重複錯誤。但是,如果兩個值都是浮點數,或者它們都是可以在相同長度上編碼的整數,那麼如果行上沒有發生壓縮,則原始值可能會被覆蓋。
在大多數情況下,如果寫入重複的資料點,通常表明資料來源出現問題,例如程序意外重啟或指令碼中出現錯誤。當您查詢具有一個或多個重複項的行時,OpenTSDB將通過丟擲異常來“安全”失敗,這樣您就可以解決問題。
使用OpenTSDB 2.1,您可以通過將tsd.storage.fix_duplicates
配置值設定為來啟用last-write-wins true
。啟用此標誌後,在查詢時,將返回記錄的最新值,而不是丟擲異常。警告也將寫入日誌檔案,注意到找到了重複項。如果還啟用了壓縮,則原始壓縮的值將被最新值覆蓋。
輸入方式
目前有三種主要方法可以將資料匯入OpenTSDB:Telnet API,HTTP API和從檔案批量匯入。或者,您可以使用提供OpenTSDB支援的工具,或者如果您非常冒險,請使用Java庫。
警告
不要嘗試直接寫入底層儲存系統,例如HBase。只是不要。它會很快變得混亂。
注意
如果tsd.mode
設定為ro
而不是rw
,TSD將不會通過RPC呼叫接受資料點。Telnet樣式呼叫將引發異常,對HTTP端點的呼叫將返回404錯誤。但是,當模式設定為只讀時,仍然可以通過JAVA API進行寫入。
遠端登入
開始使用OpenTSDB的最簡單方法是開啟終端或telnet客戶端,連線到TSD併發出put
命令並點選“回車”。如果您正在編寫程式,只需開啟一個套接字,用新行列印字串命令併發送資料包。telnet命令格式為:
put < metric > < timestamp > < value > < tagk1 = tagv1 [ tagk2 = tagv2 ... tagkN = tagvN ] >
例如:
把 sys 。cpu 。使用者 1356998400 42.5 host = webserver01 cpu = 0
每個put
只能傳送一個數據點。不要忘記換行符,例如\n
在命令結束時。
注意
不建議使用Telnet寫入方法,因為它沒有提供確定哪些資料點由於格式化或儲存錯誤而無法寫入的方法。而是使用HTTP API。
Http API
從版本2.0開始,資料可以通過HTTP以“Serializer”外掛支援的格式傳送。可以在單個HTTP POST請求中傳送多個不相關的資料點以節省頻寬。有關詳細資訊,請參閱../api_http/put。
批量匯入
如果要從其他系統匯入資料,或者需要回填歷史資料,則可以使用import
CLI實用程式。有關詳細資訊,請參閱cli / import。