基於kafka原理單機高效能微秒級別佇列改造

2021-10-04 21:48:55 字數 1766 閱讀 6637

線上業務需要一款擁有超低延遲(us),支援多消費者,並且能夠處理海量的訊息積壓的訊息佇列。

kafka是我們日常生活中比較常見的訊息佇列,非常適合做訊息的離線處理。但是在一些實時性要求比較高的場景下,訊息自帶的延遲是不可忍受的,測試發現一條訊息**大概需要200ms的耗時,實際情況可能有所出入,但肯定是毫秒級別的。kafka從設計上就是傾向於面向大眾,滿足大部分需求。當然滿足這些要求的成本就是通過犧牲了效能。所以說kafka適合做離線處理。而不是做一些非常實時的應用。

zeromq就是針對實時應用的一款訊息佇列,提供了各個拓撲結構的鏈結方式,效能不錯,但不足的是當訊息積壓有可能會寫滿記憶體。

市面上目前的訊息佇列都與我們的設計目標不符。

要想擁有微秒級別的延遲,

不能走網路,資料必須放本地。

使用inotify等待新資料的產生。

不適用get_line, fgets等庫函式,減少資料拷貝,自己實現拆包邏輯。

讀取的buffer_size不能設定的過小,由於下游消費通常存在一定的耗時,我們盡量一次多讀取一些,否則系統呼叫read的成本很高。

當訊息產生積壓的情況,我們採用water_mark機制來自動調節每次資料讀取的最大位元組。

#include #include #include #define event_size (sizeof(struct inotify_event))

#define buf_len (10 * (event_size + filename_max + 1))

int wartermark = 1024 * 1024;

int max_buffer_size = wartermark * 6;

char *line_ = new char[10240]; // 每行緩衝區

char *buffer_ = new char[max_buffer_size]; // 檔案緩衝區

char *buffer2_ = new char[buf_len]; // inotify事件緩衝區

// 註冊監聽檔案變化

int ifd_ = inotify_init();

if (ifd_ < 0)

inotify_add_watch(ifd_, path_.c_str(), in_modify | in_create | in_delete);

// 開啟檔案

int fd_ = open(path_.c_str(), o_rdonly);

if (fd_ < 0)

// 讀取檔案

register long int buffer_size = wartermark;

register char *cs;

register int i = 0;

cs = line_;

bool ok_ = true;

while (ok_)

//remove last \n

*(--cs) = '\0';

cb_(line_);

if (!ok_) break;

cs = line_;

}if (!ok_) break;

if (read_ == wartermark) else

i = 0;

}read(ifd_, buffer2_, buf_len);

}

消費者只需要將自己業務入口註冊為cb_,就可以實現消費。

實際測試發現從訊息生產到cb_入口訊息延遲大概在100個us以內。以上**雖然實現起來很簡單,但是正是由於其簡單才保證了超高的效能。

Kafka高效能讀寫原理

kafka是高吞吐低延遲的高併發 高效能的訊息中介軟體,在大資料領域有極為廣泛的運用。配置良好的kafka集群甚至可以做到每秒幾十萬 上百萬的超高併發寫入。那麼kafka到底是如何做到這麼高的吞吐量和效能的呢?首先kafka每次接收到資料都會往磁碟上去寫,如下圖所示。那麼在這裡我們不禁有乙個疑問了,...

kafka原理解析之 高效能內幕

1.partition的持久化佇列結構 資料按先後順序依次追加在檔案末尾,讀寫操作分開,如下圖所示。這種結構有如下優勢 注 使用6個7200rpm sata介面 raid 5的磁碟陣列在jbod配置下的順序寫入的效能約為600mb 秒,但隨機寫入的效能僅約為100k 秒,相差6000倍以上。2.利用...

高效能 爬蟲原理

socket 原理 本質上就是乙個socket服務端,乙個客戶端.客戶端在連線服務端的時候只是封裝了http協議頭以及訪問的位址 阻塞 import socket 阻塞 請求 非阻塞 http用的就是這種 請求方式,請求只管發出去,而阻塞的方式還等請求連線成功再發訊息。mport socket ip...