Grafana 系列文章(十一):Loki 中的標(biāo)簽如何使日志查詢更快更方便

???URL: https://grafana.com/blog/2020/04/21/how-labels-in-loki-can-make-log-queries-faster-and-easier/

??Description:

關(guān)于標(biāo)簽在 Loki 中如何真正發(fā)揮作用开仰,你需要知道的一切剃根。它可能與你想象的不同

在我們從事 Loki 項(xiàng)目的第一年的大部分時(shí)間里,問題和反饋似乎都來自熟悉 Prometheus 的人秉宿。畢竟奶稠,Loki 就像 Prometheus--不過是針對(duì)日志的因妙!"钠导。

但是最近略水,我們看到越來越多的人嘗試使用 Loki,他們沒有 Prometheus 的經(jīng)驗(yàn)赤赊,而且許多人來自于具有不同策略的系統(tǒng)闯狱,以處理日志。這就帶來了很多關(guān)于 Loki 一個(gè)非常重要的概念的問題砍鸠,即使是 Prometheus 專家也想了解更多:標(biāo)簽 (Labels)!

這篇文章將涵蓋很多內(nèi)容扩氢,以幫助每一個(gè)剛接觸 Loki 的人和想要復(fù)習(xí)的人耕驰。我們將探討以下主題爷辱。

什么是標(biāo)簽 (Label)?

標(biāo)簽是鍵值對(duì),可以被定義為任何東西!我們喜歡把它們稱為元數(shù)據(jù) (metadata)饭弓,用來描述日志流双饥。如果你熟悉 Prometheus,你會(huì)習(xí)慣性地看到一些標(biāo)簽弟断,比如jobinstance咏花,我將在接下來的例子中使用這些。

我們用 Loki 提供的刮削 (scrape) 配置也定義了這些標(biāo)簽阀趴。如果你正在使用 Prometheus昏翰,在 Loki 和 Prometheus 之間擁有一致的標(biāo)簽是 Loki 的超級(jí)優(yōu)勢(shì)之一,使你 非常容易將你的應(yīng)用程序指標(biāo) (Metrics) 與你的日志 (Logs) 數(shù)據(jù)聯(lián)系起來刘急。

Loki 如何使用標(biāo)簽

Loki 中的標(biāo)簽執(zhí)行一個(gè)非常重要的任務(wù)棚菊。它們定義了一個(gè)流。更確切地說叔汁,每個(gè)標(biāo)簽的鍵和值的組合都定義了流统求。如果只有一個(gè)標(biāo)簽值發(fā)生變化,就會(huì)產(chǎn)生一個(gè)新的流据块。

如果你熟悉 Prometheus码邻,那里使用的術(shù)語是系列 (series);但是另假,Prometheus 有一個(gè)額外的維度:度量名稱 (metric name)像屋。Loki 簡(jiǎn)化了這一點(diǎn),沒有度量名稱边篮,只有標(biāo)簽开睡,我們決定使用流而不是系列。

讓我們舉個(gè)例子:

scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      __path__: /var/log/syslog

這個(gè)配置將跟蹤一個(gè)文件并分配一個(gè)標(biāo)簽:job=syslog苟耻。你可以這樣查詢:

{job=”syslog”}

這將在 Loki 創(chuàng)建一個(gè)流篇恒。

現(xiàn)在讓我們把這個(gè)例子擴(kuò)大一點(diǎn):

scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      __path__: /var/log/syslog
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      __path__: /var/log/apache.log

現(xiàn)在我們正在跟蹤兩個(gè)文件。每個(gè)文件只得到一個(gè)標(biāo)簽和一個(gè)值凶杖,所以 Loki 現(xiàn)在將存儲(chǔ)兩個(gè)數(shù)據(jù)流胁艰。

我們可以用幾種方式查詢這些流:

{job=”apache”} <- 顯示標(biāo)簽 job 是 apache 的日志
{job=”syslog”} <- 顯示標(biāo)簽 job 是 syslog 的日志
{job=~”apache|syslog”} <- 顯示標(biāo)簽 job 是 apache **或** syslog 的日志

在最后一個(gè)例子中,我們使用了一個(gè) regex 標(biāo)簽匹配器來記錄使用標(biāo)簽 job 的兩個(gè)值的流≈球穑現(xiàn)在考慮一下如何也使用一個(gè)額外的標(biāo)簽:

scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      env: dev
      __path__: /var/log/syslog
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      env: dev
      __path__: /var/log/apache.log

現(xiàn)在我們可以這樣做腾么,而不是使用正則表達(dá)式:

{env=”dev”} <- 返回 env=dev 的所有日志,本例中包括兩個(gè)日志流

希望你現(xiàn)在開始看到標(biāo)簽的力量杈湾。通過使用一個(gè)標(biāo)簽解虱,你可以查詢?cè)S多數(shù)據(jù)流。通過結(jié)合幾個(gè)不同的標(biāo)簽漆撞,你可以創(chuàng)建非常靈活的日志查詢殴泰。

標(biāo)簽是 Loki 的日志數(shù)據(jù)的索引于宙。它們被用來尋找壓縮的日志內(nèi)容,這些內(nèi)容以塊形式單獨(dú)存儲(chǔ)悍汛。每個(gè)獨(dú)特的標(biāo)簽和值的組合都定義了一個(gè)流捞魁,一個(gè)流的日志被分批壓縮,并作為塊存儲(chǔ)离咐。

為了使 Loki 的效率和成本效益谱俭,我們必須負(fù)責(zé)任地使用標(biāo)簽。下一節(jié)將更詳細(xì)地探討這個(gè)問題宵蛀。

基數(shù) (Cardinality)

前面的兩個(gè)例子使用的是靜態(tài)定義的標(biāo)簽昆著,只有一個(gè)值;但是术陶,有一些方法可以動(dòng)態(tài)地定義標(biāo)簽宣吱。讓我們用 Apache 的日志和你可以用來解析這樣的日志行的大量的重合詞來看看。

11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
- job_name: system
   pipeline_stages:
      - regex:
        expression: "^(?P<ip>\\S+) (?P<identd>\\S+) (?P<user>\\S+) \\[(?P<timestamp>[\\w:/]+\\s[+\\-]\\d{4})\\] \"(?P<action>\\S+)\\s?(?P<path>\\S+)?\\s?(?P<protocol>\\S+)?\" (?P<status_code>\\d{3}|-) (?P<size>\\d+|-)\\s?\"?(?P<referer>[^\"]*)\"?\\s?\"?(?P<useragent>[^\"]*)?\"?$"
    - labels:
        action:
        status_code:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      env: dev
      __path__: /var/log/apache.log

這個(gè)詞組匹配日志行的每一個(gè)組件瞳别,并將每個(gè)組件的值提取到一個(gè)捕獲組中征候。在管道代碼中,這些數(shù)據(jù)被放置在一個(gè)臨時(shí)數(shù)據(jù)結(jié)構(gòu)中祟敛,允許在處理該日志行時(shí)將其用于多種用途(此時(shí)疤坝,這些臨時(shí)數(shù)據(jù)被丟棄)。關(guān)于這一點(diǎn)的更多細(xì)節(jié)可以在 這里 找到馆铁。

從該重合碼中沛慢,我們將使用兩個(gè)捕獲組掂铐,根據(jù)日志行本身的內(nèi)容動(dòng)態(tài)地設(shè)置兩個(gè)標(biāo)簽忽舟。

action(例如虾标,action="GET",action="POST") status_code(例如辣垒, status_code="200"望侈, status_code="400")。

現(xiàn)在讓我們看幾個(gè)例子行:

11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] "POST /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] "GET /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] "POST /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

在 Loki 中勋桶,將創(chuàng)建以下數(shù)據(jù)流:

{job=”apache”,env=”dev”,action=”GET”,status_code=”200”} 11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
{job=”apache”,env=”dev”,action=”POST”,status_code=”200”} 11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] "POST /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
{job=”apache”,env=”dev”,action=”GET”,status_code=”400”} 11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] "GET /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
{job=”apache”,env=”dev”,action=”POST”,status_code=”400”} 11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] "POST /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

這四條日志行將成為四個(gè)獨(dú)立的流脱衙,并開始填充四個(gè)獨(dú)立的塊。

任何符合這些標(biāo)簽/值組合的額外日志行將被添加到現(xiàn)有的流中例驹。如果有另一個(gè)獨(dú)特的標(biāo)簽組合進(jìn)來(例如 status_code="500")捐韩,就會(huì)創(chuàng)建另一個(gè)新的流。

