天天看點

從 Elasticsearch 到 Apache Doris,建構新一代日志存儲分析平台

作者:SelectDB

作者介紹: 肖康,SelectDB 技術副總裁

導語

日志資料的處理與分析是最典型的大資料分析場景之一,過去業内以 Elasticsearch 和 Grafana Loki 為代表的兩類架構難以同時兼顧高吞吐實時寫入、低成本海量存儲、實時文字檢索的需求。Apache Doris 借鑒了資訊檢索的核心技術,在存儲引擎上實作了面向 AP 場景優化的高性能反向索引,對于字元串類型的全文檢索和普通數值、日期等類型的等值、範圍檢索具有更高效的支援,相較于 Elasticsearch 實作成本效益 10 餘倍的提升,以此為日志存儲與分析場景提供了更優的選擇。

日志資料分析的需求與特點

日志資料在企業大資料中非常普遍,其體量往往在企業大資料體系中占據非常高的比重,包括伺服器、資料庫、網絡裝置、IoT 物聯網裝置産生的系統運維日志,與此同時還包含了使用者行為埋點等業務日志。

日志資料對于保障系統穩定運作和業務發展至關重要:基于日志的監控告警可以發現系統運作風險,及時預警;在故障排查過程中,實時日志檢索能幫助工程師快速定位到問題,盡快恢複服務;日志報表能通過長曆史統計發現潛在趨勢。而使用者埋點日志資料則是使用者行為分析以及智能推薦業務所依賴的決策基礎,有助于使用者需求洞察與體驗優化以及後續的業務流程改進。

由于其在業務中能發揮的重要意義,是以建構統一的日志分析平台,提供對日志資料的存儲、高效檢索以及快速分析能力,成為企業挖掘日志資料價值的關鍵一環。而日志資料和應用場景往往呈現如下的特點:

  • 資料增長快:每一次使用者操作、系統事件都會觸發新的日志産生,很多企業每天新增日志達到幾十甚至幾百億條,對日志平台的寫入吞吐要求很高;
  • 資料總量大:由于自身業務和監管等需要,日志資料經常要存儲較長的周期,是以累積的資料量經常達到幾百 TB 甚至 PB 級,而較老的曆史資料通路頻率又比較低,面臨沉重的存儲成本壓力;
  • 時效性要求高:在故障排查等場景需要能快速查詢到最新的日志,分鐘級的資料延遲往往無法滿足業務極高的時效性要求,是以需要實作日志資料的實時寫入與實時查詢。

這些日志資料和應用場景的特點,為承載存儲和分析需求的日志平台提出了如下挑戰:

  • 高吞吐實時寫入:既需要保證日志流量的大規模寫入,又要支援低延遲可見;
  • 低成本大規模存儲:既要存儲大量的資料,又要降低存儲成本;
  • 支援文字檢索的實時查詢:既要能支援日志文本的全文檢索,又要做到實時查詢響應;

業界日志存儲分析解決方案

目前業界有兩種比較典型的日志存儲與分析架構,分别是以 Elasticsearch 為代表的反向索引檢索架構以及以 Loki 為代表的輕量索引/無索引架構,如果我們從實時寫入吞吐、存儲成本、實時互動式查詢性能等幾方面進行對比,不難發現以下結論:

  • 以 ES 為代表的反向索引檢索架構,支援全文檢索、查詢性能好,是以在日志場景中被業内大規模應用,但其仍存在一些不足,包括實時寫入吞吐低、消耗大量資源建構索引,且需要消耗巨大存儲成本;
  • 以 Loki 為代表的輕量索引或無索引架構,實時寫入吞吐高、存儲成本較低,但是檢索性能慢、關鍵時候查詢響應跟不上,性能成為制約業務分析的最大掣肘。
從 Elasticsearch 到 Apache Doris,建構新一代日志存儲分析平台

ES 在日志場景的優勢在于全文檢索能力,能快速從海量日志中檢索出比對關鍵字的日志,其底層核心技術是反向索引(Inverted Index)。

反向索引是一種用于快速查找文檔中包含特定單詞或短語的資料結構,最早應用于資訊檢索領域。如下圖所示,在資料寫入時,反向索引可以将每一行文本進行分詞,變成一個個詞(Term),然後建構詞(Term) -> 行号清單(Posting List) 的映射關系,将映射關系按照詞進行排序存儲。當需要查詢某個詞在哪些行出現的時候,先在 詞 -> 行号清單 的有序映射關系中查找詞對應的行号清單,然後用行号清單中的行号去取出對應行的内容。這樣的查詢方式,可以避免周遊對每一行資料進行掃描和比對,隻需要通路包含查找詞的行,在海量資料下性能有數量級的提升。

