Metaq原理與應用

Metaq原理與應用

(針對2.X版本)

 

誓嘉 蘭生

2013/1/13

 

目錄

1       前言

2       特別說明

3       專業術語

4       消息系統需要解決哪些問題?

4.1        Publish/Subscribe

4.2        Message Order

4.3        消息過濾

4.4       Message Priority

4.5        Exactly And Only Once

4.6       回溯消費

4.7        Message Persistence

4.8       Broker的Buffer滿了怎麼辦?

4.9       消息堆積

4.10      Message Reliablity

4.11       分佈式事務

5       消息系統實現

5.1         典型實現

5.2        Apache Kafka實現

5.3        Push和Pull

6       Metaq Overview

6.1        Metaq與Apache Kafka的區別

6.2        Metaq是什麼?

7       Metaq主要功能點實現細節

7.1         單機如何實現1萬以上個隊列

7.2        刷盤策略

7.2.1          異步刷盤

7.2.2         同步刷盤

7.3        服務器消息過濾

7.3.1          按照Message Type過濾

7.3.2         按照Message Tag過濾

7.4        消息查詢

7.4.1         按照MessageId查詢消息

7.4.2         按照時間查詢隊列Offset

7.4.3         按照Message Key查詢消息

7.5        HA,同步雙寫

7.6        HA,異步複製

7.7        單個JVM進程也能利用機器超大內存

7.8        消息堆積問題解決辦法

8       Metaq開發過程中遇到了哪些問題?

9       Metaq目前有哪些地方需要改進?

10     Metaq的幾個設計原則

附錄A 參考文檔、規範

 

 

 

1   前言

本文檔旨在描述Metaq的多個關鍵特性的實現原理,並對Messaging System遇到的各種問題進行總結,闡述Metaq如何解決這些問題。文中主要引用了JMS規範與CORBA Notification規範,規範爲我們設計系統指明瞭方向,但是仍有不少問題規範沒有提及,對於消息系統又至關重要。Metaq並不遵循任何規範,但是參考了各種規範與其他產品的優點。

2   特別說明

(1).     關於產品名稱

Metamorphosis,取自Kafka短篇代表作《變形記》,是卡氏藝術上的最高成就,被認爲是20世紀最偉大的小說作品之一。創作於1912年,發表於1915年。

爲方便讀寫,又因爲她是一個完全的隊列模型消息中間件,所以從2.0版本開始,產品名稱由“Metamorphosis”改爲“Metaq”。

淘寶內部都這樣讀:[maɪtʌkjuː]

(2).    Metamorphosis 1.x版本由Java社區著名的莊曉丹([email protected])開發,可參見以下資料

http://www.iteye.com/magazines/107

http://github.com/killme2008/Metamorphosis

(3).    本文着重介紹Metaq 2.x版本相關,2.x版本現在已經開源,有任何問題可以通過開源網站聯繫我們。

http://metaq.taobao.org/

3          專業術語

n  Producer

消息生產者,負責產生消息,一般由業務系統負責產生消息。

n  Consumer

消息消費者,負責消費消息,一般是後臺系統負責異步消費。

n  Consumer Group

一類Consumer的集合名稱,這類Consumer通常消費一類消息,且消費邏輯一致。

n  Broker

消息中轉角色,負責存儲消息,轉發消息,一般也稱爲Server。在JMS規範中稱爲Provider。

n  廣播消費

一條消息被多個Consumer消費,即使這些Consumer屬於同一個Consumer Group,消息也會被Consumer Group中的每個Consumer都消費一次。

在CORBA Notification規範中,消費方式都屬於廣播消費。

n  集羣消費

一個Consumer Group中的Consumer實例平均分攤消費消息,類似於JMS規範中的Point-to-Point Messaging

特點如下:

u  Each message has only one consumer.

u  A sender and a receiver of a message have no timing dependencies. The receiver can fetch the message whether or not it was running when the client sent the message.

u  The receiver acknowledges the successful processing of a message.

