本篇要來講解時間序列資料的壓縮。
Prometheus 是將所有時間序列資料,按樣本時間區段(預設兩小時為一區段),全部壓縮成一個檔案(chunk)儲存。
於是壓縮的對象能提供的資訊就局限在一個 chunk。
舉例來說,我們無法在壓縮算法中「對每個樣本值都記錄它跟一天前的差」。
但我們可以「對於一個時間序列標籤,記錄它跟上一同名時間序列標籤的異同」。
Prometheus 所收集的時間序列,資料包含指標名稱、標籤集、和樣本集。
指標名稱和標籤集做為鍵值,代表一個時間序列,所以是不變的。佔用的空間不會隨時間增加。而樣本集則是隨時間增加的,所以是主要壓縮的對象。
Prometheus 用 gorilla 算法壓縮所有的樣本集。
假設樣本的時間戳近乎是等差整數數列,而樣本值近乎是等差浮點數列。
gorilla 算法對這兩個數列分別做壓縮。
先存入前兩個時間戳,之後每個新的時間戳,計算該項的二階差值。
然後以變動的位元數存入這個差值。
如果差值是 0,則存入 0。否則依差值的二進位位元數,存入位元數和差值。
這樣如果時間戳是等差的,就只需要存入跟數列長度一樣多的 0。
先存入一個樣本值,之後每個新的樣本值,計算 float64 二進位表示法與前項的 xor 值。
然後以變動的位元數存入這個差值。
如果 xor 值是 0,則存入 0。否則依 xor 值的後綴 0 數,存入有效位數和差值。
這樣如果樣本值是不變的,就只需要存入跟數列長度一樣多的 0。
可以看出,如果時間戳序列是亂序(Out of Order)或不等差,gorilla 算法的壓縮效果就會變差。
所以 Prometheus 預設不充許時間戳亂序,遇到倒序時就會直接丟棄樣本。