Kafka萬億級訊息實戰

vivo網際網路技術發表於2021-05-18

一、Kafka應用

本文主要總結當Kafka叢集流量達到 萬億級記錄/天或者十萬億級記錄/天  甚至更高後,我們需要具備哪些能力才能保障叢集高可用、高可靠、高效能、高吞吐、安全的執行。

這裡總結內容主要針對Kafka2.1.1版本,包括叢集版本升級、資料遷移、流量限制、監控告警、負載均衡、叢集擴/縮容、資源隔離、叢集容災、叢集安全、效能優化、平臺化、開源版本缺陷、社群動態等方面。本文主要是介紹核心脈絡,不做過多細節講解。下面我們先來看看Kafka作為資料中樞的一些核心應用場景。

下圖展示了一些主流的資料處理流程,Kafka起到一個資料中樞的作用。

接下來看看我們Kafka平臺整體架構;

1.1 版本升級

1.1.1  開源版本如何進行版本滾動升級與回退

官網地址:http://kafka.apache.org

1.1.1.2 原始碼改造如何升級與回退

由於在升級過程中,必然出現新舊程式碼邏輯交替的情況。叢集內部部分節點是開源版本,另外一部分節點是改造後的版本。所以,需要考慮在升級過程中,新舊程式碼混合的情況,如何相容以及出現故障時如何回退。

1.2 資料遷移

由於Kafka叢集的架構特點,這必然導致叢集內流量負載不均衡的情況,所以我們需要做一些資料遷移來實現叢集不同節點間的流量均衡。Kafka開源版本為資料遷移提供了一個指令碼工具“bin/kafka-reassign-partitions.sh”,如果自己沒有實現自動負載均衡,可以使用此指令碼。

開源版本提供的這個指令碼生成遷移計劃完全是人工干預的,當叢集規模非常大時,遷移效率變得非常低下,一般以天為單位進行計算。當然,我們可以實現一套自動化的均衡程式,當負載均衡實現自動化以後,基本使用呼叫內部提供的API,由程式去幫我們生成遷移計劃及執行遷移任務。需要注意的是,遷移計劃有指定資料目錄和不指定資料目錄兩種,指定資料目錄的需要配置ACL安全認證。

官網地址:http://kafka.apache.org

1.2.1 broker間資料遷移

不指定資料目錄

//未指定遷移目錄的遷移計劃
{
    "version":1,
    "partitions":[
        {"topic":"yyj4","partition":0,"replicas":[1000003,1000004]},
        {"topic":"yyj4","partition":1,"replicas":[1000003,1000004]},
        {"topic":"yyj4","partition":2,"replicas":[1000003,1000004]}
    ]
}

指定資料目錄

//指定遷移目錄的遷移計劃
{
    "version":1,
    "partitions":[
        {"topic":"yyj1","partition":0,"replicas":[1000006,1000005],"log_dirs":["/data1/bigdata/mydata1","/data1/bigdata/mydata3"]},
        {"topic":"yyj1","partition":1,"replicas":[1000006,1000005],"log_dirs":["/data1/bigdata/mydata1","/data1/bigdata/mydata3"]},
        {"topic":"yyj1","partition":2,"replicas":[1000006,1000005],"log_dirs":["/data1/bigdata/mydata1","/data1/bigdata/mydata3"]}
    ]
}

1.2.2 broker內部磁碟間資料遷移

生產環境的伺服器一般都是掛載多塊硬碟,比如4塊/12塊等;那麼可能出現在Kafka叢集內部,各broker間流量比較均衡,但是在broker內部,各磁碟間流量不均衡,導致部分磁碟過載,從而影響叢集效能和穩定,也沒有較好的利用硬體資源。在這種情況下,我們就需要對broker內部多塊磁碟的流量做負載均衡,讓流量更均勻的分佈到各磁碟上。

1.2.3 併發資料遷移

當前Kafka開源版本(2.1.1版本)提供的副本遷移工具“bin/kafka-reassign-partitions.sh”在同一個叢集內只能實現遷移任務的序列。對於叢集內已經實現多個資源組物理隔離的情況,由於各資源組不會相互影響,但是卻不能友好的進行並行的提交遷移任務,遷移效率有點低下,這種不足直到2.6.0版本才得以解決。如果需要實現併發資料遷移,可以選擇升級Kafka版本或者修改Kafka原始碼。

1.2.4 終止資料遷移

當前Kafka開源版本(2.1.1版本)提供的副本遷移工具“bin/kafka-reassign-partitions.sh”在啟動遷移任務後,無法終止遷移。當遷移任務對叢集的穩定性或者效能有影響時,將變得束手無策,只能等待遷移任務執行完畢(成功或者失敗),這種不足直到2.6.0版本才得以解決。如果需要實現終止資料遷移,可以選擇升級Kafka版本或者修改Kafka原始碼。