n  主動消費

Consumer主動向Broker發起獲取消息請求,控制權完全在於Consumer應用。

類似於JMS規範中描述的Synchronously方式消費

n  被動消費

Consumer註冊一個Callback接口,由Metaq後臺自動從Broker接收消息,並回調Callback接口。

類似於JMS規範中的描述的Asynchronously方式消費

n  順序消息

消費消息的順序要同發送消息的順序一致,在Metaq中,主要指的是局部順序,即一類消息爲滿足順序性,必須Producer單線程順序發送,且發送到同一個隊列,這樣Consumer就可以按照Producer發送的順序去消費消息。

n  普通順序消息

順序消息的一種,正常情況下可以保證完全的順序消息,但是一旦發生通信異常,Broker重啓,由於隊列總數發生變化,哈希取模後定位的隊列會變化,產生短暫的消息順序不一致。

n  嚴格順序消息

順序消息的一種,無論正常異常情況都能保證順序,但是犧牲了分佈式Failover特性。

n  Message Queue

在Metaq中,所有消息隊列都是持久化,長度無限的數據結構,所謂長度無限是指隊列中的每個存儲單元都是定長,訪問其中的存儲單元使用Offset來訪問,offset爲java long類型,64位,理論上在100年內不會溢出,所以認爲是長度無限,另外隊列中只保存最近幾天的數據,之前的數據會按照過期時間來刪除。

在Metaq2.x之前版本,隊列也稱爲“分區”,兩者描述的是一個概念。但是按照2.x的實現,使用隊列描述更合適。

n  Messaging System

消息中間件的統稱,但並不侷限於消息中間件,與消息傳輸相關的類似系統。

4         消息系統需要解決哪些問題?

本節闡述消息系統通常需要解決哪些問題,在解決這些問題當中會遇到什麼困難,Metaq是否可以解決,規範中如何定義這些問題。

4.1     Publish/Subscribe

發佈訂閱是消息系統的最基本功能,也是相對於傳統RPC通信而言。在此不再詳述。

4.2     Message Order

消息有序指的是一類消息消費時,能按照發送的順序來消費。例如:一個訂單產生了3條消息,分別是訂單創建,訂單付款,訂單完成。消費時,要按照這個順序消費纔能有意義。但是同時訂單之間是可以並行消費的。

Metaq可以嚴格的保證消息有序。

4.3     消息過濾

n  Broker端消息過濾

在Broker中,按照Consumer的要求做過濾,優點是減少了對於Consumer無用消息的網絡傳輸。

缺點是增加了Broker的負擔,實現相對複雜。

(1).     淘寶Notify支持多種過濾方式,包含直接按照消息類型過濾,靈活的語法表達式過濾,幾乎可以滿足最苛刻的過濾需求。

(2).    淘寶Metaq只支持按照簡單的消息類型過濾。

(3).    CORBA Notification規範中也支持靈活的語法表達式過濾。

n  Consumer端消息過濾

這種過濾方式可由應用完全自定義實現, 但是缺點是很多無用的消息要傳輸到Consumer端。

4.4     Message Priority

規範中描述的優先級是指在一個消息隊列中,每條消息都有不同的優先級,一般用整數來描述,優先級高的消息先投遞,如果消息完全在一個內存隊列中,那麼在投遞前可以按照優先級排序,令優先級高的先投遞。

由於Metaq所有消息都是持久化的,所以如果按照優先級來排序,開銷會非常大,因此Metaq沒有特意支持消息優先級,但是可以通過變通的方式實現類似功能,即單獨配置一個優先級高的隊列,和一個普通優先級的隊列, 將不同優先級發送到不同隊列即可。

4.5     Exactly And Only Once

消息是否重複性問題,JMS中有如下說明:

The JMS API can ensure that a message is delivered once and only once. Lower levels of reliability are available for applications that can afford to miss messages or to receive duplicate messages.

         我對於此特性的理解:

(1).     發送消息階段,不允許發送重複的消息。