從 Elasticsearch 到 Apache Doris,建構新一代日志存儲分析平台

圖:反向索引原理示意

反向索引為 ES 帶來快速檢索能力的同時,也付出了寫入速度吞吐低和存儲空間占用高的代價——由于資料寫入時反向索引需要進行分詞、詞典排序、建構倒排表等 CPU 和記憶體密集型操作,導緻寫入吞吐大幅下降。而從存儲成本角度考慮,ES 會存儲原始資料和反向索引,為了加速分析可能還需要額外存儲一份列存資料,是以 3 份備援也會導緻更高的存儲空間占用。

Loki 則放棄了反向索引,雖然帶來來寫入吞吐和存儲空間的優勢,但是損失了日志檢索的使用者體驗,在關鍵時刻不能發揮快速查日志的作用。成本雖然有所降低,但是沒有真正解決使用者的問題。

更高成本效益的日志存儲分析解決方案

從以上方案對比可知,以 Elasticsearch 為代表的反向索引檢索架構以及以 Loki 為代表的輕量索引/無索引架構無法同時兼顧 高吞吐、低存儲成本和實時高性能的要求,隻能在某一方面或某幾方面做權衡取舍。如果在保持反向索引的文字檢索性能優勢的同時,大幅提升系統的寫入速度與吞吐量并降低存儲資源成本,是否日志場景所面臨的困境就迎刃而解呢?答案是肯定的。

如果我們希望使用 Apache Doris 來更好解決日志存儲與分析場景的痛點,其實作路徑也非常清晰——在資料庫内部增加反向索引、以滿足字元串類型的全文檢索和普通數值/日期等類型的等值、範圍檢索,同時進一步優化反向索引的查詢性能、使其更加契合日志資料分析的場景需求。

在同樣實作反向索引的情況下,相較于 ES, Apache Doris 怎麼做到更高的性能表現呢?或者說現有反向索引的優化空間有哪些呢?

  • ES 基于 Apache Lucene 建構反向索引,Apache Lucene 自 2000 年開源至今已有超過 20 年的曆史,設計之初主要面向資訊檢索領域、功能豐富且複雜,而日志和大多數 OLAP 場景隻需要其核心功能,包括分詞、倒排表等,而相關度排序等并非強需求,是以存在進一步功能簡化和性能提升的空間;
  • ES 和 Apache Lucene 均采用 Java 實作,而 Apache Doris 存儲引擎和執行引擎采用 C++ 開發并且實作了全面向量化,相對于 Java 實作具有更好的性能;
  • 反向索引并不能決定性能表現的全部,作為一個高性能、實時的 OLAP 資料庫,Apache Doris 的列式存儲引擎、MPP 分布式查詢架構、向量化執行引擎以及智能 CBO 查詢優化器,相較于 ES 更為高效。

通過在 Apache Doris 2.0.0 最新版本的探索與持續優化,在相同硬體配置和資料集的測試表現上,Apache Doris 在資料庫核心實作高性能反向索引後,相對于 ES 實作了日志資料寫入速度提升 4 倍、存儲空間降低 80%、查詢性能提升 2 倍,再結合 Apache Doris 2.0.0 版本引入的冷熱資料分離特性,整體成本效益提升 10 倍以上!

接下來我們進一步介紹設計與實作細節。

高性能反向索引的設計與實作

業界各類系統為了支援全文檢索和任意列索引,往往有兩種實作方式:一是通過外接索引系統來實作,原始資料存儲在原系統中、索引存儲在獨立的索引系統中,兩個系統通過資料的 ID 進行關聯。資料寫入時會同步寫入到原系統和索引系統,索引系統建構索引後不存儲完整資料隻保留索引。查詢時先從索引系統查出滿足過濾條件的資料 ID 集合,然後用 ID 集合去原系統查原始資料。

這種架構的優勢是實作簡單,借力外部索引系統,對原有系統改動小。但是問題也很明顯:

  • 資料寫入兩個系統,異常有資料不一緻的問題,也存在一定備援存儲;
  • 查詢需在兩個系統進行網絡互動有額外開銷,資料量大時用 ID 集合去原系統查性能比較低;
  • 維護兩套系統的複雜度高,将系統的複雜性從開發測轉移到運維測;

而另一種方式則是直接在系統中内置反向索引,盡管技術難度更高,但性能更好、且無需花費額外的系統維護成本,對使用者更加友好,這也是 Apache Doris 所選擇的方式。

