下一代雲原生消息流平臺 Apache Pulsar 消息保留和過期策略設計

Apache Pulsar 是 Apache 軟件基金會頂級項目,是下一代雲原生分佈式消息流平臺,集消息、存儲、輕量化函數式計算爲一體,採用計算與存儲分離架構設計,支持多租戶、持久化存儲、多機房跨區域數據複製,具有強一致性、高吞吐、低延時及高可擴展性等流數據存儲特性。

作者介紹

冉小龍

騰訊雲微服務產品中心研發工程師
Apache Pulsar Committer
Apache BookKeeper Contributor

默認情況下,Pulsar Broker 會對消息做如下處理:

但是,很多線上的生產環境下,這種默認行爲並不能滿足我們的生產需求,所以,Pulsar 提供瞭如下配置策略來覆蓋這些行爲:

上述兩種策略的設置都是在 NameSpace 的級別進行設置

Retention 策略

Retention 策略的設置提供了兩種方式:

我們可以在 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 進行配置時,我們需要明確以下兩點:

當超過設定的 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 本身不會去涉及相應的刪除操作,具體如下圖所示:

圖片

  1. 在 T1 階段,m1-m5 這 5 條消息被確認,m6-m10 這 5 條消息未被確認

  2. 在 T2 階段,對 m6、m7、m8 這三條消息設置 TTL 策略

  3. 在 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