(2).    消費消息階段,不允許消費重複的消息。

只有以上兩個條件都滿足情況下,才能認爲消息是“Exactly And Only Once”,而要實現以上兩點,在分佈式系統環境下,不可避免要產生巨大的開銷。所以Metaq爲了追求高性能,並不保證此特性,要求在業務上進行去重,也就是說消費消息要做到冪等性。Metaq雖然不能嚴格保證不重複,但是正常情況下都不會出現重複發送、消費情況,只有網絡異常,Consumer啓停等異常情況下會出現消息重複。

4.6     回溯消費

回溯消費是指Consumer已經消費成功的消息,由於業務上需求需要重新消費,要支持此功能,Broker在向Consumer投遞成功消息後,消息仍然需要保留。並且重新消費一般是按照時間維度,例如由於Consumer系統故障,恢復後需要重新消費1小時前的數據,那麼Broker要提供一種機制,可以按照時間維度來回退消費進度。

Metaq支持按照時間回溯消費,時間維度精確到毫秒。

4.7     Message Persistence

幾種持久化方式:

(1).     持久化到數據庫,例如Mysql。

(2).    持久化到KV存儲,例如levelDB、伯克利DB等KV存儲系統。

(3).    文件記錄形式持久化,例如Kafka,Metaq

(4).   對內存數據做一個持久化鏡像,例如beanstalkd,VisiNotify

(1)、(2)、(3)三種持久化方式都具有將內存隊列Buffer進行擴展的能力,(4)只是一個內存的鏡像,作用是當Broker掛掉重啓後仍然能將之前內存的數據恢復出來。

JMS與CORBA Notification規範沒有明確說明如何持久化,但是持久化部分的性能直接決定了整個消息系統的性能。

4.8     Broker的Buffer滿了怎麼辦?

Broker的Buffer通常指的是Broker中一個隊列的內存Buffer大小,這類Buffer通常大小有限,如果Buffer滿了以後怎麼辦?

下面是CORBA Notification規範中處理方式:

(1).     RejectNewEvents

拒絕新來的消息,向Producer返回RejectNewEvents錯誤碼。

(2).    按照特定策略丟棄已有消息

a)        AnyOrder - Any event may be discarded on overflow. This is the default setting for this

property.

b)        FifoOrder - The first event received will be the first discarded.

c)         LifoOrder - The last event received will be the first discarded.

d)        PriorityOrder - Events should be discarded in priority order, such that lower priority

events will be discarded before higher priority events.

e)        DeadlineOrder - Events should be discarded in the order of shortest expiry deadline first.

4.9     消息堆積

Messaging System的主要功能是異步解耦,還有個重要功能是擋住前端的數據洪峯,保證後端系統的穩定性,這就要求Messaging System具有一定的消息堆積能力,消息堆積分以下兩種情況:

(1).     消息堆積在內存Buffer,一旦超過內存Buffer,可以根據一定的丟棄策略來丟棄消息,如CORBA Notification規範中描述。適合能容忍丟棄消息的業務,這種情況消息的堆積能力主要在於內存Buffer大小,而且消息堆積後,性能下降不會太大,因爲內存中數據多少對於對外提供的訪問能力影響有限。

(2).    消息堆積到持久化存儲系統中,例如DB,KV存儲,文件記錄形式。

當消息不能在內存Cache命中時,要不可避免的訪問磁盤,會產生大量讀IO,讀IO的吞吐量直接決定了消息堆積後的訪問能力。

         評估消息堆積能力主要有以下四點:

(1).     消息能堆積多少條,多少字節?即消息的堆積容量。

(2).    消息堆積後,發消息的吞吐量大小,是否會受堆積影響?

(3).    消息堆積後,正常消費的Consumer是否會受影響?

(4).   消息堆積後,訪問堆積在磁盤的消息時,吞吐量有多大?

4.10        Message Reliablity

影響消息可靠性的幾種情況:

(1).     Broker正常關閉

(2).    Broker異常Crash