資料庫内置反向索引

在選擇了在資料庫核心中内置反向索引後,我們需要進一步對 Apache Doris 索引結構進行分析,判斷能否通過在已有索引基礎上進行拓展來實作。

Apache Doris 現有的索引存儲在 Segment 檔案的 Index Region 中,按照适用場景可以分為跳數索引和點查索引兩類:

  • 跳數索引:包括 ZoneMap 索引和 Bloom Filter 索引。
    • ZoneMap 索引對每一個資料塊和檔案儲存 Min/Max/isnull 等彙總資訊,可以用于等值、範圍查詢的粗粒度過濾,隻能排除不滿足查詢條件的資料塊和檔案,不能定位到行,也不支援文本分詞。
    • BloomFilter 索引也是資料塊和檔案級别的索引,通過 Bloom Filter 判斷某個值是否在資料塊和檔案中,同樣不能定位到行、不支援文本分詞;
  • 點查索引:包括 ShortKey 字首排序索引和 Bitmap 索引。
    • ShortKey 在排序的基礎上,根據給定的字首列實作快速查詢資料的索引方式,能夠對字首索引的列進行等值、範圍查詢,但不支援文本分詞,另外由于資料要按字首索引排序、是以一個表隻允許一組字首索引。
    • Bitmap 索引記錄資料值 -> 行号 Bitmap 的有序映射,是一種很基礎的反向索引,但是索引結構比較簡單、查詢效率不高、不支援文本分詞。

原有索引結構很難滿足日志場景實時文字檢索的需求,是以設計了全新的反向索引。反向索引在設計和實作上我們采取了無侵入的方式、不改變 Segment 資料檔案格式,而是增加了新的 Inverted Index File,邏輯上在 Table 的 Column 級别。具體流程如下:

  • 資料寫入和 Compaction 階段:在寫 Segment 檔案的同時,同步寫入一個 Inverted Index 檔案,檔案路徑由 Segment ID + Index ID 決定。寫入 Segment 的 Row 和 Index 中的 Doc 一一對應,由于同步順序寫入,Segment 中的 Rowid 和 Index 中的 Docid 完全對應。
  • 查詢階段:如果查詢 Where 條件中有建了反向索引的列,會自動去 Index 檔案中查詢,傳回滿足條件的 Docid List,将 Docid List 一一對應的轉成 Rowid Bitmap,然後走 Doris 通用的 Rowid 過濾機制隻讀取滿足條件的行,達到查詢加速的效果。
從 Elasticsearch 到 Apache Doris,建構新一代日志存儲分析平台

圖:Doris反向索引架構圖

這個設計的好處是已有的資料檔案無需修改,可以做到相容更新,而且增減索引不影響資料檔案和其他索引,使用者增建索引沒有負擔。

通用反向索引優化

C++和向量化實作

Apache Doris 使用 CLucene 作為底層的反向索引庫,CLucene 是一個用 C++ 實作的高性能、穩定的 Lucene 反向索引庫,它的功能比較完整,支援分詞和自定義分詞算法,支援全文檢索查詢和等值、範圍查詢。

Apache Doris 的存儲子產品和 CLucene 都用 C++ 實作,避免了Java Lucene 的 JVM GC 等開銷,同樣的計算 C++ 實作相對于 Java 性能優勢明顯,而且更利于做向量化加速。Doris 反向索引進行了向量化優化,包括分詞、倒排表建構、查詢等,性能得到進一步提升。整體來看 Doris 的反向索引寫入速度可以超過單核 20MB/s,而 ES 的單核寫入速度不到 5MB/s,有 4 倍的性能優勢。

列式存儲和壓縮

Lucene 本身是文檔存儲模型,主資料采用行存,而 Doris 中不同列的反向索引是互相獨立的,是以反向索引檔案也采用列式存儲,有利于向量化建構索引和提高壓縮率。

采用壓縮比高且速度快的 ZSTD,通常可以達到 5 ~10倍的壓縮比,與常用的GZIP壓縮相比有50%以上的空間節省且速度更快。

BKD 索引與 數值、日期類型 列優化

