Kafka 0.9.0 文檔翻譯-1、Getting Started

kafka目前應用比較廣泛,中小規模的公司都把kafka當做大數據平臺的數據總線,成爲很多流計算系統的輸入源,比如storm,flink,spark-streaming等。同時各種應用的日誌做離線處理的時候,架構上傾向於使用kafka作爲消息管道,日誌push到kafka,然後使用分佈式task將數據寫入hdfs等,諸如此類的應用還有很多,這些正說明kafka有不錯的高吞吐低延時性能。一些大的公司bat可能有自己的更加定製化的消息系統,比如阿里的metaq等。一直以來,沒能系統地研究一下這些消息系統,現在打算先把kafka文檔翻譯一遍,然後看下kafka爲什麼這麼受歡迎。


首先看下getting started:

kafka是一個分佈式的,數據可分區的,分區有多個副本的消息系統,它很特別,特別在哪?

首先,review一下消息系統幾個基本的語義:

1、消息怎麼區分,topics,不同的topic代表不同類型的日誌,這個就是tt(timetunnel)裏的日誌的概念

2、生產者  寫消息到消息系統的角色

3、消費者  從消息系統訂閱消息的角色

4、消息系統的服務端,由1個或者多個角色構成,這些角色叫做broker


生產、消費關係圖:



我們之前接觸的分佈式系統,一般都有一些rpc協議,比如thrift,protobuffer,或者hadoop、hbase裏面用的那套rpc框架等,kafka沒用這些,控制流或者數據流都是最簡單高效的tcp協議,serversocket,socket那一套。rpc框架可以提高編程效率,更傾向於做高併發的控制流通信。

kafka 大家都知道是scala編寫的核心,但是它也支持java以及其他很多語言的客戶端。


下面再講講kafka的topics的概念

topic其實是一個邏輯概念,對於用戶來說,我需要用你kafka傳輸數據的時候,訂閱數據的時候,我需要知道一個topic,我的數據因爲有topic不至於跟其他日誌混淆。

在kafka裏,topic的物理意義就是指存儲數據的目錄名字啊,之類的,不同topic的數據放到不同的目錄裏。tt的不同日誌其實對應的是多個queue,這些queue對應的是hbase表的region,不同topic對應不同的一組region,即消息系統的topic其實就是底層存儲系統上,獨立的存儲單元的集合。

Topics and Logs

topic下面是queue的語義,kafka裏成爲partition,什麼是queue、partition?我們可以統一叫做分區,分區有自己的特點:有序的,數據不可變的消息集合,臥槽,說的太學術了,直接點就是追加寫的一個文件,只能追加,不許改寫過的數據,這個分區內是有序的,分區內每條消息都有個點位,叫做offset,即一條消息在這個分區內的唯一的位置標號,如果這個分區消息是寫在一個文件中的,你可以理解成一行在這個文件中的偏移量,讀的時候只要seek到這個位置,就能讀到這一行數據。

kafka接收讀寫,一個個的topic,每個topic又有多個分區,這些數據是持久化存儲的,一般保存3天,這個時間你可以配置的,過期的數據,kafka會安排線程清理掉

前面提到分區的點位,這個點位是最關鍵的信息,比如你再storm裏處理數據,對於ack_failed的數據重發,你可能需要replay,重放那些失敗的數據,怎麼重放?就是重新調整點位,重新從消息系統拉取數據。

一個文件順序追加,數據就在那躺着,你想讀哪些數據,你只要讓點位動一動就行了,一般來說這個點位包含時間信息,我想讀15點的數據,就直接操作點位就行了。

點位系統其實是一個比較複雜的系統,一個topic的每個分區都有自己的點位,怎麼衡量整個topic的點位,一般是取消費最慢的那個分區的點位當做整個分區的點位,點位怎麼存儲,怎麼計算,不簡單,做一個好的點位系統其實很複雜。kafka避開了點位系統,自己不管,讓消費者自己控制,你可以把點位存儲在zk上面,也可以存儲到mysql等等。

實現,點位爲什麼不好做,首先,服務端需要記住每個訂閱,即給每個訂閱分配一個subid,我要記住全部subid的點位。

kafka省心啊,不做點位,誰訂閱可以,自己記住你的點位,別來找我要,這樣的話,服務端就省去了很多狀態管理的開銷。

分區的作用不必細說了,主要是解決併發的問題,以及分佈式數據管理的問題,即擴展的問題。比如你的數據量很大,我沒有分區的話,就相當於只有一個分區,這個分區追加寫,讀的時候只能單線程讀啊,還有就是追加寫,我如果多臺機器管理同一個“分區”,怎麼追加寫,怎麼跨機器讀,顯然不合理,因此多分區是必然的。

下面再看看kafka的分佈式化特點。所謂分佈式化其實就是管理的分區的分佈式,你不把分區放到多臺機器上,網卡能受了,tps,qps也滿足不了業務需求,所以一個topic的數據分區肯定要分散到不同的機器上,就跟hdfs的塊一樣的道理,同樣的,爲了提供更好的併發性和容錯,讀寫儘量散列到不同的機器上,那麼最好每個分區還有多個副本,這樣的話,我讀一個分區,到A機器也行,到B機器也行。當然這樣做就得考慮副本數據一致性,副本之間的數據複製等,或者雙寫。