1.3 流量限制

1.3.1 生產消費流量限制

經常會出現一些突發的,不可預測的異常生產或者消費流量會對叢集的IO等資源產生巨大壓力,最終影響整個叢集的穩定與效能。那麼我們可以對使用者的生產、消費、副本間資料同步進行流量限制,這個限流機制並不是為了限制使用者,而是避免突發的流量影響叢集的穩定和效能,給使用者可以更好的服務。

如下圖所示,節點入流量由140MB/s左右突增到250MB/s,而出流量則從400MB/s左右突增至800MB/s。如果沒有限流機制,那麼叢集的多個節點將有被這些異常流量打掛的風險,甚至造成叢集雪崩。

圖片生產/消費流量限制官網地址:點選連結

對於生產者和消費者的流量限制,官網提供了以下幾種維度組合進行限制(當然,下面限流機制存在一定缺陷,後面在“Kafka開源版本功能缺陷”我們將提到):

/config/users/<user>/clients/<client-id> //根據使用者和客戶端ID組合限流
/config/users/<user>/clients/<default>
/config/users/<user>//根據使用者限流 這種限流方式是我們最常用的方式
/config/users/<default>/clients/<client-id>
/config/users/<default>/clients/<default>
/config/users/<default>
/config/clients/<client-id>
/config/clients/<default>

在啟動Kafka的broker服務時需要開啟JMX引數配置,方便通過其他應用程式採集Kafka的各項JMX指標進行服務監控。當使用者需要調整限流閾值時,根據單個broker所能承受的流量進行智慧評估,無需人工干預判斷是否可以調整;對於使用者流量限制,主要需要參考的指標包括以下兩個:

(1)消費流量指標:ObjectName:kafka.server:type=Fetch,user=acl認證使用者名稱稱 屬性:byte-rate(使用者在當前broker的出流量)、throttle-time(使用者在當前broker的出流量被限制時間)
(2)生產流量指標:ObjectName:kafka.server:type=Produce,user=acl認證使用者名稱稱 屬性:byte-rate(使用者在當前broker的入流量)、throttle-time(使用者在當前broker的入流量被限制時間)


1.3.2 follower同步leader/資料遷移流量限制

副本遷移/資料同步流量限制官網地址:連結

涉及引數如下:

//副本同步限流配置共涉及以下4個引數
leader.replication.throttled.rate
follower.replication.throttled.rate
leader.replication.throttled.replicas
follower.replication.throttled.replicas

輔助指標如下:

(1)副本同步出流量指標:ObjectName:kafka.server:type=BrokerTopicMetrics,name=ReplicationBytesOutPerSec
(2)副本同步入流量指標:ObjectName:kafka.server:type=BrokerTopicMetrics,name=ReplicationBytesInPerSec

1.4 監控告警

關於Kafka的監控有一些開源的工具可用使用,比如下面這幾種:

Kafka Manager

Kafka Eagle

Kafka Monitor

KafkaOffsetMonitor;

我們已經把Kafka Manager作為我們檢視一些基本指標的工具嵌入平臺,然而這些開源工具不能很好的融入到我們自己的業務系統或者平臺上。所以,我們需要自己去實現一套粒度更細、監控更智慧、告警更精準的系統。其監控覆蓋範圍應該包括基礎硬體、作業系統(作業系統偶爾出現系統程式hang住情況,導致broker假死,無法正常提供服務)、Kafka的broker服務、Kafka客戶端應用程式、zookeeper叢集、上下游全鏈路監控。

1.4.1 硬體監控

網路監控:

核心指標包括網路入流量、網路出流量、網路丟包、網路重傳、處於TIME.WAIT的TCP連線數、交換機、機房頻寬、DNS伺服器監控(如果DNS伺服器異常,可能出現流量黑洞,引起大面積業務故障)等。

磁碟監控:

核心指標包括監控磁碟write、磁碟read(如果消費時沒有延時,或者只有少量延時,一般都沒有磁碟read操作)、磁碟ioutil、磁碟iowait(這個指標如果過高說明磁碟負載較大)、磁碟儲存空間、磁碟壞盤、磁碟壞塊/壞道(壞道或者壞塊將導致broker處於半死不活狀態,由於有crc校驗,消費者將被卡住)等。

CPU監控:

監控CPU空閒率/負載,主機板故障等,通常CPU使用率比較低不是Kafka的瓶頸。

記憶體/交換區監控:

記憶體使用率,記憶體故障。一般情況下,伺服器上除了啟動Kafka的broker時分配的堆記憶體以外,其他記憶體基本全部被用來做PageCache。

快取命中率監控:

由於是否讀磁碟對Kafka的效能影響很大,所以我們需要監控Linux的PageCache快取命中率,如果快取命中率高,則說明消費者基本命中快取。

