下一代雲原生消息流平臺 Apache Pulsar 消息保留和過期策略設計
Apache Pulsar 是 Apache 軟件基金會頂級項目,是下一代雲原生分佈式消息流平臺,集消息、存儲、輕量化函數式計算爲一體,採用計算與存儲分離架構設計,支持多租戶、持久化存儲、多機房跨區域數據複製,具有強一致性、高吞吐、低延時及高可擴展性等流數據存儲特性。
作者介紹
冉小龍
騰訊雲微服務產品中心研發工程師
Apache Pulsar Committer
Apache BookKeeper Contributor
默認情況下,Pulsar Broker 會對消息做如下處理:
-
當消息被 Consumer 確認之後,會立即執行刪除操作。
-
對於未被確認的消息會存儲到 backlog 中。
但是,很多線上的生產環境下,這種默認行爲並不能滿足我們的生產需求,所以,Pulsar 提供瞭如下配置策略來覆蓋這些行爲:
-
Retention 策略:用戶可以將 Consumer 已經確認的消息保留下來。
-
TTL 策略:對於未確認的消息,用戶可以通過設置 TTL 來使未確認的消息到達已經確認的狀態。
上述兩種策略的設置都是在 NameSpace 的級別進行設置
Retention 策略
Retention 策略的設置提供了兩種方式:
-
消息的大小,默認值:defaultRetentionSizeInMB=0
-
消息被保存的時間,默認值:defaultRetentionTimeInMinutes=0
我們可以在 broker.conf 中對這兩項內容進行配置也可以通過命令行的形式。上文提到過,這兩種策略的設置,都是在 NameSpace 的級別進行設置,所以當我們使用命令行配置時,使用 NameSpaces 來進行配置,具體如下:
root@e6df71e544ea:/pulsar# ./bin/pulsar-admin namespaces set-retention
The following options are required: --size, -s --time, -t
Set the retention policy for a namespace
Usage: set-retention [options] tenant/namespace
Options:
* --size, -s
Retention size limit (eg: 10M, 16G, 3T). 0 or less than 1MB means no
retention and -1 means infinite size retention
* --time, -t
Retention time in minutes (or minutes, hours, days, weeks eg: 100m, 3h, 2d,
5w). 0 means no retention and -1 means infinite time retention
如上所示:我們可以通過 -s 或者 -t 來指定我們需要配置的大小或者時間。
當你設置 Retention 策略之後,可以通過如下命令來查看具體的信息:
$ pulsar-admin namespaces get-retention [your tenant]/[your-namespace]
{
"retentionTimeInMinutes": 10,
"retentionSizeInMB": 0
}
**Backlog
**
backlog 是未被確認消息的集合,它有一個大前提是,這些消息所在的 Topic 是被 Broker 所持久化的,在默認情況下,用戶創建的 Topic 都會被持久化。換句話說,Pulsar Broker 會將所有未確認或者未處理的消息都存放到 backlog 中。
同樣的,我們可以在 NameSpace 級別對 backlog 的大小進行配置。需要注意的是,對 backlog 進行配置時,我們需要明確以下兩點:
-
在當前的 NameSpace 下,每一個 Topic 允許的大小是多少
-
如果超過設定的 backlog 的閾值,將會執行哪些操作
當超過設定的 backlog 的閾值,Pulsar 提供了以下三種策略供用戶選擇:
你可以通過 set-backlog-quota 在 NameSpace 級別對 backlog 進行配置,具體如下:
root@e6df71e544ea:/pulsar# ./bin/pulsar-admin namespaces set-backlog-quota
The following options are required: -l, --limit -p, --policy
Set a backlog quota policy for a namespace
Usage: set-backlog-quota [options] tenant/namespace
Options:
* -l, --limit
Size limit (eg: 10M, 16G)
* -p, --policy
Retention policy to enforce when the limit is reached. Valid options are:
[producer_request_hold, producer_exception, consumer_backlog_eviction]
如上所示,set-backlog-quota 提供了兩個參數,-l 用來指定你設置 backlog 的大小,-p 用來指定,當超過你設置的 backlog 的閾值之後,Broker 將會執行的策略。
當你設置 backlog 之後,可以通過如下命令,查看相應的信息:
$ pulsar-admin namespaces get-backlog-quotas [your tenant]/[your namespace]
{
"destination_storage": {
"limit" : 2147483648,
"policy" : "producer_request_hold"
}
}
如果你期望取消 backlog 的配置,可以使用如下命令:
$ pulsar-admin namespaces remove-backlog-quota [your tenant]/[your namespace]
當有消息積壓時,你可以通過 clear-backlog 來清除積壓的消息。清除 backlog 中積壓的消息是相對危險的操作,所以系統會提示你,是否確認要刪除 backlog 中的消息, clear-backlog 提供了 -f(--force) 的參數來屏蔽該提示。
$ pulsar-admin namespaces clear-backlog [your tenant]/[your namespace]
Time To Live (TTL)
默認情況下,Pulsar 會持久化所有未被確認的消息。如果未被確認的消息有很多,這種策略會造成大量的消息被積壓,導致磁盤空間增大。有些場景下,消息並不需要被持久化,用戶更期望的行爲是,將這些未被確認的消息直接丟棄。這種情況下,你可以通過設置 TTL 使得未被確認的消息進入到被確認的狀態,當超過設定的 TTL 時間之後,配合相應的 Retention 策略將消息丟棄。
TTL 的一個典型使用場景是,當 Consumer 由於某些原因出現故障,不能正常消費消息,這時 Producer 還在不斷的往 Topic 中生產消息,會造成 Topic 中有大量的未確認的消息出現,這時你可以通過設置 TTL 將這些未確認的消息變爲已確認的狀態。
同樣的,你可以在 Namesapce 級別下,通過指定 set-message-ttl 對 TTL 進行設置,具體命令如下:
root@e6df71e544ea:/pulsar# ./bin/pulsar-admin namespaces set-message-ttl
The following option is required: --messageTTL, -ttl
Set Message TTL for a namespace
Usage: set-message-ttl [options] tenant/namespace
Options:
* --messageTTL, -ttl
Message TTL in seconds
Default: 0
如上所示,set-message-ttl 只有一個參數 -ttl,單位爲秒,默認值爲 0。
當你設置 TTL 策略之後,可以通過 get-message-ttl 查看相應的配置信息,具體如下:
$ pulsar-admin namespaces get-message-ttl [your tenant]/[your namespace]
60
TTL、Backlog 與 Retention 的區別和聯繫
在上述的描述過程中,可以發現,TTL 只去處理一件事情,將未被確認的消息變爲被確認的狀態,TTL 本身不會去涉及相應的刪除操作,具體如下圖所示:
-
在 T1 階段,m1-m5 這 5 條消息被確認,m6-m10 這 5 條消息未被確認
-
在 T2 階段,對 m6、m7、m8 這三條消息設置 TTL 策略
-
在 T3 階段,到達 TTL 設定的閾值,m6、m7、m8 這三條消息被確認
通過上圖可以看到,對於 backlog 中未被確認的消息,當你設置 TTL 之後,會將未確認消息的狀態變爲確認的狀態。TTL 在這裏所起到的作用就是將消息的 Cursor 從 m5 移動到 m8,m6、m7、m8 這三條消息變爲已確認狀態。
Pulsar 是一個 multiple-subscription 的消息系統,對於 Topic 中的一條消息,只有當所有訂閱者都對這條消息 ack 或者消費了,它才能被刪除。
默認情況下,Pulsar Broker 會將所有未確認的消息持久化到 backlog 中。TTL 的功能是,你可以將這些未被確認的消息變爲被確認的狀態,而 Retention 所關注的點是,當消息處於被確認的狀態時,你可以對已確認的消息進行的保留策略是什麼。換句話說,backlog 是針對未確認的消息,Broker 所做的處理是什麼。Retention 是針對已確認的消息,Broker 所做的保留策略是什麼。
TTL 與死信隊列
死信隊列的相關介紹在此不做贅述。
在生產環境中,有時可能遇到質量差的數據是由於上游的原因導致的,必須由上游來解決,繼續嘗試處理其它的消息已經沒有意義,這時候用戶希望在發生錯誤時立即停止處理。Pulsar 中提供了一種特殊的 Topic——死信隊列。
死信隊列與 TTL 都可以將未確認的消息變爲已確認的狀態。他們之間主要的不同在於,在上圖中的 T2 階段,TTL 只是將未確認的消息變爲已確認的狀態,死信隊列的做法是將消息丟棄到死信隊列中,m6、m7、m8 這三條消息變爲被確認的狀態。m9、m10 這兩條有效消息會正常處理,Broker 也會繼續運行。之後,你可以從死信隊列中檢查無效消息,並根據需要忽略或修復並重新處理。用戶可以根據自己的需求來確定未確認的消息是通過 TTL 的形式將其變爲確認狀態還是通過死信隊列的方式來實現,依據的主要標準就是看你需不要處理消費不了的消息。
使用問題
- 場景一:
啓動 Producer 往 Broker 發送消息,設置了 TTL ,沒有啓動 Consumer,同時設置了 Retention 策略爲半小時,到達 Retention 的閾值之後,發現設置 TTL 的消息並沒有被移除,這是爲什麼呢?
在上述場景中,有一個問題需要注意,沒有啓動 Consumer,在上面我們說到,TTL 是將消息設置的 Cousor 向前移動,如果沒有啓動 Consumer,相當於 Cousor 沒有被初始化,也就是如果沒有 Consumer,你就沒有必要去設置 TTL。
- 場景二:
我設置了 Retention 策略,但是到達了 Retention 的閾值,Topic 中的數據並沒有被刪除掉,這是爲什麼呢?
這個是 Pulsar 內部的一個實現機制,在 Pulsar 中 Topic 是一個邏輯的概念,一個 Topic 對應一個 manage ledger,當你寫數據的時候,實際上是將數據寫到了 ledger 中,還記得在之前很多文章中提到的有關 Pulsar 設計的一個核心所在:在 Pulsar 中,所有的操作都是異步的,所以當 Retention 到達指定閾值之後,是否刪除對應 ledger 中的數據,這個操作也是異步的。delete 的操作是不會對當前 active 的 ledger 執行的。只有當數據寫滿了當前的 ledger ,ledger 發生切換時,纔會去真正的執行 retention 策略。
如果想要強制執行,可以使用 pulsar-admin 將當前的 ledger 強制卸載,迫使其發生 ledger 的切換。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/uznWp2mClwIx44956Afy6A