2023 年 3 月,在阿里云瑶池数据库峰会上,阿里云与飞轮科技正式达成战略合作协议,双方旨在共同研发名为“阿里云数据库 SelectDB 版”的新一代实时数据仓库,为用户提供在阿里云上的全托管服务。
SelectDB 是飞轮科技基于 Apache Doris 内核打造的聚焦于企业大数据实时分析需求的企业级产品。因此阿里云数据库 SelectDB 版也延续了 Apache Doris 性能优异、架构精简、稳定可靠、生态丰富等核心特性,同时还融入了云服务随需而用的特性,通过云原生存算分离的创新架构,为企业带来分钟级弹性伸缩、高性价比、简单易用、安全稳定的一键式云上实时分析体验。
为了更深度的了解阿里云数据库 SelectDB 版,我们可以全面多角度的了解 Apache Doris 的应用实践和经验。
导读:作为网易重要的业务线,灵犀办公和云信针对大规模日志/时序数据处理和分析的挑战,分别构建了灵犀 Eagle 监控平台和云信数据平台。本文将重点介绍 Apache Doris 在网易日志和时序场景中的应用,如何使用 Apache Doris 替换 Elasticsearch 和 InfluxDB,从而实现更低的服务器资源以及更高的查询性能体验,相较于 Elasticsearch,Apache Doris 查询速度至少提升 11 倍,存储资源的节省高达 70%。
随着信息技术的飞速发展,企业数据量呈现爆炸式增长。对于像网易这样规模庞大的互联网公司,无论是内部办公系统还是外部提供的服务,每天都会产生大量的日志和时序数据。这些数据已成为故障排查、问题诊断、安全监测、风险预警以及用户行为分析及体验优化的重要基石。充分挖掘这些数据的价值,有利于提升产品的可靠性、性能、安全性以及用户满意度。
灵犀办公和云信作为网易重要的业务线,分别构建了灵犀 Eagle 监控平台、云信数据平台来应对大规模日志/时序数据在处理分析时带来的挑战。而随着业务的持续扩张,日志/时序数据也呈井喷式增长,随之带来的是存储成本增高,查询时间延长、系统稳定性变差等问题。早期的平台已难以为继,这促使网易寻找更加优质的解决方案。
本文将聚焦于 Apache Doris 在网易日志和时序类场景中的落地,分别介绍 Apache Doris 在网易灵犀办公、网易云信业务中的架构升级实践,并结合实际场景分享建表、导入、查询等方面的调优方案。
早期架构及痛点
01 灵犀 - Eagle 监控平台
网易灵犀办公是全新一代邮件协同办公平台。整合了邮箱、日历、云文档、即时消息、客户管理等模块。Eagle 监控平台是一个全链路 APM 系统,可为网易灵犀办公提供多维度、不同粒度的性能分析。
Eagle 监控平台主要对灵犀办公、企业邮、有道云笔记、灵犀文档等业务日志数据进行存储分析,日志数据首先通过 Logstash 采集并处理,然后存储到 Elasticsearch 中,由 Elasticsearch 进行实时日志检索及分析,并为灵犀办公提供日志搜索以及全链路日志查询等服务。
随着时间的推移、日志数据的增长,在使用 Elasticsearch 的过程中逐渐暴露出一些问题:
- 查询延迟高:在日常查询中,Elasticsearch 平均响应延迟较高,影响使用体验。这主要受到数据的规模、索引设计的合理性以及硬件资源等因素的制约。
- 存储成本高:在降本增效的大背景下,业务对降低存储成本的需求日益迫切。但由于 Elasticsearch 存在正排、倒排、列存等多份数据存储,数据冗余程度较高,给降本提效带来了一定的挑战。
02 云信 - 数据平台
网易云信是集网易 26 年技术打造的融合通信与云原生PaaS 服务专家,提供融合通信与云原生核心产品及解决方案,包含 IM 即时通讯、视频云、短信,及轻舟微服务、中间件 PaaS 等。
云信数据平台主要是对 IM、RTC、短信等服务所产生的时序数据进行分析。早期数据架构主要基于时序数据库 InfluxDB 搭建,数据源首先通过 Kafka 消息队列进行上报 ,经字段解析和清洗之后,存储到时序数据库 InfluxDB 中,以提供在线和离线查询。离线侧支持离线 T+1 数据分析,实时侧需提供指标监控报表及账单的实时生成。
在客户规模的快速覆盖下,上报的数据源也持续增加,InfluxDB 同样面临一系列新的挑战:
- 内存溢出 OOM:随着数据源的增多,需要基于多个数据源进行离线分析,分析难度随之增加。受限于 InfluxDB 的查询能力,当前架构在面对多个数据源的复杂查询时,可能会导致内存溢出( OOM),这给业务的可用性及系统的稳定性带来巨大的挑战。
- 存储成本高:业务的发展也带来集群数据量的不断增长,而集群中较大比例数据为冷数据,冷热数据采用同一种方式进行存储,导致了高昂的存储成本,这与降本增效的企业目标相悖。
核心引擎的选型
为此网易开始寻找新的数据库解决方案,旨在解决上述两大业务在日志时序类场景所面临的挑战。同时,网易期望只用一个数据库,能够适配两大应用场景的业务体系及技术架构,满足极简易用、低成本投入的升级需求。在这方面,Apache Doris 符合我们的选型要求,具体表现在以下几个方面:
- 存储成本优化:Apache Doris 在存储结构上面进行了许多优化,减少了冗余存储。具有更高的压缩比,且支持基于 S3、NOS (网易对象存储服务 Netease Object Storage)的冷热分层存储,可有效降低存储成本,提高数据存储效率。
- 高吞吐高性能:Apache Doris 支持列式存储高性能磁盘写入、时序 Compaction 以及 Stream Load 高效流式导入,能够支持每秒数十 GB 的数据写入。这样既能保证日志数据的大规模写入,同时还能够提供低延迟的查询可见性。
- 实时日志检索:Apache Doris 不仅能够支持日志文本的全文检索,还能够实现实时查询响应。Doris 支持在内部增加倒排索引,可以满足字符串类型的全文检索和普通数值/日期等类型的等值、范围检索,同时可进一步优化倒排索引的查询性能、使其更加契合日志数据分析的场景需求。
- 支持大规模租户隔离: Doris 可承载数千数据库以及数万数据表,并能够实现一个租户独立使用一个数据库,满足多租户数据隔离的需求,保证了数据的隐私性和安全性。
除此之外,近一年以来, Apache Doris 在日志场景持续深耕,推出了一系列核心能力,如高效的倒排索引、灵活的 Variant 数据类型等,为日志/时序数据的处理分析提供了更高效、灵活的解决方案。综合以上优势,网易最终决定引入 Apache Doris 作为全新架构核心引擎。
基于 Apache Doris 的统一日志存储和分析平台
01 灵犀 - Eagle 监控平台
首先,在灵犀办公 - Eagle 监控平台中,网易成功将 Elasticsearch 全面升级为 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 云信-数据平台
在云信数据平台中,网易同样使用 Apache Doris 替代了早期架构中的时序数据库 InfluxDB,将其作为数据平台核心存储和计算引擎,由 Apache Doris 统一提供离线和实时查询服务。
- 支持高吞吐写入:线上平均 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 建表优化
数据库 Schema 的设计对于性能至关重要,而在处理日志和时序数据时也不例外。Apache Doris 针对这两种场景提供了一些专门的优化选项,因此在表的创建过程中启用这些优化选项非常关键。以下是我们在实践中使用到的具体优化选项:
- 当使用 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 集群配置优化
FE 配置
# 开启单副本导入提升导入性能
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
BE 配置
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 导入调优
云信 - 数据平台在业务高峰期时,面临着高达 100 万以上的写入 TPS 以及 1GB/s 的写入流量,这无疑对系统性能提出了极高的要求。然而,由于业务侧存在众多小并发的表,且查询侧对数据的实时性要求极高,这使得在短时间内无法将批处理积攒到足够大的 Batch。联合业务方进行系列优化后, Stream Load 仍然难以迅速消费 Kafka 中的数据,导致 Kafka 中的数据积压现象日益严重。
经过深入分析,发现在业务高峰期,业务侧的数据导入程序已遭受性能瓶颈,主要体现在 CPU 和内存资源的过度占用。然而,Doris 侧的性能状况尚未出现显著的瓶颈,但 Stream Load 的响应时间却有明显的上升趋势。
由于业务程序是同步调用 Stream Load 的,这意味着 Stream Load 的响应速度直接影响着整体的数据处理效率。因此,如果能够有效降低单个 Stream Load 的响应时间,那么整个系统的吞吐能力将得到显著提升。
在与 Apache Doris 社区同学交流之后,了解到针对日志和时序场景,Doris 推出了两个重要的导入性能优化:
- 单副本导入:先写入一个副本,其他副本从第一个副本拉取数据。这种方式可避免多个副本重复排序、构建建索引所带来的开销。
- 单 Tablet 导入:相较于普通模式下数据分散到多个 Tablet 的写入方式,可采用一次仅写入单个 Tablet 的策略。这种优化减少了写入时产生的小文件数量和 IO 开销,进而提升了整体的导入效率。可在导入时设置
load_to_single_tablet
参数为true
来启用这一功能。
在使用上述方式优化后,导入性能得到显著的提升:
- 消费 Kafka 速度提升超 2 倍
- Kafka 的延迟时间显著下降,仅为原先耗时的 1/4
- Stream Load 的 RT 减少约 70%
网易在正式上线前也开展了大压力测试和灰度试运行,经过持续不断的调优工作,最终确保系统能够在大规模场景下稳定上线运行,为业务提供强有力的支持。
1. Stream Load 超时:
在压测初期出现数据导入频繁超时报错的问题,且在进程及集群状态正常的情况下,监控无法正常采集 BE 的 Metrics 数据。
通过 Pstack 获得 Doris BE 的堆栈,并使用 PT-PMT 对堆栈进行分析。发现主要原因是当客户端发起请求时,没有设置 HTTP Chunked 编码 也没有设置 Content-Length,这导致 Doris 误认为数据传输尚未结束,从而一直处于等待状态。在客户端添加 Chunked 编码设置后,数据导入恢复正常。
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 操作失败。
当 Doris 系统检测到这种异常情况时,会将该磁盘标记为不可用状态。由于该表的配置是单副本策略,当唯一的副本所在磁盘出现问题时,就会因为副本数不足而无法继续写入数据。
因此,将进程 FD 最大打开限制调整到了 100 万,并删除be_custom.conf
配置文件、重启该 BE 节点,服务最终恢复正常运行。
4. FE 内存抖动
在业务灰度测试期间,出现无法连接到 FE 的问题。通过查看监控数据,发现 JVM 32G 内存已经耗尽,同时 FE 的 meta 目录下 bdb 文件目录异常膨胀至 50G。
由于业务一直在进行高并发的 Stream Load 数据导入操作,而导入过程中 FE 会记录相关的 Load 信息,每次导入产生的内存信息约为 200K。这些内存信息的清理时间由streaming_label_keep_max_second
参数控制,默认值为 12 小时,将它调小到 5 分钟后 FE 内存不会耗尽,但是运行一段时间后,发现内存按照 1 小时为周期进行抖动,高峰内存使用率达到 80%。分析代码发现清理 label 的线程每隔 label_clean_interval_second
运行一次,默认为 1 小时,把它也调小到 5 分钟后,FE 内存很平稳。
04 查询调优
当灵犀 - Eagle 监控平台在进行查询测试的时候,疑似读取到了不符合匹配条件的结果,这一现象显然不符合预期的检索逻辑。如下图第一条记录:
起初误以为是 Doris 的 Bug,于是尝试搜索类似的 issue 及规避方案。然而,在咨询社区成员并仔细查阅官方文档后,发现问题的根源是对match_all
使用场景的理解存在误区。
match_all
的工作原理是只要存在分词就能进行匹配,而分词是依据空格或标点来进行的。在该案例中,match_all
中的'29'与第一条记录后续内容中的'29'进行了匹配,从而输出了不符合预期的结果。
针对该 Case,正确的方式是使用 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
添加新的索引。这一过程是在已有表上增量进行,无需重写整个表的数据,从而确保了操作的高效性。
相较于 Elasticsearch,Doris 的索引管理方式更为灵活,能够根据业务需求快速添加或删除索引,提供了更大的便利性和灵活性。
结束语
Apache Doris 的引入,有效满足了网易对日志、时序场景的需求,有效解决了网易灵犀办公以及网易云信早期日志处理及分析平台存储成本高,查询效率低等问题。
在实际应用中,Apache Doris 以更低的服务器资源,承载了线上平均 500MB/s 、峰值超 1GB/s 的写入流量的平稳写入。同时,查询响应也得到了显著的提升,相较于 Elasticsearch ,查询效率至少提升了 11 倍。此外,Doris 具备更高的压缩比,存储资源相较之前可节约 70%。
最后,特别感谢 SelectDB 技术团队一直以来的支持。未来,网易将继续推广 Apache Doris,将其深入应用于网易其他大数据场景中。同时,也期待能与更多对 Doris 感兴趣的业务团队展开深入交流,共同推动 Apache Doris 发展。