現(xiàn)在想象一下鹃锈,如果你為 ip 設(shè)置一個(gè)標(biāo)簽荤胁。不僅每個(gè)來自用戶的請(qǐng)求都成為一個(gè)獨(dú)特的流。每個(gè)來自同一用戶的具有不同動(dòng)作或狀態(tài)代碼的請(qǐng)求都將得到它自己的流屎债。

做一些簡(jiǎn)單的計(jì)算仅政,如果有四個(gè)常見的動(dòng)作(GET, PUT, POST, DELETE)和四個(gè)常見的狀態(tài)代碼(雖然可能不止四個(gè)9赣汀),這將是 16 個(gè)流和 16 個(gè)獨(dú)立的塊∫丫桑現(xiàn)在,如果我們用一個(gè)標(biāo)簽來表示 ip召娜,就把這個(gè)數(shù)字乘以每個(gè)用戶运褪。你可以很快有幾千或幾萬個(gè)流。

這會(huì)導(dǎo)致很高的 cardinality玖瘸。會(huì)殺死 Loki秸讹。

當(dāng)我們談?wù)?cardinality 時(shí),我們指的是標(biāo)簽和值的組合以及它們創(chuàng)造的流的數(shù)量雅倒。高 cardinality 是指使用具有大范圍可能值的標(biāo)簽璃诀,如 ip,或結(jié)合許多標(biāo)簽蔑匣,即使它們有一個(gè)小而有限的值集劣欢,如使用 status_code 和 action。

高 cardinality 導(dǎo)致 Loki 建立一個(gè)巨大的索引(讀作:????????)裁良,并將成千上萬的小塊沖到對(duì)象存儲(chǔ)中(讀作:慢)凿将。目前,Loki 在這種配置下表現(xiàn)很差价脾,運(yùn)行和使用起來將是最不劃算和最沒有樂趣的牧抵。

使用并行化 (parallelization) 的最佳 Loki 性能

現(xiàn)在你可能會(huì)問:如果使用大量的標(biāo)簽或有大量數(shù)值的標(biāo)簽是不好的,那么我應(yīng)該如何查詢我的日志呢侨把?如果沒有一個(gè)數(shù)據(jù)是有索引的犀变,那查詢豈不是很慢?

當(dāng)我們看到使用 Loki 的人習(xí)慣于使用其他索引重復(fù)的解決方案時(shí)秋柄,他們似乎覺得有義務(wù)定義大量的標(biāo)簽获枝,以便有效地查詢他們的日志。畢竟骇笔,許多其他的日志解決方案都是關(guān)于索引的映琳,這也是常見的思維方式。

在使用 Loki 時(shí)蜘拉,你可能需要忘記你所知道的東西萨西,看看如何用并行化的方式來解決這個(gè)問題。Loki 的超能力是將查詢分解成小塊旭旭,并將其并行調(diào)度谎脯,這樣你就可以在小時(shí)間內(nèi)查詢大量的日志數(shù)據(jù)。

這種粗暴的方法聽起來可能并不理想持寄,但讓我解釋一下為什么會(huì)這樣源梭。

大型索引是復(fù)雜而昂貴的娱俺。通常情況下,你的日志數(shù)據(jù)的全文索引與日志數(shù)據(jù)本身的大小相同或更大废麻。為了查詢你的日志數(shù)據(jù)荠卷,你需要加載這個(gè)索引,而且為了性能烛愧,它可能應(yīng)該在內(nèi)存中油宜。這是很難擴(kuò)展的,當(dāng)你攝入更多的日志時(shí)怜姿,你的索引會(huì)很快變大慎冤。

現(xiàn)在讓我們來談?wù)?Loki,它的索引通常比你攝入的日志量小一個(gè)數(shù)量級(jí)沧卢。因此蚁堤,如果你能很好地保持你的數(shù)據(jù)流和數(shù)據(jù)流的流失,那么與攝取的日志相比但狭,索引的增長(zhǎng)非常緩慢披诗。

Loki 將有效地保持你的靜態(tài)成本盡可能低(索引大小和內(nèi)存要求以及靜態(tài)日志存儲(chǔ)),并使查詢性能成為你可以在運(yùn)行時(shí)控制的水平擴(kuò)展立磁。