針對數值、日期類型的列,我們還實作了 BKD 索引,可以對範圍查詢提高性能,存儲空間也相對于轉成定長字元串更加高效,具有以下主要特性和優勢:

  1. 高效範圍查詢:BKD 索引采用多元資料結構,為範圍查詢帶來高效率。它能迅速定位數值或日期類型列中所需的資料範圍,降低查詢時間複雜度。
  2. 存儲空間優化:與其他索引方法相比,BKD 索引在存儲空間使用上更高效。通過聚合并壓縮相鄰資料塊,減少索引所需存儲空間,降低存儲成本。
  3. 多元資料支援:BKD 索引具備良好擴充性,支援多元資料類型,如地理坐标(GEO point)和範圍(Range),使其在處理複雜資料類型時具有高适應性。

此外,我們在原有 BKD 索引能力基礎上進行了進一步拓展:

  1. 優化低基數場景:針對數值分布集中、單個數值倒排清單較多的低基數場景,我們調整了針對性的壓縮算法,降低大量倒排表解壓縮和反序列化所帶來的CPU性能消耗。
  2. 預查詢技術:針對查詢結果命中數較高的場景,我們采用預查詢技術進行命中數預估。若命中數顯著超過門檻值,可跳過索引查詢,直接利用Doris在大資料量查詢下的技術優勢進行資料過濾。

面向 OLAP 的反向索引優化

日志存儲和分析場景對檢索的需求很簡單,不需要特别複雜的功能(比如相關性排序),更需要降低存儲成本和快速按照條件查出資料。是以,在面對海量資料的寫入和查詢時,Apache Doris 還針對 OLAP 資料庫的特點優化了反向索引的結構,使其更加簡潔高效。例如:

  • 在寫入流程保證不會多個線程寫入一個索引,進而避免寫入時多線程鎖競争的開銷;
  • 在存儲結構上去掉了不必要的正排、norm 等檔案,減少寫入 IO 開銷和存儲空間占用;
  • 查詢過程中簡化相關性打分和排序邏輯,降低不必要的開銷,提升查詢性能。

針對日志等資料有按時間分區、曆史資料通路頻度低的特點,基于獨立的索引檔案設計,Apache Doris 還将在後續的版本中提供更細粒度、更靈活的索引管理功能:

  • 指定分區建構反向索引,比如新增一個索引的時候指定最近7天的日志建構索引,曆史資料不建索引
  • 指定分區删除反向索引,比如删除超過1個月的日志的索引,釋放通路頻度低的索引存儲空間

性能測試

高性能是 Apache Doris 反向索引設計和實作的首要出發點,我們通過公開的測試資料集分别與 ES 以及 Clickhouse 進行性能測試,測試效果如下:

vs Elasticsearch

我們采用了 ES 官方的性能測試 Benchmark esrally 并使用其中的 HTTP Logs 日志,在同樣的硬體資源、資料、測試Case 以及測試工具下,記錄并對比各自的資料寫入時間、吞吐以及查詢延遲。

  • 測試資料:esrally HTTP Logs track 中自帶測試資料集,1998 年 World Cup HTTP Server Logs,未壓縮前 32G、共 2.47 億行、單行平均長度 134 位元組;
  • 測試查詢:esrally HTTP Logs 測試關鍵詞檢索、範圍查詢、聚合、排序等 11 個 Query,所有查詢跑 100 次串行執行;
  • 測試環境:3 台 16C 64G 雲主機組成的叢集。

在最終的測試結果中,Doris 寫入速度是 ES 的 4.2 倍、達到 550 MB/s,寫入後的資料壓縮比接近 1:10、存儲空間 節省 超 ****** 80%** ,查詢耗時下降 57%、查詢性能是 ES 的 2.3 倍。加上冷熱資料分離降低冷資料存儲成本,整體相較 ES 實作 10倍以上的成本效益提升。

從 Elasticsearch 到 Apache Doris,建構新一代日志存儲分析平台

vs Clickhouse

Clickhouse 近期的 v23.1 版本也引入了類似 Feature,将反向索引作為實驗性功能釋出,是以我們同樣進行了跟 Clickhouse 反向索引的性能對比。在本次測試中,我們采用了 Clickhouse 官方 Inverted Index 介紹部落格中使用的 Hacker News 樣例資料以及查詢 SQL ,同樣保持相同的實體資源、資料、測試 Case 以及測試工具。