(3).    OS Crash

(4).   機器掉電,但是能立即恢復供電情況。

(5).    機器無法開機(可能是cpu、主板、內存等關鍵設備損壞)

(6).   磁盤設備損壞。

(1)、(2)、(3)、(4)四種情況都屬於硬件資源可立即恢復情況,Metaq在這四種情況下能保證消息不丟,或者丟失少量數據(依賴刷盤方式是同步還是異步)。

(5)、(6)屬於單點故障,且無法恢復,一旦發生,在此單點上的消息全部丟失。Metaq在這兩種情況下,通過異步複製,可保證99%的消息不丟,但是仍然會有極少量的消息可能丟失。未來版本會通過同步雙寫技術來完全避免單點,同步雙寫勢必會影響性能,適合對消息可靠性要求極高的場合,例如與Money相關的應用。

4.11        分佈式事務

已知的幾個分佈式事務規範,如XA,JTA等。其中XA規範被各大數據庫廠商廣泛支持,如Oracle,Mysql等。其中XA的TM實現佼佼者如Oracle Tuxedo,在金融、電信等領域被廣泛應用。

Metaq的存儲結構是文件記錄形式,通過Offset遞增進行訪問數據,缺乏KV存儲具有的update能力,如果要支持事務,必須引入類似於KV存儲的模塊纔可以。

Metaq目前不支持分佈式事務。

5   消息系統實現

5.1     典型實現

圖表 5‑1 Messaging System

         一個典型的消息系統實現一般分爲以下幾部分:

(1).     消息接收階段,收到消息後,存儲到存儲模塊,可以是本地KV存儲、文件記錄存儲、遠程DB、或其他存儲模式,然後將消息轉發至Dispatch處理流程。

(2).    消息分發階段,可能的操作包含消息過濾、分發到特定隊列或者Consumer Group隊列。

(3).    消息投遞階段,直接與Consumer進行通信,可以是主動投遞或者被動投遞。

5.2     Apache Kafka實現

Apache Kafka is a distributed publish-subscribe messaging system. It is designed to support the following.

n  Persistent messaging with O(1) disk structures that provide constant time performance even with many TB of stored messages.

n  High-throughput: even with very modest hardware Kafka can support hundreds of thousands of messages per second.

n  Explicit support for partitioning messages over Kafka servers and distributing consumption over a cluster of consumer machines while maintaining per-partition ordering semantics.

n  Support for parallel data load into Hadoop.

Kafka provides a publish-subscribe solution that can handle all activity stream data and processing on a consumer-scale web site. This kind of activity (page views, searches, and other user actions) are a key ingredient in many of the social feature on the modern web. This data is typically handled by "logging" and ad hoc log aggregation solutions due to the throughput requirements. This kind of ad hoc solution is a viable solution to providing logging data to an offline analysis system like Hadoop, but is very limiting for building real-time processing. Kafka aims to unify offline and online processing by providing a mechanism for parallel load into Hadoop as well as the ability to partition real-time consumption over a cluster of machines.

The use for activity stream processing makes Kafka comparable to Facebook's Scribe or Apache Flume (incubating), though the architecture and primitives are very different for these systems and make Kafka more comparable to a traditional messaging system. See our design page for more details.

以上文字摘自Apache Kafka官方網站,Kafka詳細資料,請參照官方網站,此文不再詳述。

http://kafka.apache.org/

Kafka是一個實現非常特別的消息系統,同我們的典型實現區別較大,跳出了各種消息系統規範定義的思維模式,按照我的理解總結如下:

(1).     Kafka的設計初衷消息是面向堆積需求的,讀優先級高於寫優先級,優先爲讀消息準備,所以無論堆積的消息多少,消費能力都很強。(前提是分區數在一定範圍內)

(2).    Kafka是面向廣播消費類型的,對廣播支持友好,並且也支持集羣消費模式。

(3).    很適合日誌收集類應用。

5.3     Push和Pull