為了了解這一點(diǎn)藤巢,讓我們回過頭來看看我們查詢特定 IP 地址的訪問日志數(shù)據(jù)的例子。我們不想用一個(gè)標(biāo)簽來存儲(chǔ) IP息罗。相反掂咒,我們使用一個(gè)過濾器表達(dá)式來查詢它。

{job=”apache”} |= “11.11.11.11”

在幕后迈喉,Loki 會(huì)將該查詢分解成更小的片段(分片)绍刮,并為標(biāo)簽所匹配的流打開每個(gè)分片,開始尋找這個(gè) IP 地址挨摸。

這些分片的大小和并行化的數(shù)量是可配置的孩革,并基于你提供的資源。如果你愿意得运,你可以把分片的間隔配置到 5m膝蜈,部署 20 個(gè)查詢器,在幾秒鐘內(nèi)處理幾十億字節(jié)的日志熔掺”ゲ或者你可以瘋狂地配置 200 個(gè)查詢器,處理 TB 級(jí)的日志置逻。

這種較小的索引和平行的暴力查詢與較大/較快的全文索引之間的權(quán)衡推沸,使得 Loki 能夠比其他系統(tǒng)節(jié)省成本。操作大型索引的成本和復(fù)雜性很高,而且通常是固定的--無論你是否查詢它鬓催,你都要一天 24 小時(shí)為它付費(fèi)肺素。

這種設(shè)計(jì)的好處是,你可以決定你想擁有多少查詢能力宇驾,而且你可以按需改變倍靡。查詢性能成為你想在上面花多少錢的一個(gè)函數(shù)。同時(shí)课舍,數(shù)據(jù)被大量壓縮并存儲(chǔ)在低成本的對(duì)象存儲(chǔ)中塌西,如 S3 和 GCS。這使固定的運(yùn)營成本降到最低布卡,同時(shí)還能實(shí)現(xiàn)令人難以置信的快速查詢能力

最佳實(shí)踐

這里有一些 Loki 目前最有效的標(biāo)簽做法雨让,可以給你帶來 Loki 的最佳體驗(yàn)雇盖。

1. 推薦靜態(tài)標(biāo)簽

像主機(jī)忿等、應(yīng)用程序和環(huán)境這些東西是很好的標(biāo)簽。它們對(duì)于一個(gè)給定的系統(tǒng)/應(yīng)用程序來說是固定的崔挖,并且有限定的值贸街。使用靜態(tài)標(biāo)簽可以使你更容易在邏輯上查詢你的日志(例如,給我看一個(gè)給定的應(yīng)用程序和特定環(huán)境的所有日志狸相,或者給我看一個(gè)特定主機(jī)上的所有應(yīng)用程序的所有日志)薛匪。

2. 謹(jǐn)慎使用動(dòng)態(tài)標(biāo)簽

太多的標(biāo)簽值組合會(huì)導(dǎo)致太多的數(shù)據(jù)流。在 Loki 中脓鹃,這樣做的懲罰是一個(gè)大索引和存儲(chǔ)中的小塊逸尖,這反過來又會(huì)降低性能。

為了避免這些問題瘸右,在你知道你需要它之前娇跟,不要為某樣?xùn)|西添加標(biāo)簽。使用過濾表達(dá)式 ( |= "text", |~ "regex", ...) 并對(duì)這些日志進(jìn)行暴力處理太颤。這很有效--而且速度很快苞俘。

從早期開始,我們就使用 promtail 管道為level動(dòng)態(tài)地設(shè)置了一個(gè)標(biāo)簽龄章。這對(duì)我們來說似乎很直觀吃谣,因?yàn)槲覀兘?jīng)常想只顯示level="error"的日志;然而做裙,我們現(xiàn)在正在重新評(píng)估這一點(diǎn)岗憋,因?yàn)閷懸粋€(gè)查詢。{app="loki"} |= "level=error"對(duì)我們的許多應(yīng)用來說锚贱,證明與{app="loki",level="error"}一樣快澜驮。

這似乎令人驚訝,但如果應(yīng)用程序有中等至低容量惋鸥,該標(biāo)簽導(dǎo)致一個(gè)應(yīng)用程序的日志被分成多達(dá)五個(gè)流杂穷,這意味著 5 倍的塊被存儲(chǔ)悍缠。而加載塊有一個(gè)與之相關(guān)的開銷。想象一下耐量,如果這個(gè)查詢是{app="loki",level!="debug"}飞蚓。這將不得不比{app="loki"} != "level=debug"}加載多的多數(shù)據(jù)塊。