詳細內容請閱讀文章:《Linux Page Cache調優在Kafka中的應用》。

系統日誌:

我們需要對作業系統的錯誤日誌進行監控告警,及時發現一些硬體故障。

1.4.2 broker服務監控

broker服務的監控,主要是通過在broker服務啟動時指定JMX埠,然後通過實現一套指標採集程式去採集JMX指標。(服務端指標官網地址

broker級監控:broker程式、broker入流量位元組大小/記錄數、broker出流量位元組大小/記錄數、副本同步入流量、副本同步出流量、broker間流量偏差、broker連線數、broker請求佇列數、broker網路空閒率、broker生產延時、broker消費延時、broker生產請求數、broker消費請求數、broker上分佈leader個數、broker上分佈副本個數、broker上各磁碟流量、broker GC等。

topic級監控:topic入流量位元組大小/記錄數、topic出流量位元組大小/記錄數、無流量topic、topic流量突變(突增/突降)、topic消費延時。

partition級監控:分割槽入流量位元組大小/記錄數、分割槽出流量位元組大小/記錄數、topic分割槽副本缺失、分割槽消費延遲記錄、分割槽leader切換、分割槽資料傾斜(生產訊息時,如果指定了訊息的key容易造成資料傾斜,這嚴重影響Kafka的服務效能)、分割槽儲存大小(可以治理單分割槽過大的topic)。

使用者級監控:使用者出/入流量位元組大小、使用者出/入流量被限制時間、使用者流量突變(突增/突降)。

broker服務日誌監控:對server端列印的錯誤日誌進行監控告警,及時發現服務異常。

1.4.3.客戶端監控

客戶端監控主要是自己實現一套指標上報程式,這個程式需要實現

org.apache.kafka.common.metrics.MetricsReporter 介面。然後在生產者或者消費者的配置中加入配置項 metric.reporters,如下所示:

Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, IntegerSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
 
//ClientMetricsReporter類實現org.apache.kafka.common.metrics.MetricsReporter介面
props.put(ProducerConfig.METRIC_REPORTER_CLASSES_CONFIG, ClientMetricsReporter.class.getName());
...

客戶端指標官網地址:

http://kafka.apache.org/21/documentation.html#selector_monitoring

http://kafka.apache.org/21/documentation.html#common_node_monitoring

http://kafka.apache.org/21/documentation.html#producer_monitoring

http://kafka.apache.org/21/documentation.html#producer_sender_monitoring

http://kafka.apache.org/21/documentation.html#consumer_monitoring

http://kafka.apache.org/21/documentation.html#consumer_fetch_monitoring

客戶端監控流程架構如下圖所示:

1.4.3.1 生產者客戶端監控

維度:使用者名稱稱、客戶端ID、客戶端IP、topic名稱、叢集名稱、brokerIP;

指標:連線數、IO等待時間、生產流量大小、生產記錄數、請求次數、請求延時、傳送錯誤/重試次數等。

1.4.3.2 消費者客戶端監控

維度:使用者名稱稱、客戶端ID、客戶端IP、topic名稱、叢集名稱、消費組、brokerIP、topic分割槽;

指標:連線數、io等待時間、消費流量大小、消費記錄數、消費延時、topic分割槽消費延遲記錄等。

1.4.4 Zookeeper監控

  1. Zookeeper程式監控;

  2. Zookeeper的leader切換監控;

  3. Zookeeper服務的錯誤日誌監控;

1.4.5 全鏈路監控

當資料鏈路非常長的時候(比如:業務應用->埋點SDk->資料採集->Kafka->實時計算->業務應用),我們定位問題通常需要經過多個團隊反覆溝通與排查才能發現問題到底出現在哪個環節,這樣排查問題效率比較低下。在這種情況下,我們就需要與上下游一起梳理整個鏈路的監控。出現問題時,第一時間定位問題出現在哪個環節,縮短問題定位與故障恢復時間。

1.5 資源隔離

1.5.1 相同叢集不同業務資源物理隔離

我們對所有叢集中不同對業務進行資源組物理隔離,避免各業務之間相互影響。在這裡,我們假設叢集有4個broker節點(Broker1/Broker2/Broker3/Broker4),2個業務(業務A/業務B),他們分別擁有topic分割槽分佈如下圖所示,兩個業務topic都分散在叢集的各個broker上,並且在磁碟層面也存在交叉。

試想一下,如果我們其中一個業務異常,比如流量突增,導致broker節點異常或者被打掛。那麼這時候另外一個業務也將受到影響,這樣將大大的影響了我們服務的可用性,造成故障,擴大了故障影響範圍。

針對這些痛點,我們可以對叢集中的業務進行物理資源隔離,各業務獨享資源,進行資源組劃分(這裡把4各broker劃分為Group1和Group2兩個資源組)如下圖所示,不同業務的topic分佈在自己的資源組內,當其中一個業務異常時,不會波及另外一個業務,這樣就可以有效的縮小我們的故障範圍,提高服務可用性。

1.6 叢集歸類

我們把叢集根據業務特點進行拆分為日誌叢集、監控叢集、計費叢集、搜尋叢集、離線叢集、線上叢集等,不同場景業務放在不同叢集,避免不同業務相互影響。

1.7 擴容/縮容

1.7.1 topic擴容分割槽

隨著topic資料量增長,我們最初建立的topic指定的分割槽個數可能已經無法滿足數量流量要求,所以我們需要對topic的分割槽進行擴充套件。擴容分割槽時需要考慮一下幾點:

必須保證topic分割槽leader與follower輪詢的分佈在資源組內所有broker上,讓流量分佈更加均衡,同時需要考慮相同分割槽不同副本跨機架分佈以提高容災能力;

當topic分割槽leader個數除以資源組節點個數有餘數時,需要把餘數分割槽leader優先考慮放入流量較低的broker。

1.7.2 broker上線

隨著業務量增多,資料量不斷增大,我們的叢集也需要進行broker節點擴容。關於擴容,我們需要實現以下幾點:

擴容智慧評估:根據叢集負載,把是否需要擴容評估程式化、智慧化;

智慧擴容:當評估需要擴容後,把擴容流程以及流量均衡平臺化。

1.7.3 broker下線

某些場景下,我們需要下線我們的broker,主要包括以下幾個場景:

一些老化的伺服器需要下線,實現節點下線平臺化;

伺服器故障,broker故障無法恢復,我們需要下線故障伺服器,實現節點下線平臺化;

有更優配置的伺服器替換已有broker節點,實現下線節點平臺化。

1.8 負載均衡

我們為什麼需要負載均衡呢?首先,我們來看第一張圖,下圖是我們叢集某個資源組剛擴容後的流量分佈情況,流量無法自動的分攤到我們新擴容後的節點上。那麼這個時候需要我們手動去觸發資料遷移,把部分副本遷移至新節點上才能實現流量均衡。

下面,我們來看一下第二張圖。這張圖我們可以看出流量分佈非常不均衡,最低和最高流量偏差數倍以上。這和Kafka的架構特點有關,當叢集規模與資料量達到一定量後,必然出現當問題。這種情況下,我們也需要進行負載均衡。

我們再來看看第三張圖。這裡我們可以看出出流量只有部分節點突增,這就是topic分割槽在叢集內部不夠分散,集中分佈到了某幾個broker導致,這種情況我們也需要進行擴容分割槽和均衡。

我們比較理想的流量分佈應該如下圖所示,各節點間流量偏差非常小,這種情況下,既可以增強叢集扛住流量異常突增的能力又可以提升叢集整體資源利用率和服務穩定性,降低成本。

負載均衡我們需要實現以下效果:

1)生成副本遷移計劃以及執行遷移任務平臺化、自動化、智慧化;