push與pull是兩種數據通信方式,在Consumer從Broker獲取消息過程中會用到這兩種方式,區別如下:

 

Push

Pull

數據傳輸狀態

保存在Broker端

保存在Consumer端

傳輸失敗,重試

Broker需要維護每次傳輸狀態,遇到失敗情況需要重試

不需要

數據傳輸實時性

非常實時

(1).     默認的短輪詢方式實時性依賴pull間隔時間,間隔越大實時性越低。

(2).    長輪詢模式實時性與push一致。

流控機制

Broker需要依據Consumer的消費能力做流控。

Consumer可以根據自身消費能力決定是否去pull message。

 

6   Metaq Overview

6.1     Metaq與Apache Kafka的區別

表格 6‑1Metaq與Kafka區別

 

Apache Kafka

Taobao Metaq

分區數

分區過多會Load升高

單機1萬以上

SATA盤下性能

性能極低

由於PAGECACHE作用,及刷盤方式的不同,性能接近SAS盤

服務端消息過濾

不支持

支持

按照時間回溯

不支持

支持

Consumer訂閱實時性

1、數據落盤後,纔可被訂閱
2、Consumer Pull最大間隔時間

1、數據進入Broker就可以被訂閱
2、同樣依賴Consumer Pull最大間隔時間

異步刷盤實時性

按照條數與時間刷盤,實時性低

後臺線程實時刷盤

同步刷盤

不支持

支持,且性能接近異步刷盤

異步複製

不支持

支持

 

6.2     Metaq是什麼?

圖表 6‑1 Metaq是什麼

(1).     是一個隊列模型的消息中間件。

(2).    Producer、Consumer、隊列都可以分佈式。

(3).    Producer向一些隊列輪流發送消息,隊列集合稱爲Topic,Consumer如果做廣播消費,則一個consumer實例消費這個Topic對應的所有隊列,如果做集羣消費,則多個Consumer實例平均消費這個topic對應的隊列集合。

7          Metaq主要功能點實現細節

7.1     單機如何實現1萬以上個隊列

圖表 7‑1Metaq隊列

(1).     所有數據單獨存儲到一個物理隊列,完全順序寫,隨機讀。

(2).    對最終用戶展現的隊列實際只存儲消息在物理隊列的位置信息,並且串行方式刷盤。

 

這樣做的好處如下:

(1).     隊列輕量化,單個隊列數據量非常少。

(2).    對磁盤的訪問串行化,避免磁盤竟爭,不會因爲隊列增加導致IOWAIT增高。

 

每個方案都有缺點,它的缺點如下:

(1).     寫雖然完全是順序寫,但是讀卻變成了完全的隨機讀。

(2).    讀一條消息,會先讀邏輯隊列,再讀物理隊列,增加了開銷。

(3).    要保證物理隊列與邏輯隊列完全的一致,增加了編程的複雜度。

 

以上缺點如何克服:

(1).     隨機讀,儘可能讓讀命中PAGECACHE,減少IO讀操作,所以內存越大越好。如果系統中堆積的消息過多,讀數據要訪問磁盤會不會由於隨機讀導致系統性能急劇下降,答案是否定的。

a)        訪問PAGECACHE時,即使只訪問1k的消息,系統也會提前預讀出更多數據,在下次讀時,就可能命中內存。

b)        隨機訪問物理隊列磁盤數據,系統IO調度算法設置爲NOOP方式,會在一定程度上將完全的隨機讀變成順序跳躍方式,而順序跳躍方式讀較完全的隨機讀性能會高5倍以上,可參見以下針對各種IO方式的性能數據。

http://stblog.baidu-tech.com/?p=851

另外4k的消息在完全隨機訪問情況下,仍然可以達到10000次每秒以上的讀性能。

(2).    由於邏輯隊列存儲數據量極少,而且是順序讀,在PAGECACHE預讀作用下,邏輯隊列的讀性能幾乎與內存一致,即使堆積情況下。所以可認爲邏輯隊列完全不會阻礙讀性能。