上面廊蜒,我們提到在你需要它們之前不要添加標(biāo)簽趴拧,那么你什么時(shí)候會(huì)需要標(biāo)簽?zāi)兀吭偻乱稽c(diǎn)是關(guān)于 chunk_target_size 的部分山叮。如果你把這個(gè)設(shè)置為 1MB(這是合理的)著榴,這將試圖以 1MB 的壓縮大小來切割塊,這大約是 5MB 左右的未壓縮的日志(可能多達(dá) 10MB屁倔,取決于壓縮)脑又。如果你的日志有足夠的容量在比max_chunk_age更短的時(shí)間內(nèi)寫入 5MB,或者在這個(gè)時(shí)間范圍內(nèi)有多的多的塊锐借,你可能要考慮用動(dòng)態(tài)標(biāo)簽把它分成獨(dú)立的流问麸。

你想避免的是將一個(gè)日志文件分割成流,這將導(dǎo)致塊被刷新钞翔,因?yàn)榱魇强臻e的或在滿之前達(dá)到最大年齡严卖。從 Loki 1.4.0 開始,有一個(gè)指標(biāo)可以幫助你了解為什么要刷新數(shù)據(jù)塊sum by (reason) (rate(loki_ingester_chunks_flushed_total{cluster="dev"}[1m]))布轿。

每個(gè)塊在刷新時(shí)都是滿的哮笆,這并不關(guān)鍵,但它將改善許多方面的操作汰扭。因此稠肘,我們目前的指導(dǎo)思想是盡可能避免動(dòng)態(tài)標(biāo)簽,而傾向于過濾器表達(dá)式东且。例如启具,不要添加 level 的動(dòng)態(tài)標(biāo)簽,而用|= "level=debug"代替珊泳。

3. 標(biāo)簽值必須始終是有界的

如果你要?jiǎng)討B(tài)地設(shè)置標(biāo)簽鲁冯,千萬不要使用可以有無界值或無限值的標(biāo)簽。這總是會(huì)給 Loki 帶來大問題色查。

盡量將值限制在盡可能小的范圍內(nèi)薯演。我們對(duì) Loki 能處理的數(shù)值沒有完美的指導(dǎo),但對(duì)于動(dòng)態(tài)標(biāo)簽來說秧了,要考慮個(gè)位數(shù)跨扮,或者10 個(gè)數(shù)值。這對(duì)靜態(tài)標(biāo)簽來說就不那么重要了。例如衡创,如果你的環(huán)境中有 1,000 臺(tái)主機(jī)帝嗡,那么有 1,000 個(gè)值的主機(jī)標(biāo)簽就會(huì)很好。

4. 注意客戶端的動(dòng)態(tài)標(biāo)簽

Loki 有幾個(gè)客戶端選項(xiàng)璃氢。Promtail(也支持 systemd 日志攝取和基于 TCP 的系統(tǒng)日志攝扔寸琛),FluentD一也,Fluent Bit巢寡,一個(gè) Docker 插件,以及更多椰苟!

每一個(gè)都有方法來配置用什么標(biāo)簽來創(chuàng)建日志流抑月。但要注意可能會(huì)用哪些動(dòng)態(tài)標(biāo)簽。使用 Loki 系列 API 來了解你的日志流是什么樣子的舆蝴,看看是否有辦法減少流和 cardinality谦絮。系列 API 的細(xì)節(jié)可以在 這里 找到,或者你可以使用 logcli 來查詢 Loki 的系列信息须误。

5. 配置緩存

Loki 可以對(duì)數(shù)據(jù)進(jìn)行多層次的緩存挨稿,這可以極大地提高性能仇轻。這方面的細(xì)節(jié)將在今后的文章中介紹京痢。

6. 每條流的日志必須按時(shí)間順序遞增(新版本默認(rèn)接受無序日志)

??Notes:

新版本默認(rèn)接受無序日志

許多人在使用 Loki 時(shí)遇到的一個(gè)問題是,他們的客戶端收到了錯(cuò)誤的日志條目篷店。這是因?yàn)?Loki 內(nèi)部有一條硬性規(guī)定祭椰。

  • 對(duì)于任何單一的日志流,日志必須總是以遞增的時(shí)間順序發(fā)送疲陕。如果收到的日志的時(shí)間戳比該流收到的最新日志的時(shí)間戳大方淤,該日志將被放棄。

