kafka實踐

一、硬件考量

1.1、內存
不建議爲kafka分配超過5g的heap,因爲會消耗28-30g的文件系統緩存,而是考慮爲kafka的讀寫預留充足的buffer。Buffer大小的快速計算方法是平均磁盤寫入數量的30倍。推薦使用64GB及以上內存的服務器,低於32GB內存的機器可能會適得其反,導致不斷依賴堆積機器來應付需求增長。(我們在生產環境使用的機器是64G內存的,但也看到LinkedIn用了大量28G內存的服務器。)
1.2、CPU
kafka不算是CPU消耗型服務,在主頻和CPU核數之間,選擇後者,將會獲得多核帶來的更好的併發處理性能。
1.3、磁盤
毋庸置疑,RAID是優先推薦的,它在底層實現了物理磁盤的負載均衡和冗餘,雖然會犧牲一些磁盤空間和寫入性能。更進一步,我們推薦在配置中使用多目錄,每個目錄掛在在不同的磁盤(或者RAID)上。需要注意的是,NAS是不可取的,無論供應商如何吹噓他們的NAS的卓越性能。另外,我們經常看到用戶諮詢kafka是否一定要採用SSD,答案是沒有必要。
1.4網絡
分佈式系統中,網絡的速度和可靠性異常重要,千兆甚至萬兆網絡現在應該成爲數據中心的標配。避免kafka集羣出現跨數據中心的情況,更要避免有很大的物理空間跨度,尤其中國還有詭異的聯通電信問題。kafka集羣中各個節點地位均等,一旦因爲延時導致分佈式集羣不穩定,排錯尤其困難。
1.5、文件系
ext4是最佳選擇。
1.6、其它
在硬件越來越強大和雲計算如火如荼的今天,你需要在超高配置的服務器和IaaS供應商的數百個虛擬機之間做取捨。我們建議使用中等配置的服務器,因爲集羣規模越大,單臺超高配置的服務器運行的節點越多,集羣穩定性隨之下降,複雜度則會上升。
二、JVM的考慮
對於java應用,jvm和gc是繞不過去的坎。實踐表明,官方JDK1.7u51會是一個不錯的選擇,配合以G1來做垃圾回收。推薦配置可參考:
-Xms4g -Xmx4g -XX:PermSize=48m -XX:MaxPermSize=48m -XX:+UseG1GC-XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35
注:kafka版本更新會帶來變化。請隨時關注。我們現在的版本是kafka_2.11-0.8.2.1
三、File descriptors
kafka會使用大量文件和網絡socket,所以,我們需要把file descriptors的默認配置改爲100000。修改方法如下:
#vi /etc/sysctl.conf
fs.file-max = 32000
#vi /etc/security/limits.conf
yourusersoftnofile10000
youruserhardnofile30000
四、關鍵配置項解讀
儘管默認配置已經很不錯,但出於性能和實際集羣部署情況,我們還是需要講解一些重要的配置項。除此之外,如果對某個默認參數存在質疑,在詳細瞭解改參數的作用前,建議採用默認配置。
4.1、zookeeper.connect
必配參數,建議在kafka集羣的每天機器都配置所有zk。
4.2、broker.id
必配參數。集羣節點的標示符,不得重複。取值範圍0~n。
4.3、log.dirs
建議參照文章前面描述的磁盤配置,不要使用默認的“/tmp/kafka-logs”
4.4、advertised.host.name
註冊到zk供用戶使用的主機名。內網環境通常無需配置,而IaaS一般需要配置爲公網地址。默認爲“host.name”,可以通過java.net.InetAddress.getCanonicalHostName()接口獲取該值。
4.5、advertised.port
註冊到zk供用戶使用的服務端口,通常在IaaS環境需要額外配置。
4.6、num.partitions
自動創建topic的默認partition數量。默認是1,爲了獲得更好的性能,建議修改爲更大。最優取值參考後文。
4.7、default.replication.factor
自動創建topic的默認副本數量,官方建議修改爲2;但通常一個副本就足夠了。
4.8、min.insync.replicas
ISR提交生成者請求的最小副本數。
4.9、unclean.leader.election.enable
是否允許不具備ISR資格的replicas選舉爲leader作爲不得已的措施,甚至不惜犧牲部分數據。默認允許。建議允許。數據異常重要的情況例外。
4.10、controlled.shutdown.enable
在kafka收到stop命令或者異常終止時,允許自動同步數據。建議開啓。
五、動態調整配置
大部分kafka配置是寫死在properties文件裏的。然而,許多關於topic的參數我們可以動態調配,kafka-topic.sh工具提供了該功能,更改將一直生效直到服務器重啓。可以調整的參數如下:
unclean.leader.election.enable:不嚴格的leader選舉,有助於集羣健壯,但是存在數據丟失風險。
min.insync.replicas:如果同步狀態的副本小於該值,服務器將不再接受request.required.acks爲-1或all的寫入請求。
max.message.bytes:單條消息的最大長度。如果修改了該值,那麼replica.fetch.max.bytes和消費者的fetch.message.max.bytes也要跟着修改。
cleanup.policy:生命週期終結數據的處理,默認刪除。
flush.messages:強制刷新寫入的最大緩存消息數。
flust.ms:強制刷新寫入的最大等待時長。
還有segment.bytes、segment.ms、retention.bytes、retention.ms和segment.jitter.ms。詳見官方解釋。
六、性能優化技巧
6.1、配置合適的partitons數量。
這似乎是kafka新手必問得問題。首先,我們必須理解,partiton是kafka的並行單元。從producer和broker的視角看,向不同的partition寫入是完全並行的;而對於consumer,併發數完全取決於partition的數量,即,如果consumer數量大於partition數量,則必有consumer閒置。所以,我們可以認爲kafka的吞吐與partition時線性關係。partition的數量要根據吞吐來推斷,假定p代表生產者寫入單個partition的最大吞吐,c代表消費者從單個partition消費的最大吞吐,我們的目標吞吐是t,那麼partition的數量應該是t/p和t/c中較大的那一個。實際情況中,p的影響因素有批處理的規模,壓縮算法,確認機制和副本數等,然而,多次benchmark的結果表明,單個partition的最大寫入吞吐在10MB/sec左右;c的影響因素是邏輯算法,需要在不同場景下實測得出。
這個結論似乎太書生氣和不實用。我們通常建議partition的數量一定要大於等於消費者的數量來實現最大併發。官方曾測試過1萬個partition的情況,所以不需要太擔心partition過多的問題。下面的知識會有助於讀者在生產環境做出最佳的選擇:
a、一個partition就是一個存儲kafka-log的目錄。
b、一個partition只能寄宿在一個broker上。
c、單個partition是可以實現消息的順序寫入的。
d、單個partition只能被單個消費者進程消費,與該消費者所屬於的消費組無關。這樣做,有助於實現順序消費。
e、單個消費者進程可同時消費多個partition,即partition限制了消費端的併發能力。
f、partition越多則file和memory消耗越大,要在服務器承受服務器設置。
g、每個partition信息都存在所有的zk節點中。
h、partition越多則失敗選舉耗時越長。
k、offset是對每個partition而言的,partition越多,查詢offset就越耗時。
i、partition的數量是可以動態增加的(只能加不能減)。
我們建議的做法是,如果是3個broker的集羣,有5個消費者,那麼建議partition的數量是15,也就是broker和consumer數量的最小公倍數。當然,也可以是一個大於消費者的broker數量的倍數,比如6或者9,還請讀者自行根據實際環境裁定。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章