(3).    物理隊列中存儲了所有的元信息,類似於Mysql的binlog,Oracle的redolog,所有只要有物理隊列在,邏輯隊列即使數據丟失,仍然可以恢復出來。

7.2     刷盤策略

Metaq的所有消息都是持久化的,先寫入系統PAGECACHE,然後刷盤,可以保證內存與磁盤都有一份數據,訪問時,直接從內存讀取。

7.2.1      異步刷盤

在有RAID卡,SAS 15000轉磁盤測試順序寫文件,速度可以達到200M每秒以上,而線上的網卡一般都爲千兆網卡,寫磁盤速度明顯快於數據網絡入口速度,那麼是否可以做到寫完內存就向用戶返回,由後臺線程刷盤呢?

(1).     由於磁盤速度大於網卡速度,那麼刷盤的進度肯定可以跟上消息的寫入速度。

(2).    萬一由於此時系統壓力過大,可能堆積消息,除了寫入IO,還有讀取IO,萬一出現磁盤讀取落後情況,會不會導致系統內存溢出,答案是否定的,原因如下:

a)        寫入消息到PAGECACHE時,如果內存不足,則嘗試丟棄乾淨的PAGE,騰出內存供新消息使用,策略是LRU方式。

b)        如果幹淨頁不足,此時寫入PAGECACHE會被阻塞,系統嘗試刷盤部分數據,大約每次嘗試32個PAGE,來找出更多幹淨PAGE。

綜上,內存溢出的情況不會出現。

7.2.2    同步刷盤

同步刷盤與異步刷盤的唯一區別是異步刷盤寫完PAGECACHE直接返回,而同步刷盤需要等待刷盤完成才返回,同步刷盤流程如下:

(1).     寫入PAGECACHE後,線程等待,通知刷盤線程刷盤。

(2).    刷盤線程刷盤後,喚醒前端等待線程,可能是一批線程。

(3).    前端等待線程向用戶返回成功。

7.3     服務器消息過濾

7.3.1      按照Message Type過濾

Metaq的消息過濾方式有別於其他消息中間件,是在訂閱時,再做過濾,先來看下邏輯隊列的存儲結構。

圖表 7‑2邏輯隊列單個存儲單元結構

(1).     在Broker端進行Message Type比對,先遍歷邏輯隊列,如果存儲的Message Type與訂閱的Message Type不符合,則跳過,繼續比對下一個,符合則傳輸給Consumer。注意:Message Type是字符串形式,邏輯隊列中存儲的是其對應的hashcode,比對時也是比對hashcode。

(2).    Consumer收到過濾後的消息後,同樣也要執行在Broker端的操作,但是比對的是真實的Message Type字符串,而不是Hashcode。

 

爲什麼過濾要這樣做?

(1).     Message Type存儲Hashcode,是爲了在邏輯隊列定長方式存儲,節約空間。

(2).    過濾過程中不會訪問物理隊列數據,可以保證堆積情況下也能高效過濾。

(3).    即使存在Hash衝突,也可以在Consumer端進行修正,保證萬無一失。

7.3.2    按照Message Tag過濾

暫時不支持。

7.4     消息查詢

7.4.1     按照MessageId查詢消息

圖表 7‑3 Message Id組成

MsgId總共20字節,包含消息存儲時間,消息存儲主機地址,消息物理分區offset。從MsgId中解析出server的地址和物理分區的偏移地址,然後按照存儲格式所在位置消息buffer解析成一個完整的消息。

7.4.2    按照時間查詢隊列Offset

圖表 7‑4邏輯隊列組成

根據時間Tn查找到對應的索引文件Fn,索引文件在metaq的內部存儲結構中是有序排列的(按時間遞增),因此當一個查詢進來的時候首先根據查詢的時間 Tn查找到所屬的索引文件。例如:假設T2<Tn<T3(Tn對應的索引文件記做Fn,Tn是索引文件Fn最後一次的修改時間),則Tn時間對應的消息就應包含在索引文件F3中。

 