從這個(gè)聲明中蹄殃,有幾件事需要剖析携茂。首先,這個(gè)限制是針對(duì)每個(gè)流的诅岩。讓我們看一個(gè)例子:

{job=”syslog”} 00:00:00 i’m a syslog!
{job=”syslog”} 00:00:01 i’m a syslog!

如果 Loki 收到這兩行是針對(duì)同一流的讳苦,那么一切都會(huì)好起來。但這種情況呢吩谦?

{job=”syslog”} 00:00:00 i’m a syslog!
{job=”syslog”} 00:00:02 i’m a syslog!
{job=”syslog”} 00:00:01 i’m a syslog!  <- 拒絕不符合順序的鸳谜!

嗯,額式廷。..... 但我們能做些什么呢咐扭?如果這是因?yàn)檫@些日志的來源是不同的系統(tǒng)呢?我們可以用一個(gè)額外的標(biāo)簽來解決這個(gè)問題,這個(gè)標(biāo)簽在每個(gè)系統(tǒng)中是唯一的蝗肪。

{job=”syslog”, instance=”host1”} 00:00:00 i’m a syslog!
{job=”syslog”, instance=”host1”} 00:00:02 i’m a syslog!
{job=”syslog”, instance=”host2”} 00:00:01 i’m a syslog!  <- 被接受袜爪,這是一個(gè)新的流!
{job=”syslog”, instance=”host1”} 00:00:03 i’m a syslog!  <- 被接受薛闪,流 1 仍是有序的
{job=”syslog”, instance=”host2”} 00:00:02 i’m a syslog!  <- 被接受饿敲,流 2 仍是有序的

但是,如果應(yīng)用程序本身產(chǎn)生的日志是不正常的呢逛绵?嗯怀各,這恐怕是個(gè)問題。如果你用類似 promtail 管道階段的東西從日志行中提取時(shí)間戳术浪,你反而可以不這樣做瓢对,讓 Promtail 給日志行分配一個(gè)時(shí)間戳∫人眨或者你可以希望在應(yīng)用程序本身中修復(fù)它硕蛹。

但是我想讓 Loki 來解決這個(gè)問題!為什么你不能為我緩沖數(shù)據(jù)流并重新排序硕并?說實(shí)話法焰,因?yàn)檫@將給 Loki 增加大量的內(nèi)存開銷和復(fù)雜性,而正如這篇文章中的一個(gè)共同點(diǎn)倔毙,我們希望 Loki 簡(jiǎn)單而經(jīng)濟(jì)埃仪。理想情況下,我們希望改進(jìn)我們的客戶端來做一些基本的緩沖和排序陕赃,因?yàn)檫@似乎是解決這個(gè)問題的一個(gè)更好的地方卵蛉。

另外值得注意的是,Loki 推送 API 的批處理性質(zhì)可能會(huì)導(dǎo)致收到一些順序錯(cuò)誤的情況么库,這其實(shí)是誤報(bào)傻丝。(也許一個(gè)批處理部分成功了,并出現(xiàn)了诉儒;或者任何以前成功的東西都會(huì)返回一個(gè)失序的條目葡缰;或者任何新的東西都會(huì)被接受)。

7. 使用 chunk_target_size

這是在 2020 年早些時(shí)候我們 發(fā)布 Loki v1.3.0 時(shí)添加的忱反,我們已經(jīng)用它實(shí)驗(yàn)了幾個(gè)月》菏停現(xiàn)在我們?cè)谒械沫h(huán)境中都有chunk_target_size: 1536000。這指示 Loki 嘗試將所有的 chunks 填充到 1.5MB 的目標(biāo)壓縮大小缭受。這些較大的塊對(duì) Loki 來說是更有效的處理胁澳。

其他幾個(gè)配置變量會(huì)影響到一個(gè)塊的大小。Loki 默認(rèn)的 max_chunk_age 為 1 小時(shí)米者,chunk_idle_period 為 30 分鐘韭畸,以限制所使用的內(nèi)存量宇智,以及在進(jìn)程崩潰時(shí)丟失日志的風(fēng)險(xiǎn)。