2)執行均衡後broker間流量比較均勻,且單個topic分割槽均勻分佈在所有broker節點上;

3)執行均衡後broker內部多塊磁碟間流量比較均衡;

要實現這個效果,我們需要開發一套自己的負載均衡工具,如對開源的 cruise control進行二次開發;此工具的核心主要在生成遷移計劃的策略,遷移計劃的生成方案直接影響到最後叢集負載均衡的效果。參考內容:

1. linkedIn/cruise-control

2. Introduction to Kafka Cruise Control

3. Cloudera Cruise Control REST API Reference

cruise control架構圖如下:

在生成遷移計劃時,我們需要考慮以下幾點:

1)選擇核心指標作為生成遷移計劃的依據,比如出流量、入流量、機架、單topic分割槽分散性等;

2)優化用來生成遷移計劃的指標樣本,比如過濾流量突增/突降/掉零等異常樣本;

3)各資源組的遷移計劃需要使用的樣本全部為資源組內部樣本,不涉及其他資源組,無交叉;

4)治理單分割槽過大topic,讓topic分割槽分佈更分散,流量不集中在部分broker,讓topic單分割槽資料量更小,這樣可以減少遷移的資料量,提升遷移速度;

5)已經均勻分散在資源組內的topic,加入遷移黑名單,不做遷移,這樣可以減少遷移的資料量,提升遷移速度;

6)做topic治理,排除長期無流量topic對均衡的干擾;

7)新建topic或者topic分割槽擴容時,應讓所有分割槽輪詢分佈在所有broker節點,輪詢後餘數分割槽優先分佈流量較低的broker;

8)擴容broker節點後開啟負載均衡時,優先把同一broker分配了同一大流量(流量大而不是儲存空間大,這裡可以認為是每秒的吞吐量)topic多個分割槽leader的,遷移一部分到新broker節點;