圖表 7‑5 按照時間二分查找

二分遍歷索引文件,查找到一個最接近的消息,同一個隊列的消息是嚴格按照時間先後順序入隊,所以按照二分查找定位到一個消息的offset時間複雜度爲O(logN)。例如:一個索引文件的大小爲8M,一條索引佔16字節,一個文件中總共的索引條數爲524288條,極端情況下最多遍歷次數爲19,因爲query的時間精確到ms,所以不命中的情況下會返回最接近的結果值。

7.4.3    按照Message Key查詢消息

圖表 7‑6索引的邏輯結構,類似HashMap實現

 

圖表 7‑7單個索引項的存儲結構

圖表 7‑8每個索引文件的物理存儲結構

1.        根據查詢的key的hashcode%slotNum得到具體的槽的位置(slotNum是一個索引文件裏面包含的最大槽的數目,例如圖7.4.3-1中所示slotNum=5000000),索引的邏輯結構見圖7.4.3-1 。

2.       根據slotValue(slot位置對應的值)查找到索引項列表的最後一項(倒序排列,slotValue總是指向最新的一個索引項),索引項的存儲結構見圖7.4.3-2 。

3.       遍歷索引項列表返回查詢時間範圍內的結果集(默認一次最大返回的32條記錄)

4.      Hash衝突;尋找key的slot位置時相當於執行了兩次散列函數,一次key的hash,一次key的hash值取模,因此這裏存在兩次衝突的情況;第一種,key的hash值不同但模數相同,此時查詢的時候會在比較一次key的hash值(每個索引項保存了key的hash值),過濾掉hash值不相等的項。第二種,hash值相等但key不等,出於性能的考慮衝突的檢測放到客戶端處理(key的原始值是存儲在消息文件中的,避免對數據文件的解析),客戶端比較一次消息體的key是否相同。

5.       存儲;爲了節省空間索引項中存儲的時間是時間差值(存儲時間-開始時間,開始時間存儲在索引文件頭中),整個索引文件是定長的,結構也是固定的。索引文件存儲結構參見圖7.4.3-3 。

7.5     HA,同步雙寫

暫時不支持。

7.6     HA,異步複製

異步複製的實現思路非常簡單,Slave啓動一個線程,不斷從Master拉取物理隊列中的數據,然後在異步build出邏輯隊列數據結構。整個實現過程基本同Mysql主從同步類似。

7.7     單個JVM進程也能利用機器超大內存

圖表 7‑9消息在系統中流轉圖

(1).     Producer發送消息,消息從socket進入java堆。

(2).    Producer發送消息,消息從java堆轉入PAGACACHE,物理內存。

(3).    Producer發送消息,由異步線程刷盤,消息從PAGECACHE刷入磁盤。

(4).   Consumer拉消息(正常消費),消息直接從PAGECACHE(數據在物理內存)轉入socket,到達consumer,不經過java堆。這種消費場景最多,線上96G物理內存,按照1K消息算,可以在物理內存緩存1億條消息。

(5).    Consumer拉消息(異常消費),消息直接從PAGECACHE(數據在虛擬內存)轉入socket。

(6).   Consumer拉消息(異常消費),由於Socket訪問了虛擬內存,產生缺頁中斷,此時會產生磁盤IO,從磁盤Load消息到PAGECACHE,然後直接從socket發出去。

(7).    同5一致。

(8).   同6一致。

7.8     消息堆積問題解決辦法

前面提到衡量消息系統堆積能力的幾個指標,現將Metaq的堆積能力整理如下

表格 7‑1Metaq性能堆積指標

 

堆積性能指標

1

消息的堆積容量

依賴磁盤大小

2

發消息的吞吐量大小受影響程度

無SLAVE情況,會受一定影響
有SLAVE情況,不受影響

3

正常消費的Consumer是否會受影響

無SLAVE情況,會受一定影響
有SLAVE情況,不受影響

4

訪問堆積在磁盤的消息時,吞吐量有多大

