CTO觀點:如何爲企業選擇合適的消息系統?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在評估新技術時,高層管理人員的視角通常與中層管理人員、架構師、數據工程師等有所不同。高層管理人員不僅要關注基準測試結果、產品支持的特性,還要從長遠角度考慮新技術的可靠性,新技術能夠爲企業帶來哪些競爭優勢,以及是否可以縮短上市時間、節約開銷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我是 Big Data Institute 的常務董事,技術評估是我的一項主要工作。我們幫助企業根據業務需求選擇並落地最合適的技術。我們不與供應商合作,因此客戶尤爲看中我們能夠客觀地評估不同的技術。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在本文中,我將從 CTO 的視角出發,對比 Apache Pulsar 和 Apache Kafka。只進行理論上的對比空洞無效,也不能幫助我們作出決策,實際用例才真正值得參考。所以,在本文中,我會通過一些常見的實際使用場景來對比 Pulsar 和 Kafka,即簡單消息使用場景、複雜消息使用場景和高級消息使用場景。在這些實際使用場景下,Pulsar 和 Kafka 的表現能夠幫助我們更好地理解二者的性能和優勢,進而作出決策。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"簡單消息使用場景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假設有一個企業,之前從未使用過消息系統,現在需要通過一個簡單的消息系統,將消息從位置 A 發送到位置 B,但不需要複製消息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據架構師團隊在深入研究 Pulsar 和 Kafka 的業務案例後,得出如下結論:在這一使用場景中,Pulsar 和 Kafka 都沒有絕對優勢。並且,他們認爲在短時間內,該使用場景基本不會發生改變。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於類似這樣的簡單消息使用場景而言,我也贊同 Pulsar 和 Kafka 都沒有絕對優勢。僅從技術角度出發,Pulsar 和 Kafka 這一回合打成平局,那麼我們只能考慮成本。二者的運營成本、員工培訓成本分別是多少?我打算根據 Kafka 或 Pulsar 的服務提供商的收費標準進行對比。對比開銷時,選好服務提供商也可以在一定程度上減少運營成本和員工培訓成本。Kafka 的雲服務提供商,我參考了使用 "},{"type":"link","attrs":{"href":"https:\/\/docs.microsoft.com\/en-us\/azure\/event-hubs\/event-hubs-for-kafka-ecosystem-overview","title":null,"type":null},"content":[{"type":"text","text":"Kafka API"}]},{"type":"text","text":"(Azure)的 "},{"type":"link","attrs":{"href":"https:\/\/www.confluent.io\/confluent-cloud\/","title":null,"type":null},"content":[{"type":"text","text":"Confluent Cloud"}]},{"type":"text","text":"、"},{"type":"link","attrs":{"href":"https:\/\/aws.amazon.com\/msk\/","title":null,"type":null},"content":[{"type":"text","text":"MSK"}]},{"type":"text","text":"(AWS)和 "},{"type":"link","attrs":{"href":"https:\/\/azure.microsoft.com\/en-us\/services\/event-hubs\/","title":null,"type":null},"content":[{"type":"text","text":"Event Hubs"}]},{"type":"text","text":"。Pulsar 的雲服務提供商,我選擇 "},{"type":"link","attrs":{"href":"https:\/\/streamnative.io\/zh\/cloud\/hosted","title":null,"type":null},"content":[{"type":"text","text":"StreamNative Cloud"}]},{"type":"text","text":"。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"對比結果"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"出於穩妥考慮,我們決定選擇 Kafka API。目前,已有多種技術支持非 Kafka broker 使用 Kafka API 或傳輸協議。使用 Kafka API,非 Kafka broker 可通過添加新庫支持 Kafka 的傳輸協議,保證對 Kafka API 的兼容性,從而最大化技術選擇的多樣性。例如,可以通過修改 Kafka API 的實現重新編譯或通過 Pulsar broker 解析 Kafka 的協議(KOP),將 Pulsar 用作 Kafka 的後端。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們在對比單位成本後,選擇了成本效益高的一方。Kafka API 可以保證後端質量,用戶在後端之間的數據移動不會受到影響,有效規避風險。即使社區不活躍,技術熱度不高,我們的使用也不會受到影響。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"複雜消息使用場景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假設一個公司需要複雜消息系統。由於需要處理世界各地的數據,必須支持跨地域複製。該企業一直在使用消息系統,因此對實時系統的複雜性有一定的瞭解,也發現了當前消息系統的不足之處。因此該企業對消息系統的要求是能夠處理高級的消息傳遞和複雜的消息特性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據架構師團隊和股東以及業務部門詳細討論了當前和未來需求。最後得出的結論是,Pulsar 和 Kafka 各有優勢。同時,他們認爲隨着時間的推移,該使用場景和數據量都會有所增長。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這種情況下,Pulsar 和 Kafka 難分勝負。要想作出正確決策,必須深入研究二者的使用場景。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"跨地域複製"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 既提供私有的(價格高)跨地域複製,也提供開源的(附加服務)跨地域複製解決方案。私有的跨地域複製解決方案爲其內置特性,但價格高昂。開源的解決方案(MirrorMaker)實際上就是數據複製,但由於不是其內置特性,會增加運營開銷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar 提供開源內置的跨地域複製特性,支持複雜的複製策略。對於使用場景和數據量都在增加的企業而言,顯然,支持內置跨地域複製策略的 Pulsar 完勝。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就跨地域複製而言,我們選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"複雜消息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於企業正在向新消息平臺遷移,消息系統最好可以處理新使用場景。數據架構師團隊一直在瞭解各個平臺,嘗試尋找最佳解決方案。在當前使用的消息系統中,一旦出現處理錯誤,必須重新生成消息,再手動重試,因此最好還可以引入消息延遲發送。另外,當前消息系統的 schema 實施功能也有待加強,各個團隊選擇不同的 schema 實現時,團隊合作的難度顯著增加。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 沒有內置死信隊列特性,一旦消息處理失敗,必須手動處理,或修改代碼重試。Kafka 也沒有延遲發送消息的內置機制,延遲發送消息流程複雜、工作量大。另外,Kafka 沒有內置 schema 實施機制,導致雲服務提供商分別提供了不同的 schema 解決方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar 內置死信隊列特性,當消息處理失敗,收到否認 ack 時,Pulsar 可以自動重試,但次數有限。Pulsar 也支持延遲發送消息,可以設定延遲時間。對於 Pulsar 而言,schema 級別高,因此 Pulsar 有內置 schema 註冊,Pulsar API 也原生支持 schema。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就複雜消息而言,我們選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"高級消息傳遞"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着對架構的深入瞭解,我們發現爲了確保均勻分配資源,需要循環發送同一 topic 上的數據,並且需要通過排序確保消息有序排列。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 不能分發消息給指定的 consumer。當 consumer 接收到不屬於它消費的消息時,要保證這些消息被正確消費,我們只能重新發送這些消息到額外的 topic 中,但這樣會造成數據冗餘,增加使用成本。因此,我們需要可以制定路由規則發送給指定 consumer 的產品。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar broker 可以通過制定的路由規則,把一個 topic 的不同消息根據路由規則發送到指定的 consumer 中。Pulsar broker 輕鬆實現了我們的目標,無需任何額外工作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就高級消息傳遞而言,我們選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"部署和社區"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了全面比較 Pulsar 和 Kafka,我們還需要看一下二者的部署數量和社區概況。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從服務市場來看,Kafka 的提供商更多,銷售和支持 Kafka 產品的團隊也更多。Kafka 和 Pulsar 的開源社區都積極活躍,但 Kafka 的社區規模更大。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從使用市場來看,Kafka 和 Pulsar 都已部署在大公司的大型生產環境中。在生產環境中部署 Kafka 的公司在數量上更勝一籌。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從用戶數量來看,Kafka 的用戶更多。但是,數據工程師團隊認爲, Kafka 的使用者可以輕鬆學習 Pulsar。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就服務支持和社區而言,我們選擇 Kafka。但值得一提的是,Pulsar 社區正在迅速發展。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"對比結果"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於 Pulsar 和 Kafka 在這一使用場景中都有明顯的優劣勢,決策難度大大增加。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar 可以在社區和部署上奮起直追,Kafka 則可以努力豐富產品特性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在作出決策前,我們先來總結一下,該企業在技術上最看重哪方面;在技術方面,我們是否需要做最保守的選擇。根據以往的經驗,新的開源技術會帶來更多驚喜,因此我們更傾向於選擇 Pulsar。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果選擇 Kafka,我們需要承擔向業務贊助商坦誠“我們無法處理這一使用場景”的風險。甚至,即使支付大筆資金購買跨地域複製許可,也無法保證順利實現客戶的需求。業務團隊最終可能需要花大量時間(甚至幾個月)來編寫、完善、測試他們的工作方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果選擇 Pulsar,我們可以告訴業務贊助商“一切盡在掌握中”。由於 Pulsar 的各項內置特性都已經過測試,使用團隊可以在短時間內完成部署。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這種情況下,因爲我們不需要 Kafka API 的獨有特性,所以我們沒有使用支持 Kafka 協議(KOP)的 Pulsar Broker,而是選擇 Pulsar API,因爲 Pulsar API 支持所有我們需要 Kafka API 提供的功能。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"決策如下:選擇 Pulsar,可以優先處理業務請求,開發團隊只專注編寫代碼,而不是解決其他問題。選擇 Pulsar 的同時,也關注 Pulsar 社區和提供商的動態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果採取保守決策選擇 Kafka,需要接受可能無法實現某些使用場景的事實。對於相似的使用場景,我們採取相應解決方案。調整項目時間規劃,增加實行預期解決方案的時間。聯繫運營團隊,確保可以承受執行預期解決方案的開銷。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"高級消息使用場景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假設一個公司已經在使用多種消息和隊列系統。從運營、架構和開銷的角度來看,我們認爲有必要遷移到單個系統。同時,我們也希望降低運營成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據架構師團隊在和股東以及業務部門詳細討論了當前和未來需求後,給出的結論是,Pulsar 和 Kafka 各有優勢。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"隊列和消息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最大的難題是 RabbitMQ 系統。我們使用 RabbitMQ 發送太多消息,RabbitMQ 已經無法滿足需求。我們調整了 RabbitMQ 的代碼,將消息緩衝在內存中,並繼續創建新集羣來處理負載。但是我們需要的不是變通方法,而是一個能夠處理大規模消息的系統。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據架構師在研究這一使用場景時,得出結論:新系統必須可以同時處理消息流模型和隊列模型。我們不僅需要繼續使用 RabbitMQ 處理消息,也需要更高級的消息技術。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 擅長消息傳遞,也可以處理大規模消息流,但是無法處理隊列。開發團隊可以嘗試一些解決方案,但這樣就不能實現使用單個系統的預期目標。要處理隊列使用場景,就同時需要 Kafka 集羣和 RabbitMQ 集羣。Kafka 集羣更像一個緩衝區,可以有效防止 RabbitMQ 集羣過載。但是 Kafka 不支持原生 RabbitMQ,我們需要與提供商合作或自己編寫代碼,纔可以實現在 Kafka 和 RabbitMQ 之間移動數據。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar 可以在同一集羣中處理隊列和消息,還支持擴展集羣。Pulsar 可以將所有消息流模型和隊列模型的使用場景整合到一個集羣中。用戶可以繼續使用 RabbitMQ 代碼,Pulsar 支持 RabbitMQ 連接器,或者在 broker 中使用 StreamNative 開發的 "},{"type":"link","attrs":{"href":"https:\/\/github.com\/streamnative\/aop","title":null,"type":null},"content":[{"type":"text","text":"AoP(AMQP 協議處理插件)"}]},{"type":"text","text":",該插件已獲得 Apache 許可。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果不想繼續使用 RabbitMQ 代碼,則可以使用 Pulsar API。Pulsar API 具有和 RabbitMQ 相同的隊列功能。用戶需要對代碼進行相應修改,工作量取決於原代碼的結構和細節,修改代碼後,還需要對代碼進行評估測試。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就隊列模型和消息流模型而言,我們選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"高級保留"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據架構師分析了數據使用情況,發現 99.99% 的數據在首次使用後就未被讀取。但是,他們決定採取保守策略,保留消息一週。雖然決定存儲數據一週,但我們不希望增加太多運營成本。分層存儲可以保存數據到本地,然後卸載其他數據到 S3,降低長期保存數據的成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 團隊正在開發分層存儲,但 Kafka 目前還不支持這一特性。一些服務商提供私有分層存儲,但我們不確定是否可以直接用於生產環境中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分層存儲是 Pulsar 的原生特性,可以直接用於生產環境。目前已有多個企業在生產環境中部署該特性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就分層存儲而言,我們選擇 Pulsar。Kafka 正在全力開發分層存儲,這一特性的重要性不言而喻。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"路由 Topic"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於我們使用多個 topic 來分解數據,我們期待新系統可以創建大量 topic。數據架構師認爲,我們起初需要 10 萬個 topic,隨着時間的推移,這個數字將會漲到 50 萬。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 集羣支持創建的分區數量有限且每個 topic 至少需要一個分區。Kafka 正在增加可支持 topic 的數量,但新特性尚未發佈。另外,Kafka 沒有命名空間和多租戶,因此無法基於 topic 對資源進行分片,十萬個 topic 需要存儲在同一個命名空間中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一些企業的確在使用 Kafka 集羣存儲甚至更多的 topic,同時進行了資源分片。但他們放棄使用單一集羣,同時還需要爲此支付費用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar 支持存儲數百萬個 topic,這一功能早已發佈並投入生產環境。Pulsar 支持命名空間和多租戶,用戶可以爲每個 topic 設置資源配額,進而節約開銷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就 topic 而言,我們選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"路由"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於我們假設該企業曾經使用 RabbitMQ,在設計上,一般通過 broker 路由機制把 topic 上的數據轉發到不同的 topic 中。例如,有一個用於存儲世界範圍數據的 topic,而 RabbitMQ broker 把它處理成以國家爲單位的 topic。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據架構師團隊深入研究瞭如何在消息系統中使用單一 topic 存儲世界範圍的數據。他們發現當接收數據量增大時,下游 consumer 無法繼續處理數據。對每個下游系統進行反序列化、查看數據,再丟棄數據的流程繁雜,且費時費力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kafka 將所有數據存儲在單一 topic 中,但是,當 consumer 需要過濾的數據量增加或集羣過載時,這個方法不可行。我們通常需要進行水平縮放,增加 consumer 數量,纔可以讀取全局 topic 並做進一步處理。用戶只能選擇:編寫自定義 consumer \/ producer,編寫 Kafka Streams 程序,或使用專有 KSQL。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Pulsar 支持使用 Pulsar Functions 或自定義 consumer \/ producer 進行路由,因此可以先讀取全局 topic,再將數據保存到以國家爲單位的特定 topic 上。使用獨立 topic,consumer 可以按需訂閱 topic,只接收相關消息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就路由而言,我們選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"最終決策"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"時間是影響最終決策的主要原因。我們是否有時間讓 Kafka 趕上 Pulsar?我們是否有時間讓數據工程師來實現 Kafka 的解決方案?等待會讓公司錯失良機,延緩增加新的使用場景,影響業務發展。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最終決策:我們選擇 Pulsar。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"時間充足情況下的決策:延遲使用新架構。給 Kafka 半年時間,看 Kafka 是否可以在性能上趕超 Pulsar。如果可以,我們將在生產環境中測試這些新特性,評估穩定性。如果 Kafka 不能讓人眼前一亮,我們仍然會選擇 Pulsar。"}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"結語"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文涉及的三個使用場景都是我在實際工作中遇到的,希望本文給出的解決方案可以爲您提供參考,幫助您根據具體使用場景進行技術評估。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/dzone.com\/articles\/comparing-pulsar-and-kafka-from-a-ctos-point-of-vi","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/dzone.com\/articles\/comparing-pulsar-and-kafka-from-a-ctos-point-of-vi"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章