9)提交遷移任務時,同一批遷移計劃中的分割槽資料大小偏差應該儘可能小,這樣可以避免遷移任務中小分割槽遷移完成後長時間等待大分割槽的遷移,造成任務傾斜;

1.9 安全認證

是不是我們的叢集所有人都可以隨意訪問呢?當然不是,為了叢集的安全,我們需要進行許可權認證,遮蔽非法操作。主要包括以下幾個方面需要做安全認證:

(1)生產者許可權認證;

(2)消費者許可權認證;

(3)指定資料目錄遷移安全認證;

官網地址:http://kafka.apache.org

1.10 叢集容災

跨機架容災:

官網地址:http://kafka.apache.org

跨叢集/機房容災:如果有異地雙活等業務場景時,可以參考Kafka2.7版本的MirrorMaker 2.0。

GitHub地址:https://github.com

精確KIP地址 :https://cwiki.apache.org

ZooKeeper叢集上Kafka後設資料恢復:我們會定期對ZooKeeper上的許可權資訊資料做備份處理,當叢集後設資料異常時用於恢復。

1.11 引數/配置優化

broker服務引數優化:這裡我只列舉部分影響效能的核心引數。

num.network.threads
#建立Processor處理網路請求執行緒個數,建議設定為broker當CPU核心數*2,這個值太低經常出現網路空閒太低而缺失副本。
 
num.io.threads
#建立KafkaRequestHandler處理具體請求執行緒個數,建議設定為broker磁碟個數*2
 
num.replica.fetchers
#建議設定為CPU核心數/4,適當提高可以提升CPU利用率及follower同步leader資料當並行度。
 
compression.type
#建議採用lz4壓縮型別,壓縮可以提升CPU利用率同時可以減少網路傳輸資料量。
 
queued.max.requests
#如果是生產環境,建議配置最少500以上,預設為500。
 
log.flush.scheduler.interval.ms
log.flush.interval.ms
log.flush.interval.messages
#這幾個參數列示日誌資料重新整理到磁碟的策略,應該保持預設配置,刷盤策略讓作業系統去完成,由作業系統來決定什麼時候把資料刷盤;
#如果設定來這個引數,可能對吞吐量影響非常大;
 
auto.leader.rebalance.enable
#表示是否開啟leader自動負載均衡,預設true;我們應該把這個引數設定為false,因為自動負載均衡不可控,可能影響叢集效能和穩定;

生產優化:這裡我只列舉部分影響效能的核心引數。

linger.ms
#客戶端生產訊息等待多久時間才傳送到服務端,單位:毫秒。和batch.size引數配合使用;適當調大可以提升吞吐量,但是如果客戶端如果down機有丟失資料風險;
 
batch.size
#客戶端傳送到服務端訊息批次大小,和linger.ms引數配合使用;適當調大可以提升吞吐量,但是如果客戶端如果down機有丟失資料風險;
 
compression.type
#建議採用lz4壓縮型別,具備較高的壓縮比及吞吐量;由於Kafka對CPU的要求並不高,所以,可以通過壓縮,充分利用CPU資源以提升網路吞吐量;
 
buffer.memory
#客戶端緩衝區大小,如果topic比較大,且記憶體比較充足,可以適當調高這個引數,預設只為33554432(32MB)
 
retries
#生產失敗後的重試次數,預設0,可以適當增加。當重試超過一定次數後,如果業務要求資料準確性較高,建議做容錯處理。
 
retry.backoff.ms
#生產失敗後,重試時間間隔,預設100ms,建議不要設定太大或者太小。

除了一些核心引數優化外,我們還需要考慮比如topic的分割槽個數和topic保留時間;如果分割槽個數太少,保留時間太長,但是寫入資料量非常大的話,可能造成以下問題:

1)topic分割槽集中落在某幾個broker節點上,導致流量副本失衡;

2)導致broker節點內部某幾塊磁碟讀寫超負載,儲存被寫爆;

1.11.1 消費優化

消費最大的問題,並且經常出現的問題就是消費延時,拉歷史資料。當大量拉取歷史資料時將出現大量讀盤操作,汙染pagecache,這個將加重磁碟的負載,影響叢集效能和穩定;

可以怎樣減少或者避免大量消費延時呢?

1)當topic資料量非常大時,建議一個分割槽開啟一個執行緒去消費;

2)對topic消費延時新增監控告警,及時發現處理;

3)當topic資料可以丟棄時,遇到超大延時,比如單個分割槽延遲記錄超過千萬甚至數億,那麼可以重置topic的消費點位進行緊急處理;【此方案一般在極端場景才使用】

4)避免重置topic的分割槽offset到很早的位置,這可能造成拉取大量歷史資料;

1.11.2 Linux伺服器引數優化