1、1K大小左右消息堆積情況下吞吐量非常高,
在5W每秒以上。
2、4K消息性能最差,1W每秒左右。

 

在有Slave情況下,Master一旦發現Consumer訪問堆積在磁盤的數據時,會向Consumer下達一個重定向指令,令Consumer從Slave拉取數據,這樣正常的發消息與正常消費的Consumer都不會因爲消息堆積受影響,因爲系統將堆積場景與非堆積場景分割在了兩個不同的節點處理。這裏會產生另一個問題,Slave會不會寫性能下降,答案是否定的。因爲Slave的消息寫入只追求吞吐量,不追求實時性,只要整體的吞吐量高就可以,而Slave每次都是從Master拉取一批數據,如1M,這種批量順序寫入方式即使堆積情況,整體吞吐量影響相對較小,只是寫入RT會變長。

8         Metaq開發過程中遇到了哪些問題?

(1).     分配MapedFile有時耗時很長,長達幾百毫秒,在性能壓測過程中,會大大拉低整體性能。

解決辦法:採用預分配方式,這樣前端請求就不會因爲分配MapedFile而阻塞。

(2).    刪除單個1G文件耗時達1秒以上,導致寫消息性能下降

解決辦法:在ext3下,刪除文件確實耗時較長,使用ext4文件系統,刪除1G文件通常耗時幾十毫秒。

(3).    Consumer搶分區會存在失敗的情況,原因是寫入ZK節點失敗

解決辦法:去除搶這個概念,所有Consumer按照同樣的算法進行分配,最終一致。

9         Metaq目前有哪些地方需要改進?

(1).     異步複製仍然不能完全避免單點,會被用戶詬病,需要嘗試同步雙寫。

(2).    消息過濾功能較簡單,是否可以支持像Notify一樣的高級過濾方式

(3).    對Zookeeper強依賴問題。

(4).   客戶端API其實可以更友好。

10      Metaq的幾個設計原則

Metaq在開發過程中,遵循以下設計原則,有些觀點爲個人看法,不一定對所有產品都適用,或者不一定正確,寫出來僅供各位參考。

1.          消息都是持久化的,內存與磁盤各一份。

2.         高性能離不開異步,異步離不開隊列,無論是構建整個系統還是構建單個程序都適用

3.         磁盤IO,網絡IO儘可能的批量處理。

4.        如果操作系統的層面已經提供的功能,或者優化過的性能點,儘可能交給操作系統處理.

5.         與IO相關部分儘可能用單線程處理,避免使用多線程。一個功能儘可能拆分成幾個獨立的子功能,每個功能有專門的線程來執行。

6.        一個線程只做一件事情,並做好。因爲目前的計算機CPU資源足夠強大,即使是單個CPU也運算能力足夠快。如果一個線程沒有阻塞的地方,使用多線程並不能提升性能,反而會下降,如果有阻塞地方,可酌情使用多線程,但也要分場景。

7.         爲追求高性能,犧牲了某些消息系統中特有的高級功能,例如消息優先級、分佈式事務等。

 

附錄A 參考文檔、規範

n  Java Message Service API Tutorial

http://docs.oracle.com/javaee/1.3/jms/tutorial/1_3_1-fcs/doc/jms_tutorialTOC.html

n  Java(TM) Message Service Specification Final Release 1.1

http://www.oracle.com/technetwork/java/docs-136352.html

n  CORBA Notification Service Specification 1.1

http://www.omg.org/spec/NOT/1.1/PDF

n  Distributed Transaction Processing: The XA Specification

http://pubs.opengroup.org/onlinepubs/009680699/toc.pdf

n  Metaq Benchmark

http://taobao.github.com/metaq/document/benchmark/benchmark.pdf

n  Documentation for /proc/sys/vm/*

http://www.kernel.org/doc/Documentation/sysctl/vm.txt

說明:轉載下,方便查看

轉載自 https://blog.csdn.net/youling_lh/article/details/10953347

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