根據(jù)使用的壓縮方式(我們一直使用 snappy胰丁,它的可壓縮性較低随橘,但性能較快),你需要 5-10 倍或 7.5-10MB 的原始日志數(shù)據(jù)來填充 1.5MB 的塊锦庸。記住机蔗,一個(gè)塊是每一個(gè)流,你把你的日志文件分成的流越多甘萧,在內(nèi)存中的塊就越多萝嘁,在它們被填滿之前,它們被擊中上述的超時(shí)的可能性就越大扬卷。

很多小的牙言、未填充的塊目前是 Loki 的頑石。我們一直在努力改善這一點(diǎn)怪得,并可能考慮在某些情況下使用壓縮器來改善這一點(diǎn)咱枉。但是,一般來說徒恋,指導(dǎo)原則應(yīng)該保持不變:盡力填充塊蚕断。

如果你有一個(gè)應(yīng)用程序,它的記錄速度足以迅速填滿這些塊(遠(yuǎn)遠(yuǎn)小于max_chunk_age)入挣,那么使用動(dòng)態(tài)標(biāo)簽將其分解成獨(dú)立的數(shù)據(jù)流就變得更加合理亿乳。

總結(jié)

我最后再強(qiáng)調(diào)一次這個(gè)死馬當(dāng)活馬醫(yī)的主意吧!

為了性能而使用并行化财岔,而不是標(biāo)簽和索引

對(duì)標(biāo)簽要嚴(yán)格要求风皿。靜態(tài)標(biāo)簽通常是好的河爹,但動(dòng)態(tài)標(biāo)簽應(yīng)該少用匠璧。(如果你的日志流以每分鐘 5-10MB 的速度寫入,那么考慮一個(gè)動(dòng)態(tài)標(biāo)簽如何將其分成兩到三個(gè)流咸这,這可以提高查詢性能夷恍。如果你的量比較少,堅(jiān)持使用 過濾表達(dá)式媳维。

索引不一定是 Loki 的性能之路酿雪!首先要優(yōu)先考慮并行化和 LogQL 查詢過濾。

請(qǐng)記字豆簟:與其他日志存儲(chǔ)解決方案相比指黎,Loki 需要一種不同的思維方式。我們正在對(duì) Loki 進(jìn)行優(yōu)化州丹,以獲得更少的數(shù)據(jù)流和更小的索引醋安,這有助于填充更大的塊杂彭,更容易通過并行化進(jìn)行查詢。

我們正在積極改進(jìn) Loki吓揪,并研究如何做到這一點(diǎn)亲怠。請(qǐng)務(wù)必繼續(xù)關(guān)注 Loki 故事的展開,我們都在琢磨如何將這個(gè)真正有效的工具發(fā)揮到極致柠辞!

Grafana 系列文章

Grafana 系列文章

三人行, 必有我?guī)? 知識(shí)共享, 天下為公. 本文由東風(fēng)微鳴技術(shù)博客 EWhisper.cn 編寫.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末团秽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子叭首,更是在濱河造成了極大的恐慌习勤,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焙格,死亡現(xiàn)場(chǎng)離奇詭異姻报,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)间螟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門吴旋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人厢破,你說我怎么就攤上這事荣瑟。” “怎么了摩泪?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵笆焰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我见坑,道長(zhǎng)嚷掠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任荞驴,我火速辦了婚禮不皆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熊楼。我一直安慰自己霹娄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布鲫骗。 她就那樣靜靜地躺著犬耻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪执泰。 梳的紋絲不亂的頭發(fā)上枕磁,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音术吝,去河邊找鬼计济。 笑死晴楔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的峭咒。 我是一名探鬼主播税弃,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼凑队!你這毒婦竟也來了则果?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤漩氨,失蹤者是張志新(化名)和其女友劉穎西壮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叫惊,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡款青,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了霍狰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抡草。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蔗坯,靈堂內(nèi)的尸體忽然破棺而出康震,到底是詐尸還是另有隱情,我是刑警寧澤宾濒,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布腿短,位于F島的核電站,受9級(jí)特大地震影響绘梦,放射性物質(zhì)發(fā)生泄漏橘忱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一卸奉、第九天 我趴在偏房一處隱蔽的房頂上張望钝诚。 院中可真熱鬧,春花似錦择卦、人聲如沸敲长。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至泽铛,卻和暖如春尚辑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盔腔。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工杠茬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留月褥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓瓢喉,卻偏偏與公主長(zhǎng)得像宁赤,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子栓票,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容