1.首先來說一下我們?yōu)槭裁匆褂孟⑾到y(tǒng)
在沒有使用消息系統(tǒng)之前旅挤,許多傳統(tǒng)的系統(tǒng)業(yè)務(wù)對于消息的處理一般會采用串行方式或者并行方法;
例如伞鲫,你去網(wǎng)站注冊一個賬號粘茄,下面是串行跟并行的處理方式。
串行方式:
用戶注冊例子:用戶主責秕脓,將注冊信息記錄到數(shù)據(jù)庫后柒瓣,發(fā)送注冊消息郵件,再發(fā)送注冊短信驗證吠架,每個過程小號50毫秒芙贫,一共就需要150毫秒
并行方式:
與串行不同的就是,在數(shù)據(jù)庫記錄完注冊信息之后傍药,發(fā)送消息跟發(fā)送郵件的動作同步完成磺平,縮短了用戶的等待時間:
消息系統(tǒng):
消息系統(tǒng)負責將數(shù)據(jù)從一個應(yīng)用程序傳送到另一個應(yīng)用程序,因此應(yīng)用程序可以專注于數(shù)據(jù)拐辽,但是不必擔心 如何共享它拣挪。分布式消息系統(tǒng)基于可靠的消息隊列的概念。消息在客戶端應(yīng)用程序和消息傳遞系統(tǒng)之間的異步排隊俱诸。
2.消息系統(tǒng)的分類:
點對點:
主要采用的隊列的方式進行消息傳遞菠劝,如A->B ,A生產(chǎn)B消費睁搭,當B消費的隊列中的數(shù)據(jù)赶诊,那么隊列的數(shù)據(jù)就會被消費,也就是刪除掉介袜。
發(fā)布-訂閱:
主要有三大組件:
主題:一個消息的分類甫何,假如有一類的消息全部都是訂單,一類全部都是關(guān)于用戶的遇伞,一類全部都是關(guān)于訂單的辙喂。那么就根據(jù)這些創(chuàng)建不同的主題存放不同的東西。
發(fā)布者:將消息通過主動推送的方式推送給消息系統(tǒng)
訂閱者:可以采用拉,推的方式從消息系統(tǒng)中獲取數(shù)據(jù)
3.kafka的應(yīng)用場景以及架構(gòu)
apache kafka是一個分布式發(fā)布-訂閱消息系統(tǒng)和一個強大的消息隊列巍耗,使用scala語言編寫是一個分布式秋麸,分區(qū)的,多副本的炬太,多訂閱者的日志系統(tǒng)灸蟆,可以用于搜索日志,監(jiān)控日志亲族,訪問日志等炒考。
kafka架構(gòu)圖:
Prodecers:生產(chǎn)者,主要用于生產(chǎn)數(shù)據(jù)霎迫。之后保存到kafka集群斋枢。
Consumers:集群的消費者,從集群中對生產(chǎn)者生產(chǎn)的數(shù)據(jù)進行消費知给。
Connectors:允許構(gòu)建和運行可重用的生產(chǎn)者或者消費者瓤帚,能夠把kafka主題連接到現(xiàn)有的應(yīng)用程序或數(shù)據(jù)系統(tǒng)。例如:一個連 接到關(guān)系數(shù)據(jù)庫的連接器可能會獲取每個表的變化涩赢。
Stream processors:允許應(yīng)用程序充當流處理器(stream processor)戈次,從一個或者多個主題獲取輸入流,并生產(chǎn)一個輸出流到一個或 者多個主題筒扒,能夠有效的變化輸入流為輸出流怯邪。
相關(guān)術(shù)語說明:
Broker:kafka集群中包含一個或者多個服務(wù)實例,這種服務(wù)實例被稱為Broker
Topic:每條發(fā)布到kafka集群的消息都有一個類別花墩,這個類別就叫做Topic
Partition:Partition是一個物理上的概念擎颖,每個Topic包含一個或者多個Partition (分區(qū))
Producer:負責發(fā)布消息到kafka的Broker中。
Consumer:消息消費者,向kafka的broker中讀取消息的客戶端
Consumer Group:每一個Consumer屬于一個特定的Consumer Group(可以為每個Consumer指定 groupName)
架構(gòu)關(guān)系圖:
流程介紹:Zookeeper是一個分布式的观游,開放源碼的,用戶分布式的協(xié)調(diào)服務(wù)驮俗,生產(chǎn)者push數(shù)據(jù)到集群懂缕,消費者通過pull進行拉取,但不管是生產(chǎn)者還是消費者的動作都需要zookeeper的管理王凑。他的作用就是搪柑,生產(chǎn)者push數(shù)據(jù)到kafka集群,就必須要找到kafka集群的節(jié)點在哪里索烹,這些都是通過zookeeper去尋找的工碾。消費者消費哪一條數(shù)據(jù),也需要zookeeper的支持百姓,從zookeeper獲得offset渊额,offset記錄上一次消費的數(shù)據(jù)消費到哪里,這樣就可以接著下一條數(shù)據(jù)進行消費。
kafka Partition o?set
o?set是一個long類型數(shù)字旬迹,它唯一標識了一條消息火惊,消費者通過(o?set,partition奔垦,topic)跟蹤記錄屹耐。
任何發(fā)布到此partition的消息都會被直接追加到log文件的尾部,每條消息在文件中的位置稱為o?set(偏移量)椿猎。 記錄到上一次消費的位置惶岭,之后跟蹤到下一次接著上一次消費的位置進行繼續(xù)消費。保證了每次都從下一條開始消費犯眠,不會重復消費也不會丟失消費按灶。
kafka為什么那么快主要從下面4個方面進行理解:
1.kafka的儲存設(shè)計方面
在Kafka文件存儲中,同一個topic下有多個不同partition阔逼,每個partition為一個目錄兆衅,partiton命名規(guī)則為topic名稱+有序序號,第一個partiton序號從0開始嗜浮,序號最大值為partitions數(shù)量減1羡亩。每個partition(目錄)被平均分配到多個大小相等segment(段)數(shù)據(jù)文件中。但每個段segment file消息數(shù)量不一定相等危融,通過多個小文件段畏铆,就容易定期清除或刪除已經(jīng)消費完文件,減少磁盤占用吉殃。每一個sgement又包含了index文件和log文件辞居,可以快速定位數(shù)據(jù),通過index元數(shù)據(jù)全部映射到memory蛋勺,可以避免segment file的IO磁盤操作瓦灶。
2.利用Page cache+mmap
page cache用于緩存文件的頁數(shù)據(jù),頁是邏輯上的概念抱完,因此page cache是與文件系統(tǒng)同級的贼陶;他的作用就是加速數(shù)據(jù)的IO,寫數(shù)據(jù)的時候首先寫入緩存巧娱,將寫入的頁進行標記為dirty碉怔,之后向外部存儲flush;讀數(shù)據(jù)的時候就先讀取緩存禁添,沒有讀取到再去外部存儲讀取撮胧。page cache中的每個文件都是一棵基數(shù)樹,樹的每個節(jié)點都是一個頁老翘。根據(jù)文件內(nèi)的偏移量就可以快速定位到所在的頁芹啥。
為什么kafka要使用page cache 進行儲存管理
1.JVM中一切都是對象锻离,數(shù)據(jù)的對象儲存會浪費空間
2.使用JVM管理,會降低吞吐量
3叁征,如果系統(tǒng)程序崩潰管理的數(shù)據(jù)就會丟失纳账,造成嚴重后果
mmap即是Memory Mapped Files 內(nèi)存文件映射,可以把物理上的磁盤文件跟page cache進行映射捺疼,讓進程可以讀寫內(nèi)存疏虫,有助于數(shù)據(jù)讀寫與磁盤的交互
3.kafka的批量壓縮設(shè)計
在大企業(yè)中,數(shù)據(jù)的流動時極快的啤呼,對于消息隊列很多的情況加卧秘,系統(tǒng)要面臨的問題就是不僅僅是磁盤的IO,更多的是網(wǎng)絡(luò)的IO官扣。所以消息的壓縮對于kafka的性能來說就顯得尤其重要翅敌。
Kafka 中,壓縮可能發(fā)生在兩個地方:生產(chǎn)者端和 Broker 端惕蹄,kafka采用批量壓縮的方式蚯涮,而不是采用單個消息隊列壓縮。 如果對每一個消息都進行壓縮卖陵,壓縮的效率就會大大降低遭顶。kafka支持很多種壓縮方式,允許使用遞歸的消息集合泪蔫。
4.kafka的消息讀寫過程
1.Producer根據(jù)zookeeper連接到或者的broker棒旗,從zookeeper節(jié)點找到該partition的leader
2.producer把需要發(fā)送的消息發(fā)給該leader,leader把消息寫入到log撩荣,follows從leader拉取消息铣揉,寫入到本地的log之后向leader發(fā)送ACK,leader收到后向producer發(fā)送ACK
生產(chǎn)者把經(jīng)過批量壓縮的數(shù)據(jù)發(fā)送給broker之后餐曹,beocker就通過函數(shù)映射壓縮文件的地址到內(nèi)存逛拱,之后就可以根據(jù)這個函數(shù)進行寫入的操作,寫入的時候會直接進入到PageCache台猴,之火由os的線程異步刷新到磁盤橘券,達到一次性能優(yōu)化。
kafka在讀取數(shù)據(jù)的時候卿吐,會判斷數(shù)據(jù)是否存在于page cache,如果存在的話就會直接從page cache中消費锋华,所以消費實時數(shù)據(jù)的速度就會快很多嗡官。
5.ZeroCopy
在linux中有兩個上下文,分別是內(nèi)核態(tài)跟用戶態(tài)毯焕,我們將一個File讀取并發(fā)送出去需要經(jīng)歷4次Copy:
1.調(diào)用read,將文件拷貝到了kernel內(nèi)核態(tài)
2.CPU控制 kernel態(tài)的數(shù)據(jù)copy到用戶態(tài)
3.調(diào)用write時衍腥,user態(tài)下的內(nèi)容會copy到內(nèi)核態(tài)的socket的buffer中
4.最后將內(nèi)核態(tài)socket buffer的數(shù)據(jù)copy到網(wǎng)卡設(shè)備中傳送
缺點就是增加了上下文切換磺樱、浪費了2次無效拷貝
ZeroCopy技術(shù):
請求kernel直接把disk的data傳輸給socket,而不是通過應(yīng)用程序傳輸婆咸。Zero copy大大提高了應(yīng)用程序的性能竹捉,減少不必要的內(nèi)核緩沖區(qū)跟用戶緩沖區(qū)間的拷貝,從而減少CPU的開銷和減少了kernel和user模式的上下文切換尚骄,達到性能的提升
對應(yīng)零貝技術(shù)有mmap及sendfile:
1.mmap:小文件傳輸快
2.sendfile:大文件傳輸比mmap快
應(yīng)用:Kafka块差、Netty、RocketMQ等消息隊列都采用了零拷貝技術(shù)