作者:肖康,SelectDB 技術 副總裁 、Apache Doris Committer
日志資料是企業大資料體系中重要的組成部分之一,這些資料記錄了網絡裝置、作業系統以及應用程式的詳細曆史行為,蘊含了豐富的資訊價值,在可觀測性、網絡安全、業務分析等關鍵業務領域發揮着重要作用,可幫助企業更好了解系統及業務運作情況,及時發現及解決問題,以保障系統安全穩定運作。具體而言,日志資料可以通過以下方式為企業帶來價值:
- 可觀測性:日志是可觀測性的三大基石(Logging,Metrics,Tracing)之一,其資料規模占比最高,常用于監控告警、故障排查時快速檢索、Trace 關聯等,可保證系統穩定運作、提升運維效率;
- 網絡安全:日志記錄了網絡和主機上發生的每一個事件和行為,用于安全分析、調查驗證、安全檢測等,是提升系統安全性、降低被攻擊風險的重要手段;
- 業務分析:在常見的業務分析中,比如在使用者行為分析和使用者畫像等場景中,通常需要對使用者行為日志進行複雜分析,幫助企業了解使用者的喜好和行為軌迹,進一步提高使用者滿意度、促進留存和轉化。是以日志不僅用于運維和安全保障,對于業務增長也發揮着不可或缺的作用。
日志資料本質是一系列系統事件的有序記錄,其生成方式和使用場景決定了具備以下幾個特點:
- Schema Free:日志資料最初始的表現形态為非結構化原始日志,以 Free Text 的形式存在,然而非結構化資料是不便于進行聚合統計等分析操作的。如果想對這些資料進行存儲分析,就需要先通過 ETL 将非結構化資料加工為結構化表格,再在資料庫/資料倉庫中進行分析。而在這個過程中,當日志結構發生變化時,還需要對 ETL 和結構化表格進行相應的調整,這就需要研發和 DBA 團隊的協助,流程複雜、耗費時間長且執行難度高。在此之後進一步誕生了以 JSON 為主的半結構化日志,日志生成者可以自主增減字段,日志存儲系統根據資料調整存儲結構。
- 資料量大:日志資料規模通常非常龐大并生産周期不間斷,特别是在大型企業或典型的日志應用中,每天産生的日志資料可達十 TB 或百 TB級别。同時為了滿足業務需求或符合監管要求,日志資料往往需要存儲半年甚至更長時間,存儲總量經常達到 PB 級别,為各企業帶來高昂的存儲成本。而随着時間的推移,日志資料的價值也在逐漸下降,是以對于日志系統來說,存儲成本也變的更加敏感。
- 實時寫入與檢索:日志資料常用于故障排查、安全追蹤等時效要求較高的場景,是以如果資料寫入延遲過高,就無法及時擷取最新發生的事件;如果關鍵字檢索響應慢則無法滿足工程師、分析師的互動式分析需求。是以對于日志系統而言,要求在高吞吐寫入的前提下保證秒級以下的查詢響應時間,并能夠提供全文檢索的能力以及秒級響應的互動式查詢能力。
為了應對以上需求、發揮出日志資料的更高價值,業界對于日志場景有不少解決方案,而以 Elasticsearch 為核心的 ELK 體系則是其中典型代表。在此我們以 Elasticsearch 為例,來分享基于 Elasticsearch 的日志系統架構是如何面臨挑戰。
基于 Elasticsearch 的日志系統挑戰
基于 Elasticsearch 的日志系統典型架構如上圖所示,整個系統分為下面幾個子產品:
- 日志收集:通過 Filebeat 采集本地的日志檔案,寫入到 Kafka 消息隊列;
- 日志傳輸:使用 Kafka 消息隊列集中和緩存日志;
- 日志轉換:LogStash 消費 Kafka 中的日志,進行資料過濾、格式轉換等操作;
- 日志存儲:LogStash 将日志以 JSON 格式寫入 ES 存儲中;
- 日志查詢:通過 Kibana 可視化查詢 ES 中的日志,或者通過 ES DSL API 發起查詢請求;
基于 Elasticsearch 的日志系統架構具有較好的實時日志檢索能力,然而該系統在實際應用中也存在一些痛點,如寫入吞吐低、存儲成本高、不支援複雜查詢等問題。
Schema Free 支援不夠
Elasticsearch 的 Index Mapping 定義了資料的 Schema,包括字段的名字、資料類型、是否建索引等。
Elasticsearch 的 Dynamic Mapping 可以根據寫入的 JSON 資料自動增加 Mapping 中的字段,對日志資料的Schema Free 提供了一定程度的支援,但是也存在明顯不足:
- Dynamic Mapping 性能差:當遇到髒資料時容易出現大量字段,嚴重影響系統性能和穩定性。
- 字段類型固定:當業務類型變更時無法進行修改,為了滿足不同的業務需求,使用者常常使用 text 類型來相容,但是 text 類型的查詢性能是遠不如 integer 等二進制類型的查詢性能。
- 字段的索引固定:無法根據需求自行增加或删除某個字段的索引,靈活性較差。是以使用者為了保證查詢過濾的速度,通常會在所有字段上都建立索引。而在所有字段上建立索引又會帶來寫入速度變慢、存儲空間增加等新的問題。
分析能力弱
Elasticsearch 開發的 ES DSL(Domain Specific Language,特定領域語言)與大多數工程師、資料分析師熟悉的技術棧差異比較大,這為使用者設定了較高的學習和使用門檻,并需要學習大量的多新的概念和文法,即使學會之後還需要經常查閱手冊才能寫出正确的 DSL 語句。同時,Elasticsearch 生态自成體系、比較封閉,與其他系統如 BI 工具等打通比較困難。更重要的是, Elasticsearch 分析能力較弱,隻支援簡單的單表分析,不支援多表 ****JOIN、子查詢、視圖等複雜分析,無法滿足企業日志分析需求。
成本高,成本效益低
基于 Elasticsearch 的日志系統使用成本較高也是一個被使用者長期诟病的問題,成本主要來源于兩個方面:
- 寫入的計算成本:Elasticsearch 在寫入時要建構反向索引,會進行分詞、倒排表排序等計算密集型操作,CPU 資源占用較大,單核寫入性能在 2MB/s 左右。當一個 Elasticsearch 叢集的大多數 CPU 資源都被寫入消耗時,在遇到寫入流量高峰時極易觸發寫入 Reject,進而導緻資料延遲變長、查詢速度變慢。
- 資料的存儲成本:為加速檢索和分析的速度,Elasticsearch 存儲了原始資料正排、反向索引、Docvalue 列存等多份資料,是以造成存儲成本大幅增高,且單副本存儲的壓縮率整體被限制在 1.5 倍左右,遠低于日志資料常見的 5 倍壓縮比。
而随着資料和叢集規模增長, Elasticsearch 叢集還面臨一些穩定性問題:
- 寫入不穩定:當遇到寫入高峰時,将造成叢集負載高的問題,進而影響寫入的穩定性。
- 查詢不穩定:由于查詢都在記憶體中處理,大查詢容易觸發 JVM OOM,進而影響整個叢集的寫入和查詢的穩定性。
- 故障恢複慢:Elasticsearch 叢集在故障後恢複時需要進行 Index 加載等資源占用較大的操作,是以故障恢複時間經常需要數十分鐘,對服務可用性和 SLA 提出了很大的挑戰。
基于 Apache Doris 建構新一代日志分析系統
從以上方案對可知,基于 Elasticsearch 的日志系統架構在應用中無法同時兼顧高吞吐、低存儲成本和實時高性能的要求,且不支援複雜查詢。那麼是否有其他方案可以較好的平衡成本與性能,且能提供更好的分析能力呢?答案是有的。
立志于通過一個系統解決多個場景的資料分析問題、降低複雜技術展帶來的運維和使用成本,為了更加契合日志資料分析的場景需求,Apache Doris 在 2.0 版本中引入了多項功能優化:例如支援原生的半結構資料類型,優化了 Text 比對速度和文本算法,進而提升了日志資料導入和查詢的性能;增加了反向索引、以滿足字元串類型的全文檢索和普通數值/日期等類型的等值、範圍檢索。最終通過 Benchmark 測試和實際應用驗證表明, 基于 Apache Doris 建構的新一代日志分析系統相較于 Elasticsearch 具有最高 10 倍的成本效益提升。
基于 Apache Doris 的日志系統典型架構如下圖所示,相較于 Elasticsearch 整個系統架構更加開放:
- 更多日志接入方式:Doris 提供了多種日志資料的導入方式。例如支援 LogStash 通過 HTTP Output 将日志推送到 Doris、支援使用 Flink 對日志進行加工後再寫入 Doris,支援 Routine Load 和 S3 Load 導入存儲在 Kafka 或者對象存儲中的日志資料。
- 統一存儲消除資料孤島:日志資料可以統一存儲到 Doris 中,并可以和數倉中其他資料進行關聯分析,不再是獨立存在的資料孤島。
- 開放生态,更強分析能力:Doris 相容 MySQL 協定,各類資料分析工具或者用戶端可以通過 MySQL 連接配接到 Doris ,包括可觀測性系統 Grafana、常見的 BI 分析工具 Tableau 等。應用程式也可以通過 JDBC、ODBC 等标準 API 來連接配接 Doris ,以進行業務特定的查詢分析。後續我們還将完成類似于 Kibana 的可視化日志探索分析系統,進一步提升日志分析的體驗。
除此之外,基于 Apache Doris 的日志系統還具備以下幾個重要的優勢:
原生的半結構化資料支援
為了更好的适應 Text、JSON 格式日志 Schema Free 的特點,Apache Doris 在這兩個方面進行了增強:
- 提供豐富的資料類型:優化已有 Text 的資料類型,通過向量化技術提升字元串查找、正則比對的性能,通過這些優化實作性能提升 2-10倍;增加 JSON 資料類型,在資料寫入對 JSON字元串進行解析并存儲成緊湊高效的二進制格式,可使得查詢性能提升 4 倍;增加 Array Map 複雜資料類型,将原本使用字元串拼接的複雜類型結構化,進一步提升了存儲壓縮率和查詢性能。
- 支援 Schema Evolution:與 Elasticsearch 不同的是,Apache Doris 支援根據業務需要對 Schema 進行調整,包括按需線上增減字段、增減索引、更改字段資料類型等。
- Apache Doris 推出的 Light Schema Change 功能可以根據資料變化進行毫秒級增減字段:
- -- 增加列,毫秒級傳回,立即生效 ALTER TABLE lineitem ADD COLUMN l_new_column INT;
- 通過 Light Schema Change 還可以按需增加反向索引,無需為所有字段建立索引,避免不必要的寫入和存儲開銷。Doris 在增加索引時,預設對新寫入資料生成索引,并可以對曆史資料選擇對哪些分區生成索引,使用者可靈活控制。
-- 增加反向索引,毫秒級傳回,新寫入資料自動生成索引
ALTER TABLE table_name ADD INDEX index_name(column_name) USING INVERTED;
-- 曆史partition可以按需BUILD INDEX,背景增量生成索引
BUILD INDEX index_name ON table_name PARTITIONS(partition_name1, partition_name2);
基于 SQL 的分析引擎
Apache Doris 支援标準 SQL、相容 MySQL 協定和文法,是以基于 Doris 的日志系統能夠使用 SQL 進行日志分析,這使得日志系統具備以下優勢:
- 簡單易用:工程師和資料分析師對于 SQL 非常熟悉,經驗可以複用,不需要學習新的技術棧即可快速上手。
- 生态豐富:MySQL 生态是資料庫領域使用最廣泛的語言,是以可以與 MySQL 生态的內建和應用無縫銜接。 Doris 可以利用 MySQL指令行與各種 GUI 工具、BI 工具等大資料生态結合,實作更複雜及多樣化的資料處理分析需求。
- 分析能力強:SQL 語言已經成為資料庫和大資料分析的事實标準,它具有強大的表達能力和功能,支援檢索、聚合、多表 JOIN、子查詢、UDF、邏輯視圖、物化視圖等多種資料分析能力。
相對于 Elasticsearch 5-10 倍成本效益提升
經過 Benchmark 測試及生産驗證,基于 Apache Doris 高性能基礎引擎針對日志場景進行優化後,日志系統成本效益相對于 Elasticsearch 具有 5-10 倍的提升。
- 寫入吞吐提升:Elasticsearch 寫入的性能瓶頸在于解析資料和建構反向索引的 CPU 消耗。相比之下,Doris 進行了兩方面的寫入優化:一方面利用 SIMD 等 CPU 向量化指令提升了 JSON 資料解析速度和索引建構性能;另一方面針對日志場景簡化倒了排索引結構,去掉日志場景不需要的正排等資料結構,有效降低了索引建構的複雜度。
- 存儲成本降低:Elasticsearch 存儲瓶頸在于正排、倒排、Docvalue 列存多份存儲和通用壓縮算法壓縮率較低。相比之下,Doris 在存儲上進行了以下優化:去掉正排,縮減了30%的索引資料量;采用列式存儲和 ZSTD 壓縮算法,壓縮比可達到 5-10 倍,遠高于 Elasticsearch 的 1.5 倍;日志資料中冷資料通路頻率很低,Doris 冷熱分層功能可以将超過定義時間段的日志自動存儲到更低的對象存儲中,冷資料的存儲成本可降低 70% 以上。
我們在 Elasticsearch 提供的官方性能 Benchmark Rally 的 HTTP Logs 測試集上進行了對比測試。如下圖可知,Doris 寫入速度是 Elasticsearch 的 5 倍,存儲空間減少了 80%,達到 550 MB/s,寫入後的資料壓縮比接近 1:10、存儲空間節省超 80% ,查詢耗時下降 57%、查詢性能是 Elasticsearch 的 2.3 倍。加上冷熱資料分離降低冷資料存儲成本,整體相較 Elasticsearch 實作 10 倍以上的成本效益提升。
使用者實踐
在使用者實際場景的驗證中,Doris 也表現出了超出預期的成本效益優勢。例如,某遊戲公司最初使用的是 Elasticsearch,通過标準的 ELK 進行日志分析,使用成本非常高。由于存儲成本過高,使得該公司在日志資料的合理存儲和高效分析受到了很大的限制,無法滿足業務需求。而在使用 Doris 搭建日志系統後,所需存儲空間僅是 Elasticsearch 的 1/6,極大的降低了存儲成本。同時 Doris 的高性能和優秀的分析能力,也使得該公司能夠更高效靈活的處理日志資料,并提供更好的業務支援。此外,某安全公司利用 Doris 提供的反向索引建構了日志分析系統,僅使用原來 1/5 的伺服器,承載了 30 萬每秒的寫入流量,導入及查詢速度更快。Doris 的引入,不僅降低了該公司營運成本,也極大的提升了分析的效率及系統穩定性,為業務提供了強有力的支援
實踐指南
下面為大家介紹基于 Apache Doris 建構新一代日志系統的實踐步驟。
首先需要在 Apache Doris 官網:https://doris.apache.org/zh-CN/download 下載下傳 2.0 及以上版本;下載下傳完成後參考部署文檔進行叢集部署:https://doris.apache.org/zh-CN/docs/dev/install/standard-deployment
- 建表
參考下面的例子建表,關鍵點如下:
- 使用 DATETIMEV2 類型的時間字段作為 Key,在查詢最新 N 條日志時有明顯加速
- 對經常查詢的字段建立索引,對需要全文檢索的字段指定分詞器 Parser 參數
- 分區使用時間字段上的 RANGE 分區,開啟動态 Partiiton 可按天自動管理分區
- 分桶使用 RANDOM 随機分桶,使用 AUTO 可讓系統根據叢集規模和資料量自動計算分桶數量
- 使用冷熱分離配置 log_s3 對象存儲和 log_policy_1day 超過1天轉存 s3 政策
CREATE DATABASE log_db;
USE log_db;
CREATE RESOURCE "log_s3"
PROPERTIES
(
"type" = "s3",
"s3.endpoint" = "your_endpoint_url",
"s3.region" = "your_region",
"s3.bucket" = "your_bucket",
"s3.root.path" = "your_path",
"s3.access_key" = "your_ak",
"s3.secret_key" = "your_sk"
);
CREATE STORAGE POLICY log_policy_1day
PROPERTIES(
"storage_resource" = "log_s3",
"cooldown_ttl" = "86400"
);
CREATE TABLE log_table
(
`ts` DATETIMEV2,
`clientip` VARCHAR(20),
`request` TEXT,
`status` INT,
`size` INT,
INDEX idx_size (`size`) USING INVERTED,
INDEX idx_status (`status`) USING INVERTED,
INDEX idx_clientip (`clientip`) USING INVERTED,
INDEX idx_request (`request`) USING INVERTED PROPERTIES("parser" = "english")
)
ENGINE = OLAP
DUPLICATE KEY(`ts`)
PARTITION BY RANGE(`ts`) ()
DISTRIBUTED BY RANDOM BUCKETS AUTO
PROPERTIES (
"replication_num" = "1",
"storage_policy" = "log_policy_1day",
"deprecated_dynamic_schema" = "true",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-3",
"dynamic_partition.end" = "7",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "AUTO",
"dynamic_partition.replication_num" = "1"
);
- 日志導入
Apache Doris 支援多種資料導入方式,對于實時日志資料,推薦 3 種導入方式:
- 如果日志資料在 Kafka 消息隊列中,配置 Doris Routine Load 可從 kafka 中實時拉取資料。
- 如果之前使用了 Logstash 等工具将日志寫入 Elasticsearch,可以選擇配置 Logstash 通過 HTTP 接口将日志寫入到 Doris 中。
- 如果是自定義的寫入程式,也可以通過 HTTP 接口将日志寫入到 Doris 中。
Kafka 導入
将 JSON 格式的日志寫入 Kafka 消息隊列,建立 Kafka Routine Load,讓 Doris 從 Kafka 中主動拉取資料。示例如下,其中 property.* 配置是非必須的:
-- 準備好kafka叢集和topic log _topic
-- 建立routine load,從kafka log _topic将資料導入log_table表
CREATE ROUTINE LOAD load_log_kafka ON log_db.log_table
COLUMNS(ts, clientip, request, status, size)
PROPERTIES (
"max_batch_interval" = "10",
"max_batch_rows" = "1000000",
"max_batch_size" = "109715200",
"strict_mode" = "false",
"format" = "json"
)
FROM KAFKA (
"kafka_broker_list" = "host:port",
"kafka_topic" = "log _topic",
"property.group.id" = "your_group_id",
"property.security.protocol"="SASL_PLAINTEXT",
"property.sasl.mechanism"="GSSAPI",
"property.sasl.kerberos.service.name"="kafka",
"property.sasl.kerberos.keytab"="/path/to/xxx.keytab",
"property.sasl.kerberos.principal"="[email protected]"
);
建立好 Routine Load 後,可以通過 SHOW ROUTINE LOAD 檢視運作狀态。更多使用說明請參考 https://doris.apache.org/zh-CN/docs/dev/data-operate/import/import-way/routine-load-manual。
Logstash 導入
配置 Logstash 的 HTTP Output,将資料通過 HTTP Stream Load 發送到 Doris。
- lo``gstash.yml 配置 Batch 攢批條數和時間,用于提升資料寫入性能
pipeline.batch.size: 100000
pipeline.batch.delay: 10000
- testlog.conf 日志采集配置檔案中增加一個 HTTP Output、URL 配置 Doris 的 Stream Load 位址。
- 目前因為 Logstash 不支援 HTTP 跳轉,需要配置 BE 位址,不能用 FE 位址。
- Headers 中 Authorization 是 http basic auth ,用指令 echo -n 'username:password' | base64 來計算。
- Headers 中 load_to_single_tablet 參數能夠減少導入的小檔案。
output {
http {
follow_redirects => true
keepalive => false
http_method => "put"
url => "http://172.21.0.5:8640/api/logdb/logtable/_stream_load"
headers => [
"format", "json",
"strip_outer_array", "true",
"load_to_single_tablet", "true",
"Authorization", "Basic cm9vdDo=",
"Expect", "100-continue"
]
format => "json_batch"
}
}
自定義程式導入
參考下面的方式通過 Http Stream Load 接口導入資料到 Doris,關鍵點如下:
- 使用 basic auth 進行 HTTP 鑒權,用指令echo -n 'username:password' | base64 來計算
- 設定http header "format:json",指定資料格式為 JSON
- 設定 http header "read_json_by_line:true",指定每行一個 JSON
- 設定 http header "load_to_single_tablet:true",指定一次寫入一個分桶
- 目前建議寫入用戶端一個 Batch 100MB ~ 1GB,後續版本會通過服務端 Group Commit 降低用戶端 Batch 大小
curl \
--location-trusted \
-u username:password \
-H "format:json" \
-H "read_json_by_line:true" \
-H "load_to_single_tablet:true" \
-T logfile.json \
http://fe_host:fe_http_port/api/log_db/log_table/_stream_load
- 查詢
Doris 支援标準 SQL,可以通過 MySQL客 戶端或者通過 JDBC 等方式連接配接到叢集,然後執行 SQL 進行查詢。
mysql -h fe_host -P fe_mysql_port -u root -Dlog_db
下面是日志分析場景中,常見的幾種查詢。
- 檢視最新的 10 條資料
SELECT * FROM log_table ORDER BY ts DESC LIMIT 10;
- 查詢 clientip 為 '8.8.8.8'的最新 10 條資料
SELECT * FROM log_table WHERE clientip = '8.8.8.8' ORDER BY ts DESC LIMIT 10;
- 檢索 request 字段中有 error 或者 404 的最新 10 條資料,MATCH_ANY 是 Doris 全文檢索的 SQL 文法關鍵字,比對參數中任意一個關鍵字
SELECT * FROM log_table WHERE request MATCH_ANY 'error 404' ORDER BY ts DESC LIMIT 10;
- 檢索 request 字段中有 image 和 faq 的最新 10 條資料,MATCH_ALL 是 Doris 全文檢索的 SQL 文法關鍵字,比對參數中所有的關鍵字
SELECT * FROM log_table WHERE request MATCH_ALL 'image faq' ORDER BY ts DESC LIMIT 10;
總結
Apache Doris 針對日志場景進行了多項優化,最終達到存儲空間節省超 80% 、寫入速度是 Elasticsearch 的 5倍、查詢性能是 Elasticsearch 的 2.3 倍。在冷熱資料分層功能加持下,整體相較 Elasticsearch 實作 10 倍以上的成本效益提升。這些都表明,Apache Doris 已經足夠支撐各企業建構新一代日志系統。
後續反向索引還會增加對 JSON、Map 等複雜資料類型的支援。而 BKD 索引可以支援多元度類型的索引,為未來 Doris 增加 GEO 地理位置資料類型和索引打下了基礎。與此同時 Apache Doris 在半結構化資料分析方面還有更多能力擴充,比如豐富的複雜資料類型(Array、Map、Struct、JSON)以及高性能字元串比對算法等,這些更顯将滿足更加豐富的日志應用場景。
最後,如果該文章所述符合您的使用場景,歡迎大家下載下傳 Apache Doris 2.0 版本進行測試使用,為使用者提供全面的技術支援和服務~如果您在調研、測試以及部署更新 2.0 版本的過程中有任何問題,歡迎戳連結送出問卷資訊「連結」,屆時将由社群核心貢獻者提供 1-1 專項支援。