其實說到這,感覺消息系統跟分佈式數據庫有很多類似的地方,消息系統是順序寫,連續讀,因爲有點位也可以做基於點位的“隨機讀”,數據庫也是支持隨機讀的,數據也要分片,做副本,同時副本之間要做數據複製,一致性等時,就需要選主,即一個數據分多個副本之間要有一個leader,所有的讀寫請求都會交給這個leader。leader掛了,剩下的follower裏再選出來一個當leader。leader選舉過程當中可能會有短暫的數據不可用,因此副本的leader選舉時間要儘可能短。基於這種設計,消息系統或者分佈式數據庫就要保證每臺機器上都有leader,儘量均勻,才能做到負載均衡。

kafka的server就是broker,broker說白了就是數據分區管理器,當然本身也做存儲。

tt因爲數據寫到hbase,broker成了數據轉發,代理讀取的一個真正的broker,相對kafka,少了很多存儲的設計。客戶端發消息過來。我要先持久化了,寫到commit-log(redolog)我才告訴你ok了,tt寫hbase,不用管這些,因爲hbase寫到hlog ok了纔會返回ok,tt利用hbase的hlog做了redolog這一層。

再來看看生產者:

生產者控制消息寫入哪個topic,以及怎麼寫到各個分區,比如一個topic有多個分區,我可以寫到一個分區,也可以輪詢地往各個topic平均寫,當然也可以按消息的字段做hash寫,都是可以的。說到這裏,如果你希望用kafka做保序的處理,那麼只能在一個分區內保序,跨多個分區的是沒辦法有序的。這是業界難題,因爲不同分區可能在不同機器上,你要做到多個分區的數據連續,那麼你需要做分佈式的協調,或者類似分佈式事務,提高了分區一致性,那麼必然可用性和分區擴展能力就會下降。

一般來說,消息系統其實有2種語義模型,一種是queuing的語義,另一種是發佈訂閱模型。什麼叫queuing?

就是消息系統中的一個topic有多個queue,那麼,每一個queue的一條消息只能發給一個消費者。這種相當於消息的負載均衡,即被瓜分,如果你把一個topic看成完整的一篇文章,那麼每個消費者只讀到片段,他們的數據合起來纔是一個完整的文章我們更熟悉發佈訂閱模型,一個topic可以同時由多個消費者同時訂閱,就好像一個文件,可以有多個reader同時讀一樣,只要讀者自己記住自己讀的位置就行了,讀者之間互不干擾,這種模型有人說叫做廣播,其實不太合理,因爲消費者一般是拉的模型。

kafka 提供了一個消費者抽象模型叫做消費組,即consumer group。同時支持上述兩種語義,這是啥意思?

幾個消費者有一個共同的消費組的名字,比如a、b、c三個消費者,起個消費組名group3,這三個消費者可以不在同一個進程中,不在同一臺機器上,那麼這三個消費者可以訂閱同一個topic,這個topic裏面的一條消息,會發送給三個消費者的其中一個,也就是說這個topic的數據被三個瓜分了,而不是複製了三份,每個消費者都消費了完整的topic數據。

即group3裏面的消費者,可以按照某種算法,瓜分一個完整的topic。比如我的請求消息都發到這個topic,消費組的消費者是web服務器,那麼kafka的這種功能,相當於變成了負載均衡設備。

也就說所謂的同時支持queue和發佈訂閱模型,是指正常情況下是發佈訂閱模型,加入consumer group,相當於能支持queue模型了。

tt的日誌有多個queue,即partition,訂閱的時候,通過sdk可以指定消費哪幾個partition的數據,即單個consumer可以消費單個或者多個partition的數據,但是不能多個消費者消費同一個partition的數據(使用同一個subid)因爲這樣,系統沒辦法記錄點位。那麼kafka是怎麼做的呢,因爲consumer也不記點位,那麼kafka是不是不允許多個consumer消費同一個partition的數據呢,不是,它利用的是消費組的概念,這個消費組裏的消費者,可以分別消費這個topic的某一個partition。比如一個topic有16個partition,那麼這個消費組裏最多有16個consumer,每個consumer分別消費1個partition。也就是說這個consumer group id相當於tt裏的subid,但是tt裏其實分別消費1個partition的consumer可以不在1個進程裏,不在1臺機器上。

文檔也提到這種分區方式更方便保證有序,如果數據沒有分區,那麼當你replay的時候,雖然數據還是按照相同的數據讀出來的,但是數據一般都是併發處理的,那麼讀出來的數據怎麼保證跟上次分發給處理線程的一模一樣?還是這種指定分區的方式更方便實現,即讓數據源更加細粒度,更方便控制。

kafka保證:第一,數據單分區寫進來什麼順序,就順序追加到存儲介質中,並且點位也能體現消息的寫入先後順序,第二,分區副本balance存放,你的一個分區有N個副本,那麼掛N-1臺broker,你的副本數據不會丟。第二點也意味着,副本數據的放置策略是儘可能地打散。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章