我們需要對Linux的檔案控制程式碼、pagecache等引數進行優化。可參考《Linux Page Cache調優在Kafka中的應用》。

1.12.硬體優化

磁碟優化

在條件允許的情況下,可以採用SSD固態硬碟替換HDD機械硬碟,解決機械盤IO效能較低的問題;如果沒有SSD固態硬碟,則可以對伺服器上的多塊硬碟做硬RAID(一般採用RAID10),讓broker節點的IO負載更加均衡。如果是HDD機械硬碟,一個broker可以掛載多塊硬碟,比如 12塊*4TB。

記憶體

由於Kafka屬於高頻讀寫型服務,而Linux的讀寫請求基本走的都是Page Cache,所以單節點記憶體大一些對效能會有比較明顯的提升。一般選擇256GB或者更高。

網路

提升網路頻寬:在條件允許的情況下,網路頻寬越大越好。因為這樣網路頻寬才不會成為效能瓶頸,最少也要達到萬兆網路( 10Gb,網路卡為全雙工)才能具備相對較高的吞吐量。如果是單通道,網路出流量與入流量之和的上限理論值是1.25GB/s;如果是雙工雙通道,網路出入流量理論值都可以達到1.25GB/s。

網路隔離打標:由於一個機房可能既部署有離線叢集(比如HBase、Spark、Hadoop等)又部署有實時叢集(如Kafka)。那麼實時叢集和離線叢集掛載到同一個交換機下的伺服器將出現競爭網路頻寬的問題,離線叢集可能對實時叢集造成影響。所以我們需要進行交換機層面的隔離,讓離線機器和實時叢集不要掛載到相同的交換機下。即使有掛載到相同交換機下面的,我們也將進行網路通行優先順序(金、銀、銅、鐵)標記,當網路頻寬緊張的時候,讓實時業務優先通行。

CPU

Kafka的瓶頸不在CPU,單節點一般有32核的CPU都足夠使用。

1.13.平臺化

現在問題來了,前面我們提到很多監控、優化等手段;難道我們管理員或者業務使用者對叢集所有的操作都需要登入叢集伺服器嗎?答案當然是否定的,我們需要豐富的平臺化功能來支援。一方面是為了提升我們操作的效率,另外一方面也是為了提升叢集的穩定和降低出錯的可能。

配置管理

黑屏操作,每次修改broker的server.properties配置檔案都沒有變更記錄可追溯,有時可能因為有人修改了叢集配置導致一些故障,卻找不到相關記錄。如果我們把配置管理做到平臺上,每次變更都有跡可循,同時降低了變更出錯的風險。

滾動重啟

當我們需要做線上變更時,有時候需要對叢集對多個節點做滾動重啟,如果到命令列去操作,那效率將變得很低,而且需要人工去幹預,浪費人力。這個時候我們就需要把這種重複性的工作進行平臺化,提升我們的操作效率。

叢集管理

叢集管理主要是把原來在命令列的一系列操作做到平臺上,使用者和管理員不再需要黑屏操作Kafka叢集;這樣做主要有以下優點:

提升操作效率;

操作出錯概率更小,叢集更安全;

所有操作有跡可循,可以追溯;

叢集管理主要包括:broker管理、topic管理、生產/消費許可權管理、使用者管理等

1.13.1 mock功能

在平臺上為使用者的topic提供生產樣例資料與消費抽樣的功能,使用者可以不用自己寫程式碼也可以測試topic是否可以使用,許可權是否正常;

在平臺上為使用者的topic提供生產/消費許可權驗證功能,讓使用者可以明確自己的賬號對某個topic有沒有讀寫許可權;

1.13.2 許可權管理

把使用者讀/寫許可權管理等相關操作進行平臺化。

1.13.3 擴容/縮容

把broker節點上下線做到平臺上,所有的上線和下線節點不再需要操作命令列。

1.13.4 叢集治理

1)無流量topic的治理,對叢集中無流量topic進行清理,減少過多無用後設資料對叢集造成的壓力;

2)topic分割槽資料大小治理,把topic分割槽資料量過大的topic(如單分割槽資料量超過100GB/天)進行梳理,看看是否需要擴容,避免資料集中在叢集部分節點上;

3)topic分割槽資料傾斜治理,避免客戶端在生產訊息的時候,指定訊息的key,但是key過於集中,訊息只集中分佈在部分分割槽,導致資料傾斜;

4)topic分割槽分散性治理,讓topic分割槽分佈在叢集儘可能多的broker上,這樣可以避免因topic流量突增,流量只集中到少數節點上的風險,也可以避免某個broker異常對topic影響非常大;

5)topic分割槽消費延時治理;一般有延時消費較多的時候有兩種情況,一種是叢集效能下降,另外一種是業務方的消費併發度不夠,如果是消費者併發不夠的化應該與業務聯絡增加消費併發。

