查询提速 11 倍,资源节省 70%,Apache Doris 在网易日志和时序场景的落地实践
作为网易重要的业务线,灵犀办公和云信针对大规模日志/时序数据处理和分析的挑战,分别构建了灵犀 Eagle 监控平台和云信数据平台。本文将重点介绍 Apache Doris 在网易日志和时序场景中的应用,如何使用 Apache Doris 替换 Elasticsearch 和 InfluxDB,从而实现更低的服务器资源以及更高的查询性能体验,相较于 Elasticsearch,Apache Doris 查询速度至少提升 11 倍,存储资源的节省高达 70%。
作者|网易资深数据内核工程师 隐形(邢颖)
早期架构及痛点
查询延迟高:在日常查询中,Elasticsearch 平均响应延迟较高,影响使用体验。这主要受到数据的规模、索引设计的合理性以及硬件资源等因素的制约。 存储成本高:在降本增效的大背景下,业务对降低存储成本的需求日益迫切。但由于 Elasticsearch 存在正排、倒排、列存等多份数据存储,数据冗余程度较高,给降本提效带来了一定的挑战。
02 云信 - 数据平台
内存溢出 OOM:随着数据源的增多,需要基于多个数据源进行离线分析,分析难度随之增加。受限于 InfluxDB 的查询能力,当前架构在面对多个数据源的复杂查询时,可能会导致内存溢出( OOM),这给业务的可用性及系统的稳定性带来巨大的挑战。 存储成本高:业务的发展也带来集群数据量的不断增长,而集群中较大比例数据为冷数据,冷热数据采用同一种方式进行存储,导致了高昂的存储成本,这与降本增效的企业目标相悖。
核心引擎的选型
存储成本优化:Apache Doris 在存储结构上面进行了许多优化,减少了冗余存储。具有更高的压缩比,且支持基于 S3、NOS (网易对象存储服务 Netease Object Storage)的冷热分层存储,可有效降低存储成本,提高数据存储效率。 高吞吐高性能:Apache Doris 支持列式存储高性能磁盘写入、时序 Compaction 以及 Stream Load 高效流式导入,能够支持每秒数十 GB 的数据写入。这样既能保证日志数据的大规模写入,同时还能够提供低延迟的查询可见性。 实时日志检索:Apache Doris 不仅能够支持日志文本的全文检索,还能够实现实时查询响应。Doris 支持在内部增加倒排索引,可以满足字符串类型的全文检索和普通数值/日期等类型的等值、范围检索,同时可进一步优化倒排索引的查询性能、使其更加契合日志数据分析的场景需求。 支持大规模租户隔离:Doris 可承载数千数据库以及数万数据表,并能够实现一个租户独立使用一个数据库,满足多租户数据隔离的需求,保证了数据的隐私性和安全性。
除此之外,近一年以来, Apache Doris 在日志场景持续深耕,推出了一系列核心能力,如高效的倒排索引、灵活的 Variant 数据类型等,为日志/时序数据的处理分析提供了更高效、灵活的解决方案。综合以上优势,网易最终决定引入 Apache Doris 作为全新架构核心引擎。
基于 Apache Doris 的统一日志存储和分析平台
存储资源节省 70%:得益于 Doris 列式存储和 ZSTD 高压缩比,存储同样的日志数据,Elasticsearch 需要 100T 存储空间,而存储到 Doris 中仅需要 30T 存储空间,存储资源节省 70%。由于存储空间大幅节省,在同样的成本下可以使用 SSD 代替 HDD 存储热数据,又带来更大的查询性能提升。 查询提速 11 倍:新架构以更低的 CPU 资源消耗带来了数十倍的查询效率提升。从下方示意图可知,最近 3 小时、1 天 、7 天的日志检索,Doris 查询耗时保持稳定且均低于 4s,最快可在 1s 内响应。而 Elasticsearch 查询耗时呈现出较大的波动,最长耗时高达 75s,即使最短耗时也需要 6-7s。在更低的资源占用下,Doris 的查询效率至少是 Elasticsearch 的 11 倍。
02 云信 - 数据平台
支持高吞吐写入:线上平均 500M/s、峰值 1GB/s 的写入流量,InfluxDB 使用 22 台服务器,CPU 资源使用率约 50%,而 Doris 仅使用 11 台机器,CPU 使用率约 50%,整体资源消耗仅仅为之前的 1/2。 存储资源节省 67%:使用 11 台 Doris 物理机替换了 22 台 InfluxDB ,存储同样的数据规模,InfluxDB 需要 150T 存储空间,而存储到 Doris 中仅需要 50T 存储空间,存储资源节省 67%。 查询响应快且更稳定:为验证其查询响应速度,随机挑选一个线上 SQL(最近 10min 匹配一个字符串),对该 SQL 连续查询 99 次。从下图可知,Doris(蓝色)的查询性能比 InfluxDB(红色) 更稳定,99 次查询均比较平稳、没有明显波动,而 InfluxD 出现多次异常波动,查询耗时直线上升,查询稳定性受到严重影响。
实践及调优
01 建表优化
当使用 DATETIME 类型的时间字段作为主键 Key 时,查询最新 n 条日志的速度会得到显著提升。 使用基于时间字段的 RANGE 分区,并开启动态 Partiiton ,以便按天自动管理分区,提升数据查询和管理的灵活性。 在分桶策略上,可以使⽤ RANDOM 进行随机分桶,分桶数量大致设置为集群磁盘总数的 3 倍。 对于经常需要查询的字段,建议构建索引以提高查询效率;而对于需要进行全文检索的字段,应指定合适的分词器参数 parser,确保检索的准确性和效率。 针对日志类、时序类场景,使用专门优化过的时序 Compaction 策略。 采用 ZSTD 压缩,可以获得更好的压缩效果,节省存储空间。
CREATE TABLE log
(
ts DATETIME,
host VARCHAR(20),
msg TEXT,
status INT,
size INT,
INDEX idx_size (size) USING INVERTED,
INDEX idx_status (status) USING INVERTED,
INDEX idx_host (host) USING INVERTED,
INDEX idx_msg (msg) USING INVERTED PROPERTIES("parser" = "unicode")
)
ENGINE = OLAP
DUPLICATE KEY(ts)
PARTITION BY RANGE(ts) ()
DISTRIBUTED BY RANDOM BUCKETS 250
PROPERTIES (
"compression"="zstd",
"compaction_policy" = "time_series",
"dynamic_partition.enable" = "true",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-7",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "250"
);
02 集群配置优化
# 开启单副本导入提升导入性能
enable_single_replica_load = true
# 更加均衡的tablet分配和balance测量
enable_round_robin_create_tablet = true
tablet_rebalancer_type = partition
# 频繁导入相关的内存优化
max_running_txn_num_per_db = 10000
streaming_label_keep_max_second = 300
label_clean_interval_second = 300
write_buffer_size=1073741824
max_tablet_version_num = 20000
max_cumu_compaction_threads = 10(cpu的一半)
enable_write_index_searcher_cache = false
disable_storage_page_cache = true
enable_single_replica_load = true
streaming_load_json_max_mb=250
03 Stream Load 导入调优
单副本导入:先写入一个副本,其他副本从第一个副本拉取数据。这种方式可避免多个副本重复排序、构建建索引所带来的开销。 单 Tablet 导入:相较于普通模式下数据分散到多个 Tablet 的写入方式,可采用一次仅写入单个 Tablet 的策略。这种优化减少了写入时产生的小文件数量和 IO 开销,进而提升了整体的导入效率。可在导入时设置 load_to_single_tablet
参数为true
来启用这一功能。
在使用上述方式优化后,导入性能得到显著的提升:
1. Stream Load 超时:
2. Stream Load 单次导入数据量超过阈值:
通过调大streaming_load_json_max_mb
参数到 250M(默认 100M )后解决。
3. 副本不足写入报错:alive replica num 0 < quorum replica num 1
通过show backends
发现有一台 BE 状态异常显示为 OFFLINE。查看对应的be_custom
配置文件,发现其中存在broken_storage_path
。进一步检查 BE 的日志,发现报错信息提示“too many open files”,这意味着 BE 进程打开的文件句柄数量已经超出了系统设定的最大值,从而导致 IO 操作失败。
be_custom.conf
配置文件、重启该 BE 节点,服务最终恢复正常运行。streaming_label_keep_max_second
参数控制,默认值为 12 小时,将它调小到 5 分钟后 FE 内存不会耗尽,但是运行一段时间后,发现内存按照 1 小时为周期进行抖动,高峰内存使用率达到 80%。分析代码发现清理 label 的线程每隔label_clean_interval_second
运行一次,默认为 1 小时,把它也调小到 5 分钟后,FE 内存很平稳。04 查询调优
match_all
使用场景的理解存在误区。match_all
的工作原理是只要存在分词就能进行匹配,而分词是依据空格或标点来进行的。在该案例中,match_all
中的'29'与第一条记录后续内容中的'29'进行了匹配,从而输出了不符合预期的结果。MATCH_PHRASE
进行匹配,MATCH_PHRASE
可以满足文本中的顺序要求。-- 1.4 logmsg中同时包含keyword1和keyword2的行,并且按照keyword1在前,keyword2在后的顺序
SELECT * FROM table_name WHERE logmsg MATCH_PHRASE 'keyword1 keyword2';
在使用MATCH_PHRASE
进行匹配时,建索引时需指定support_phrase
,否则系统会进行全表扫描并进行硬匹配,查询效率较差。
INDEX idx_name4(column_name4) USING INVERTED PROPERTIES("parser" = "english|unicode|chinese", "support_phrase" = "true")
对于已经写入数据的表,若希望启用support_phrase
,可以执行DROP INDEX
来删除旧的索引,随后使用ADD INDEX
添加新的索引。这一过程是在已有表上增量进行,无需重写整个表的数据,从而确保了操作的高效性。
结束语
https://github.com/apache/doris/pull/26958 https://github.com/apache/doris/pull/26410 https://github.com/apache/doris/pull/25082 https://github.com/apache/doris/pull/25075 https://github.com/apache/doris/pull/31882 https://github.com/apache/doris/pull/30654 https://github.com/apache/doris/pull/30304 https://github.com/apache/doris/pull/29268
专项支持
扫/码/加/入/支/持/群
- END-
更多标杆企业信赖
智慧金融与政企:杭银消金|河北幸福消费金融|金融壹账通|平安人寿|奇富科技|同程数科|星云零售信贷|银联商务|招商信诺人寿|360数科 |360企业安全浏览器
互联网与文娱:斗鱼|叮咚买菜|工商信息查询平台|货拉拉|荔枝微课|票务平台|奇安信|腾讯音乐|天眼查|网易互娱|网易严选|小米|小鹅通|约苗|字节跳动|知乎|360商业化
企业服务与新经济:橙联|度言|观测云|慧策|领健|领创|Moka BI|美联物业|拈花云科|上海家化|思必驰|物易云通|云积互动|有赞|纵腾集团