概括下本文的內容:
我們可以使用 Logstash 的持久化隊列技術盡量保證數據可靠傳輸至 output完箩;
適用場景:傳輸可靠性要求稍低的場景下(和 Kafka 類比),替換架構中的 Kafka 或者加固 Logstash 本身的可靠性排吴,因為即使 queue.checkpoint.writes:1,也有可能因為磁盤故障(檢查點文件 和 queue 文件同時損壞)丟至多 1 條數據懦鼠,核心的問題是在于沒有多副本和選舉相關的實現(xiàn)钻哩;
Deliver 策略:at-least-once;
默認情況下肛冶,Logstash在 pipeline stages(inputs → pipeline workers)之間使用內存有界隊列來緩沖事件街氢。 這些內存中隊列的大小是固定的,不可配置淑趾。 如果 Logstash 遇到臨時機器故障阳仔,則內存中隊列的內容將丟失。 臨時機器故障是指 Logstash 或其主機異常終止但能夠重新啟動的情況扣泊。
為了防止異常終止期間的數據丟失近范,Logstash 具有持久性隊列功能,將消息隊列存儲在磁盤上延蟹。 持久隊列在 Logstash 中提供數據的持久性评矩。
持久隊列對于需要大型緩沖區(qū)的 Logstash 部署也很有用。 換言之阱飘,可以啟用持久性隊列來緩存磁盤上的事件而無需使用較重的組件(如 Redis斥杜,RabbitMQ 或 Apache Kafka)來實現(xiàn)緩沖的發(fā)布訂戶模型虱颗。
總而言之,啟用持久隊列的好處如下:
- 處理突發(fā)事件蔗喂,而不需要像 Redis 或 Apache Kafka 這樣的外部緩沖機制忘渔;
- 在正常關機期間以及 Logstash 異常終止時,提供 at-least-once 傳輸保證缰儿,防止消息丟失畦粮。 如果 Logstash 在事件傳遞時(我理解是事務執(zhí)行過程中,in-flight)重新啟動乖阵,Logstash 將嘗試傳遞存儲在持久性隊列中的消息宣赔,直到傳送成功至少一次。
持久隊列的限制
以下是持久隊列功能未解決的問題:
- 不使用 request-response 協(xié)議的 input 插件無法避免數據丟失瞪浸。 例如:tcp儒将,udp,zeromq push + pull和許多其他輸入沒有機制來確認 receipt 的發(fā)送方对蒲。 具有確認功能的插件(如 beats 和 http)受到此隊列的良好保護钩蚊。
- 它不會處理永久性的機器故障,如磁盤損壞蹈矮,磁盤故障和機器丟失两疚,持續(xù)到磁盤的數據不會被復制。
持久隊列如何工作
隊列位于同一進程的 input 和 filter 階段之間:
input → queue → filter + output
當 input 有事件準備好處理時含滴,它將事件寫入隊列。當寫入隊列成功時丐巫, input 可以向其數據源發(fā)送 ack谈况。
Logstash 只會在 filter 和 output 完成事件處理后,確認事件已完成递胧。隊列保留 pipeline 已處理的事件的記錄碑韵。事件被記錄為已處理(acked),當且僅當事件已由 Logstash pipeline 完全處理缎脾。
Ack 這意味著事件已由所有配置的 filter 和 output 處理祝闻。例如,如果只有一個到 Elasticsearch的輸出遗菠,當 Elasticsearch output 已成功將此事件發(fā)送到 Elasticsearch 時联喘,事件將被 ack。
在正常關機(Kill 或 SIGTERM)期間辙纬,Logstash 將停止從隊列中讀取豁遭,并完成由 filter 和 output 處理的 in-flight 事件。重新啟動后贺拣,Logstash 將恢復處理持久性隊列中的事件以及從 input 接受新事件蓖谢。
如果 Logstash 異常終止捂蕴,任何 in-flight 事件將不會被 ack,并且當 Logstash 重新啟動時將被 filter 和 output 重新處理闪幽。 Logstash 分批處理事件啥辨,因此對于任何給定的批處理,有可能已經成功完成了該批次盯腌,但是在發(fā)生異常終止時不能被記錄為已確認溉知,所以可以解釋為什么會有重復發(fā)送。
如何配置持久化隊列
要配置持久性隊列腊嗡,可以在Logstash設置文件中指定以下選項:
queue.type
:指定持久化以啟用持久性隊列着倾。默認情況下,持久隊列被禁用(默認:queue.type:memory)燕少。
path.queue
:數據文件將被存儲的目錄路徑卡者。默認情況下,文件存儲在path.data/queue中客们。
queue.page_capacity
:隊列頁面的最大大谐缇觥(以字節(jié)為單位)。隊列數據由僅附加文件稱為“頁面”組成底挫。默認大小為250MB恒傻。更改此值不太可能具有性能優(yōu)勢。
queue.max_events
:隊列中允許的最大事件數建邓。默認值為0(無限制)盈厘。該值在內部用于Logstash測試。
queue.max_bytes
:隊列的總容量官边,以字節(jié)為單位沸手。默認值為1024MB(1GB)。確保磁盤驅動器的容量大于此處指定的值注簿。
如果同時指定了queue.max_events
和queue.max_bytes
契吉,則Logstash將使用首先達到的條件。诡渴。
還可以指定控制檢查點文件何時更新的選項(queue.checkpoint.acks
捐晶,queue.checkpoint.writes
)。
示例配置:
queue.type:persisted
queue.max_bytes:4gb
處理 Back Pressure
當隊列已滿時妄辩,Logstash 會對 input 端施加壓力惑灵,以阻止流入 Logstash 的數據。這種機制有助于 Logstash 在 input 階段控制數據流量眼耀,而不會向比如 Elasticsearch 類似的 output 端瘋狂輸出泣棋。
使用queue.max_bytes
設置配置磁盤上隊列的總容量。以下示例將隊列的總容量設置為8gb:
queue.type:persisted
queue.max_bytes:8gb
指定這些設置后畔塔,Logstash 將緩存磁盤上的事件潭辈,直到隊列的大小達到8gb鸯屿。當隊列充滿 unACKed 的事件,并且已達到大小限制時把敢,Logstash 將不再接受新的事件寄摆。
每個 input 單獨處理 Back Pressure。例如修赞,當 beats input 遇到 back pressure 時婶恼,它不再接受新連接并等待,直到隊列有空間來接受更多的事件柏副。filter 和 output 階段完成處理隊列中的現(xiàn)有事件并確認它們后勾邦,Logstash 會自動開始接受新的事件。
控制 Durability
Durability 是存儲寫入的一種特性割择,可確保數據在寫入后可用眷篇。
當啟用持久性隊列功能時,Logstash 會將事件存儲在磁盤上荔泳。 Logstash以稱為檢查點的機制提交到磁盤蕉饼。
為了討論 Durability,我們需要介紹一些關于如何實現(xiàn)持久隊列的細節(jié)玛歌。
首先昧港,隊列本身是一組 pages。有兩種 page:head page 和 tail page支子。head page 是新事件寫入的地方创肥,只有一個。當 head page 達到上限(參見queue.page_capacity
)時值朋,它將成為一個 tail page瓤的,并創(chuàng)建一個新的 page。tail page 是不修改的吞歼,head page 是只能追加內容的。其次塔猾,隊列將記錄自己的詳細信息(pages篙骡,ack 確認信息等)記錄在一個名為checkpoint 文件的單獨文件中。
記錄檢查點時丈甸,Logstash將:
- 在 head page 上調用 fsync糯俗。
- 原子地寫入隊列的當前狀態(tài)至磁盤。
以下設置可用于調整持久性:
-
queue.checkpoint.writes
:Logstash 在寫入指定條數事件后睦擂,進行 checkpoint得湘。目前,一個事件計為一個寫入顿仇,但這可能會在將來的版本中更改淘正。 -
queue.checkpoint.acks
:Logstash 在指定條數事件 acked 后摆马,進行 checkpoint。此配置用來控制 Logstash 處理(filter + output)環(huán)節(jié)的 Durability鸿吆。
磁盤寫入具有資源成本囤采。調整上述值或更高值將會調整 durability。例如惩淳,如果您想要所有 input 事件具備最高 durability蕉毯,可以設置queue.checkpoint.writes:1
。
檢查點的過程是原子的思犁,這意味著如果成功代虾,將保存文件的任何更新。
如果 Logstash 終止激蹲,或者如果存在硬件級別故障棉磨,那么在持久性隊列中緩存但尚未檢查點的任何數據都將丟失。為了避免這種可能性托呕,您可以設置 queue.checkpoint.writes:1
含蓉,但請記住,此設置會嚴重影響性能项郊。
磁盤垃圾回收
在磁盤上馅扣,隊列存儲為一組 page,其中每個 page 是一個文件着降。 每個 page 最多可以是 queue.page_capacity
的大小差油。 在該 page 中的所有事件都被確認之后,page 被刪除(垃圾回收)任洞。 如果較舊的 page 至少有一個尚未確認的事件蓄喇,則整個 page 將保留在磁盤上,直到該 page 中的所有事件成功處理交掏。 包含未處理事件的每個 page 將對queue.max_bytes
字節(jié)大小進行計數妆偏。