1.13.5 監控告警

1)把所有指標採集做成平臺可配置,提供統一的指標採集和指標展示及告警平臺,實現一體化監控;

2)把上下游業務進行關聯,做成全鏈路監控;

3)使用者可以配置topic或者分割槽流量延時、突變等監控告警;

1.13.6 業務大屏

業務大屏主要指標:叢集個數、節點個數、日入流量大小、日入流量記錄、日出流量大小、日出流量記錄、每秒入流量大小、每秒入流量記錄、每秒出流量大小、每秒出流量記錄、使用者個數、生產延時、消費延時、資料可靠性、服務可用性、資料儲存大小、資源組個數、topic個數、分割槽個數、副本個數、消費組個數等指標。

1.13.7 流量限制

把使用者流量現在做到平臺,在平臺進行智慧限流處理。

1.13.8 負載均衡

把自動負載均衡功能做到平臺,通過平臺進行排程和管理。

1.13.9 資源預算

當叢集達到一定規模,流量不斷增長,那麼叢集擴容機器從哪裡來呢?業務的資源預算,讓叢集裡面的多個業務根據自己在叢集中當流量去分攤整個叢集的硬體成本;當然,獨立叢集與獨立隔離的資源組,預算方式可以單獨計算。

1.14.效能評估

1.14.1 單broker效能評估

我們做單broker效能評估的目的包括以下幾方面:

1)為我們進行資源申請評估提供依據;

2)讓我們更瞭解叢集的讀寫能力及瓶頸在哪裡,針對瓶頸進行優化;

3)為我們限流閾值設定提供依據;

4)為我們評估什麼時候應該擴容提供依據;

1.14.2 topic分割槽效能評估

1)為我們建立topic時,評估應該指定多少分割槽合理提供依據;

2)為我們topic的分割槽擴容評估提供依據;

1.14.3 單磁碟效能評估

1)為我們瞭解磁碟的真正讀寫能力,為我們選擇更合適Kafka的磁碟型別提供依據;

2)為我們做磁碟流量告警閾值設定提供依據;

1.14.4 叢集規模限制摸底

1)我們需要了解單個叢集規模的上限或者是後設資料規模的上限,探索相關資訊對叢集效能和穩定性的影響;

2)根據摸底情況,評估叢集節點規模的合理範圍,及時預測風險,進行超大叢集的拆分等工作;

1.15 DNS+LVS的網路架構

當我們的叢集節點達到一定規模,比如單叢集數百個broker節點,那麼此時我們生產消費客戶端指定bootstrap.servers配置時,如果指定呢?是隨便選擇其中幾個broker配置還是全部都配上呢?

其實以上做法都不合適,如果只配置幾個IP,當我們配置當幾個broker節點下線後,我們當應用將無法連線到Kafka叢集;如果配置所有IP,那更不現實啦,幾百個IP,那麼我們應該怎麼做呢?

方案:採用DNS+LVS網路架構,最終生產者和消費者客戶端只需要配置域名就可以啦。需要注意的是,有新節點加入叢集時,需要新增對映;有節點下線時,需要從對映中踢掉,否則這批機器如果拿到其他的地方去使用,如果埠和Kafka的一樣的話,原來叢集部分請求將傳送到這個已經下線的伺服器上來,造成生產環境重點故障。

二、開源版本功能缺陷

RTMP協議主要的特點有:多路複用,分包和應用層協議。以下將對這些特點進行詳細的描述。

2.1 副本遷移

無法實現增量遷移;【我們已經基於2.1.1版本原始碼改造,實現了增量遷移】

無法實現併發遷移;【開源版本直到2.6.0才實現了併發遷移】

無法實現終止遷移;【我們已經基於2.1.1版本原始碼改造,實現了終止副本遷移】【開源版本直到2.6.0才實現了暫停遷移,和終止遷移有些不一樣,不會回滾後設資料】

當指定遷移資料目錄時,遷移過程中,如果把topic保留時間改短,topic保留時間針對正在遷移topic分割槽不生效,topic分割槽過期資料無法刪除;【開源版本bug,目前還沒有修復】

當指定遷移資料目錄時,當遷移計劃為以下場景時,整個遷移任務無法完成遷移,一直處於卡死狀態;【開源版本bug,目前還沒有修復】

遷移過程中,如果有重啟broker節點,那個broker節點上的所有leader分割槽無法切換回來,導致節點流量全部轉移到其他節點,直到所有副本被遷移完畢後leader才會切換回來;【開源版本bug,目前還沒有修復】。

在原生的Kafka版本中存在以下指定資料目錄場景無法遷移完畢的情況,此版本我們也不決定修復次bug:
 