(參考文章:https://clickhouse.com/blog/clickhouse-search-with-inverted-indices)

  • 測試資料:Hacker News 2873 萬條資料,6.7G,Parquet 格式;
  • 測試查詢:3 個查詢,分别查詢 'clickhouse'、'olap' OR 'oltp'、'avx' AND 'sve' 等關鍵字出現的次數;
  • 測試機器:1 台 16C 64G 雲主機

在最終的測試結果中,3 個 SQL Apache Doris 的查詢性能分别是 Clickhouse 的 4.7 倍、12.0 倍以及 18.5 倍,有明顯的性能優勢。

從 Elasticsearch 到 Apache Doris,建構新一代日志存儲分析平台

如何使用

下面以一個 Hacker News 100 萬條測試資料的示例展示 Doris 如何利用反向索引實作高效的日志分析。

  1. 建表時指定索引
    1. INDEX idx_comment (comment) 指定對 comment 列建一個名為 idx_comment 的索引
    2. USING INVERTED 指定索引類型為反向索引
    3. PROPERTIES("parser" = "english") 指定分詞類型為英文分詞
CREATE TABLE hackernews_1m
(
    `id` BIGINT,
    `deleted` TINYINT,
    `type` String,
    `author` String,
    `timestamp` DateTimeV2,
    `comment` String,
    `dead` TINYINT,
    `parent` BIGINT,
    `poll` BIGINT,
    `children` Array<BIGINT>,
    `url` String,
    `score` INT,
    `title` String,
    `parts` Array<INT>,
    `descendants` INT,
    INDEX idx_comment (`comment`) USING INVERTED PROPERTIES("parser" = "english") COMMENT 'inverted index for comment'
)
DUPLICATE KEY(`id`)
DISTRIBUTED BY HASH(`id`) BUCKETS 10
PROPERTIES ("replication_num" = "1");
           

注:對于已經存在的表,也可以通過 ADD INDEX idx_comment ON hackernews_1m(`comment`) USING INVERTED PROPERTIES("parser" = "english")來增加索引。值得一提的是,和 Doris 原先存儲在 Segment 資料檔案中的智能索引和二級索引相比,增加反向索引的過程隻會讀 comment 列建構新的反向索引檔案,不會讀寫原有的其他資料,效率有明顯提升。

  1. 導入資料後查詢,使用 MATCH_ALL 在 comment 這一列上比對 OLAP 和 OLTP 兩個詞,和 LIKE 掃描硬比對相比,查詢性能有十餘倍的提升。(這僅是 100 萬條資料下的測試效果,而随着資料量增大、性能提升越明顯)
mysql> SELECT count() FROM hackernews_1m WHERE comment LIKE '%OLAP%' AND comment LIKE '%OLTP%';
+---------+
| count() |
+---------+
|      15 |
+---------+
1 row in set (0.13 sec)

mysql> SELECT count() FROM hackernews_1m WHERE comment MATCH_ALL 'OLAP OLTP';
+---------+
| count() |
+---------+
|      15 |
+---------+
1 row in set (0.01 sec)
           

更多詳細功能介紹和測試步驟可以參考Apache Doris 反向索引官方文檔 。

總結

通過内置高性能反向索引,Apache Doris 對于字元串類型的全文檢索和普通數值、日期等類型的等值、範圍檢索具有更高效的支援,進一步提升了資料查詢的效率和準确性,對于大規模日志資料查詢分析有了更好的性能表現,為需要檢索能力的使用者提供了更高成本效益的選擇。

目前反向索引已經支援了 String、Int、Decimal、Datetime 等常用 Scalar 資料類型和 Array 數組類型,後續還會增加對 JSONB、Map 等複雜資料類型的支援。而 BKD 索引可以支援多元度類型的索引,為未來 Doris 增加 GEO 地理位置資料類型和索引打下了基礎。與此同時 Apache Doris 在半結構化資料分析方面還有更多能力擴充,比如自動根據導入資料擴充表結構的 Dynamic Table、豐富的複雜資料類型(Array、Map、Struct、JSONB)以及高性能字元串比對算法等。

除反向索引以外,Apache Doris 在 2.0.0 Alpha 版本()中還實作了單節點數萬 QPS 的高并發點查詢能力、基于對象存儲的冷熱資料分離、基于代價模型的全新查詢優化器以及 Pipeline 執行引擎等,歡迎大家下載下傳體驗。高并發點查詢的詳細介紹可以檢視 SelectDB 技術團隊過往釋出的技術部落格,其他功能的使用介紹請參考社群官方文檔,同時也敬請持續關注我們後續釋出的特性解讀系列文章。

為了讓使用者可以體驗社群開發的最新特性,同時保證最新功能可以收獲到更廣範圍的使用回報,我們建立了 2.0.0 版本的專項支援群,歡迎廣大社群使用者在使用最新版本過程中多多回報使用意見,幫助 Apache Doris 持續改進,通過此處填寫申請加入專項支援群(https://wenjuan.feishu.cn/m/cfm?t=sF2FZOL1KXKi-m73g)。