首先kafka的throughput
很牛逼,參考:http://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines
接着主要談一下,Kafka的可靠性問題,有哪些機會可能丟數據?
從producer,broker,consumer的角度,分別看看
a. Producer到broker
把request.required.acks設為1,丟會重發,丟的概率很小
b. Broker
b.1 對於broker,落盤的數據,除非磁盤壞了,不會丟的
b.2 對於內存中沒有flush的數據,broker重啟會丟
可以通過log.flush.interval.messages和log.flush.interval.ms來配置flush間隔,interval大丟的數據多些,小會影響性能
但在0.8版本,可以通過replica機制保證數據不丟,代價就是需要更多資源,尤其是磁盤資源,kafka當前支持GZip和Snappy壓縮,來緩解這個問題
是否使用replica取決於在可靠性和資源代價之間的balance
c. Consumer
和其他的平台不同的是,其實Kafka真正比較復雜的是consumer,Kafka有兩種consumer
c.1 High-level consumer
這個使用比較簡單,已經封裝了對partition和offset的管理,默認是會定期自動commit offset,這樣可能會丟數據的,因為consumer可能拿到數據沒有處理完crash
之前我們在0.7上是使用這個接口的,為了保證不丟數據,把自動commit關掉,consumer處理完所有數據,再手動commit,這樣丟數據的概率比較小
對於storm,沒法這樣做,因為spout是會預讀大量數據的,當然只要spout線程不crash,也是可以保證這些數據基本不會丟失(通過storm的acker機制)
但如果spout線程crash,就會丟數據
所以High-level接口的特點,就是簡單,但是對kafka的控制不夠靈活
c.2 Simple consumer,low-level
這套接口比較復雜的,你必須要考慮很多事情,優點就是對Kafka可以有完全的控制
You must keep track of the offsets in your application to know where you left off consuming.
You must figure out which Broker is the lead Broker for a topic and partition
You must handle Broker leader changes
在考慮如何將storm和kafka結合的時候,有一些開源的庫,基於high-level和low-level接口的都有
我比較了一下,還是kafka官方列的storm-kafka-0.8-plus比較靠譜些
這個庫是基於simple consumer接口實現的,看着挺復雜,所以我先讀了遍源碼,收獲挺大,除了發現我自己代碼的問題,還學到些寫storm應用的技巧呵呵
這個庫會自己管理spout線程和partition之間的對應關系和每個partition上的已消費的offset(定期寫到zk)
並且只有當這個offset被storm ack后,即成功處理后,才會被更新到zk,所以基本是可以保證數據不丟的
即使spout線程crash,重啟后還是可以從zk中讀到對應的offset
So, 結論就是kafka和storm的結合可靠性還是可以的,你真心不想丟數據,還是可以做到的
Kafka只是能保證at-least once邏輯,即數據是可能重復的,這個在應用上需要可以容忍
當然通過Storm transaction也是可以保證only once邏輯的,但是代價比較大,后面如果有這樣的需求可以繼續深入調研一下
對於kafka consumer,一般情況下推薦使用high-level接口,最好不要直接使用low-level,太麻煩
當前其實Kafka對consumer的設計不太到位,high-level太不靈活,low-level又太難用,缺乏一個medium-level
所以在0.9中consumer會被重新design,https://cwiki.apache.org/confluence/display/KAFKA/Consumer+Client+Re-Design