1.針對同一個topic分割槽,如果部分目標副本相比原副本是所屬broker發生變化,部分目標副本相比原副本是broker內部所屬資料目錄發生變化;
那麼副本所屬broker發生變化的那個目標副本可以正常遷移完畢,目標副本是在broker內部資料目錄發生變化的無法正常完成遷移;
但是舊副本依然可以正常提供生產、消費服務,並且不影響下一次遷移任務的提交,下一次遷移任務只需要把此topic分割槽的副本列表所屬broker列表變更後提交依然可以正常完成遷移,並且可以清理掉之前未完成的目標副本;
 
這裡假設topic yyj1的初始化副本分佈情況如下:
 
{
"version":1,
"partitions":[
{"topic":"yyj","partition":0,"replicas":[1000003,1000001],"log_dirs":["/kfk211data/data31","/kfk211data/data13"]}
]
}
//遷移場景1:
{
"version":1,
"partitions":[
{"topic":"yyj","partition":0,"replicas":[1000003,1000002],"log_dirs":["/kfk211data/data32","/kfk211data/data23"]}
]
}
 
//遷移場景2:
{
"version":1,
"partitions":[
{"topic":"yyj","partition":0,"replicas":[1000002,1000001],"log_dirs":["/kfk211data/data22","/kfk211data/data13"]}
]
}
針對上述的topic yyj1的分佈分佈情況,此時如果我們的遷移計劃為“遷移場景1”或遷移場景2“,那麼都將出現有副本無法遷移完畢的情況。
但是這並不影響舊副本處理生產、消費請求,並且我們可以正常提交其他的遷移任務。
為了清理舊的未遷移完成的副本,我們只需要修改一次遷移計劃【新的目標副本列表和當前分割槽已分配副本列表完全不同即可】,再次提交遷移即可。
 
這裡,我們依然以上述的例子做遷移計劃修改如下:
{
"version":1,
"partitions":[
{"topic":"yyj","partition":0,"replicas":[1000004,1000005],"log_dirs":["/kfk211data/data42","/kfk211data/data53"]}
]
}
這樣我們就可以正常完成遷移。

2.2 流量協議

限流粒度較粗,不夠靈活精準,不夠智慧。

當前限流維度組合

/config/users/<user>/clients/<client-id>
/config/users/<user>/clients/<default>
/config/users/<user>
/config/users/<default>/clients/<client-id>
/config/users/<default>/clients/<default>
/config/users/<default>
/config/clients/<client-id>
/config/clients/<default>

存在問題

當同一個broker上有多個使用者同時進行大量的生產和消費時,想要讓broker可以正常執行,那必須在做限流時讓所有的使用者流量閾值之和不超過broker的吞吐上限;如果超過broker上限,那麼broker就存在被打掛的風險;然而,即使使用者流量沒有達到broker的流量上限,但是,如果所有使用者流量集中到了某幾塊盤上,超過了磁碟的讀寫負載,也會導致所有生產、消費請求將被阻塞,broker可能處於假死狀態。

解決方案

(1)改造原始碼,實現單個broker流量上限限制,只要流量達到broker上限立即進行限流處理,所有往這個broker寫的使用者都可以被限制住;或者對使用者進行優先順序處理,放過高優先順序的,限制低優先順序的;

(2)改造原始碼,實現broker上單塊磁碟流量上限限制(很多時候都是流量集中到某幾塊磁碟上,導致沒有達到broker流量上限卻超過了單磁碟讀寫能力上限),只要磁碟流量達到上限,立即進行限流處理,所有往這個磁碟寫的使用者都可以被限制住;或者對使用者進行優先順序處理,放過高優先順序的,限制低優先順序的;

(3)改造原始碼,實現topic維度限流以及對topic分割槽的禁寫功能;

(4)改造原始碼,實現使用者、broker、磁碟、topic等維度組合精準限流;

三、kafka發展趨勢

3.1 Kafka社群迭代計劃

3.2 逐步棄用ZooKeeper(KIP-500)

3.3 controller與broker分離,引入raft協議作為controller的仲裁機制(KIP-630)

3.4 分層儲存(KIP-405)

3.5 可以減少topic分割槽(KIP-694)

3.6 MirrorMaker2精確一次(KIP-656)

3.7 下載與各版本特性說明

3.8 Kafka所有KIP地址

四、如何貢獻社群

4.1 哪些點可以貢獻

http://kafka.apache.org/contributing

4.2 wiki貢獻地址

https://cwiki.apache.org/confluence/dashboard.action#all-updates

4.3 issues地址

1)https://issues.apache.org/jira/projects/KAFKA/issues/KAFKA-10444?filter=allopenissues

2)https://issues.apache.org/jira/secure/BrowseProjects.jspa?selectedCategory=all

4.4 主要committers

http://kafka.apache.org/committers

作者:vivo網際網路伺服器團隊-Yang Yijun

相關文章