标签 elasticsearch 下的文章

导读:面对万亿级广告数据存量、日均 3 亿行增量及数千个复杂查询模板的挑战,快手广告数据平台如何突破性能瓶颈、实现架构统一与体验跃升?本文系统介绍了快手广告团队从 ClickHouse on ES 混合架构,全面迁移至 Apache Doris 的统一分析实践,最终实现查询性能提升 20~90%,写入吞吐提升 3 倍,存储效率提升 60%。

本文整理自快手高级计算引擎研发工程师 周思闽 在 Doris Summit 2025 中的演讲内容,并以演讲者第一视角进行叙述。

快手是国内日活过亿的短视频平台,其广告投放平台是商业化外部广告主与快手电商商家进行广告投放的主要阵地,支持客户在平台上进行广告物料搭建、物料管理、策略变更、数据查看等操作,这对底层数据系统的存储、计算与查询性能提出了极高要求。

要支撑如此大规模的广告投放与实时分析,底层数据架构面临巨大挑战。当前,快手的广告数据包括:由投放系统产生的物料数据以及用于数据分析的效果数据,这些数据呈现出三个显著特征:

  • 数据存量巨大:广告物料累计已达千亿级别,且随业务发展正向万亿规模迈进,存储体量位居公司前列,对架构扩展性提出极高要求。
  • 数据增长迅猛:仅 2025 年第一季度,日均新增广告物料数据同比激增 3.5 倍,要求底层引擎具备强大的实时写入与弹性扩展能力。
  • 数据模型复杂:整个数据体系涵盖约 700 个核心字段,涉及物料、投放、用户、效果等多个维度;同时,为应对多样化分析场景,沉淀的查询模板已超 4000 个,对查询引擎的兼容性与性能均是严峻考验。

架构演进:从分散存储到统一分析

01 早期架构及挑战

早期存储架构中,物料数据由 MySQL、Elasticsearch 协同存储;效果数据主要存储与 Clickhouse 中。

数据分析时,将分散在 MySQL、Elasticsearch 中的物料数据与 ClickHouse 中的效果数据进行高效关联查询,从而为广告主提供完整、及时的投放效果洞察。

01 早期架构及挑战.PNG

在如上所说的 ClickHouse on ES 架构中,用户提交的查询通常包含 Elasticsearch 外表(a)与 ClickHouse 内表(b)。ClickHouse 会解析查询中外表部分,将其转换为 Elasticsearch 查询语句,通过 HTTP 请求获取数据并封装为 Block,最后在引擎内部完成与内表的关联计算。

01 早期架构及挑战-1.PNG

然而,随着 Elasticsearch 中数据量持续增长,该架构逐渐暴露诸多问题:

  • 查询性能恶化:慢查询率上升至 35%,平均查询耗时达到 1.4 秒;
  • 存储瓶颈:Elasticsearch 单分片难以支撑 10 亿级以上数据量,扩容与数据重分布成本高;
  • 运维复杂度高:数据链路依赖组件多,运维与监控成本显著上升;
  • 问题定位困难:缺少 ClickHouse 与 Elasticsearch 之间的全链路可观测手段,出现查询延迟、数据不一致等问题时,需跨系统排查,耗时较长。

02 选型目标及调研

基于上述问题及挑战,我们为新架构设定了明确目标:

  • 慢查询率低于 5%;
  • 运维排查耗时降低至分钟级;
  • 支持单表万亿级别数据存储;
  • 保障数据实时性,延迟低于 5 分钟。

基于以上目标,我们对 Apache Doris、ClickHouse、Elasticsearch 等主流 OLAP 引擎进行了全面的调研与性能压测。测试涵盖了写入吞吐、查询延迟、存储压缩率、全文检索性能等关键维度。

02 选型目标及调研.png

在这过程中,ClickHouse 首先被排除,因其不支持唯一键模型,而广告物料数据存在大量更新场景,要求引擎具备主键更新能力。因此,重点在 Elasticsearch 与 Apache Doris 之间进行对比。

综合测试结果,Apache Doris 在写入性能、查询效率、存储成本及运维复杂度等方面均表现优异,不仅能够满足既定架构目标,还在多个场景下显著优于 Elasticsearch。因此,我们最终选定 Apache Doris 作为下一代广告数据分析引擎

03 基于 Apache Doris 的统一分析引擎

在实际应用中,我们引入 Apache Doris(计算引擎) 替换了原先架构中的 Elasticsearch、ClickHouse,设计了统一分析引擎 Bleem。通过在外部表模块中引入数据缓存层与元数据服务层,有效提升了跨源查询效率,使数据湖外表的查询性能接近内表水平,实现了关键的性能突破。

03 基于 Apache Doris 的统一分析引擎.png

具体来看,Bleem 架构自下而上分为 5 层

  • 存储层:数据湖中的 Hive/Hudi 数据存储于 HDFS;存算分离模式下的内表数据存放于对象存储 BlobStore;存算一体模式下的内表数据则存储于本地磁盘。
  • 缓存层:将 Hive/Hudi 外部表数据缓存至 Alluxio,保障 I/O 稳定性,提升数据读取效率。
  • 计算层:Apache Doris 为核心引擎。不同项目组对应不同的 Doris 集群,以实现计算资源物理隔离,用户可按需申请计算资源。依托于 Doris 湖仓查询能力,可直接对 Doris 内表与外部 Hive/Hudi 数据查询。同时,Doris 也支持存算一体与存算分离两种部署方式,可根据实际需求灵活选择。
  • 服务层:元数据缓存服务实时监听 Hive 元数据变更,并同步至缓存中,以提升湖仓外部表的查询效率。
  • 接入层:将 OneSQL 作为统一查询接入网关,提供集群路由、查询改写、物化改写、查询鉴权、限流与阻断等功能。

依托 Doris 强大的 OLAP 计算与湖仓一体能力,将此前分散的数据湖分析、实时 OLAP 查询、在线报表及全文检索等多种场景,统一整合至同一套引擎架构中,实现了技术栈的收敛与提效。该架构在实际落地中已带来显著收益:

  • 性能大幅提升:慢查询率低于 5%,整体查询性能提升了 20%~90%
  • 存储扩展高效:支持万亿级别数据存储,水平扩容效率较 Elasticsearch 提升 10 倍以上;
  • 运维大幅简化:一套引擎覆盖全部查询场景,系统依赖组件少,运维复杂度显著降低;
  • 可观测性全面加强:Doris 支持全链路追踪与全面监控,平均问题排查时间降低 80%

迁移实践及调优经验

整个迁移过程分为三个阶段,稳步推进以确保业务平稳过渡:

  • 第一阶段(试点验证):选取关键词推广场景进行试点,跑通全量与增量数据导入流程,搭建双链路并行验证数据一致性与查询正确性。
  • 第二阶段(主体迁移):迁移原 ClickHouse on ES 查询链路,将 Elasticsearch 中全量物料数据导入 Doris,完成业务切换后下线 Elasticsearch 集群。
  • 第三阶段(收尾统一):迁移剩余纯 ClickHouse 场景,将无需关联 Elasticsearch 的查询任务及其数据全部迁移至 Doris,完成整体架构统一。

在架构升级及迁移过程中,我们收获了许多实践及优化经验,在此逐一分享

01 解决极端场景下数据一致性问题

在数据导入层面,我们基于 SeaTunnel 实现流式数据同步,该方式支持批处理场景下的 Overwrite 语义,所有导入均采用两阶段提交机制,以确保数据同步的最终一致性。

而在基于 SeaTunnel 和 Spark 的数据同步过程中,我们遇到了极端场景下的数据重复问题。主要有两种情况:

  • Spark 推测执行时,两个 Task 同时写入同一份数据并均完成 Doris 两阶段提交,尽管 Driver 只认定一个 Task 成功,但数据已重复。
  • Spark Task 完成 Doris 提交后,在向 Driver 汇报前因抢占或异常退出,Driver 重启 Task 并重新写入数据。

为解决该问题,我们在 Doris 的两阶段事务提交环节引入了 ZooKeeper 分布式锁机制,通过记录并校验事务状态来保证批同步的一致性。具体流程如下:

  • 准备提交阶段,先获取 ZooKeeper 临时锁,确保同一时间只有一个事务进入提交流程;
  • 获取锁后,将 Prepare 状态写入 ZooKeeper 临时节点,并记录当前事务 ID;
  • 查询上一个事务的状态:

    • 若不存在,直接提交当前事务;
    • 若上一事务处于 Prepare 状态,则先回滚上一事务,再提交当前事务;
    • 若上一事务已 Commit,则直接回滚当前事务;
  • 最终将 Commit 状态写入 ZooKeeper 持久节点,完成本次提交。

01 解决极端场景下数据一致性问题.png

02 Stream Load 机制优化

为应对高并发数据导入,我们对 Apache Doris 的 Stream Load 机制进行了调优。通过合理配置任务优先级与合并(Compaction)参数,显著提升了写入吞吐与稳定性。Doris 内部通过 Load Channel 进行任务调度,以区分高优与普通优先级通道。

02 Stream Load 机制优化.png

调优的核心在于合理配置相关参数,例如当 Stream Load 任务指定的 timeout 时间小于 300 秒时,系统会将其判定为高优任务并分配至高优通道。参数优化如下

load_task_high_priority_threshold_second=300
compaction_task_num_per_fast_disk=16
max_base_compaction_threads=8
max_cumu_compaction_threads=8

03 差异化的建表策略

OLAP 引擎的查询性能很大程度上取决于表结构设计。因此,我们针对不同业务场景制定了差异化的建表策略:

物料表(高频更新与大规模检索):该表数据量极大且需支持实时更新。业务查询主要基于 account_id 进行过滤,而非原 MySQL 的自增 ID。为充分发挥 Doris 前缀索引与排序键的优势,在保证业务逻辑等价的前提下,我们将 account_idid 组合为联合主键,并将account_id 设为首个排序键及分桶字段,大幅提升查询过滤效率。同时配置倒排索引以支持多维检索,并选用 ZSTD 压缩算法平衡存储与 IO 性能。

-- 建表语句参考
CREATE TABLE ad_core_winfo
(account_id BIGINT NOT NULL,
id BIGINT NOT NULL, 
word STRING,
INDEX idx_word (`word`) USING INVERTED...) 
UNIQUE KEY(account_id,id) 
DISTRIBUTED BY HASH(account_id) BUCKETS 1000;

效果表(多维聚合分析): 相较于物料表,效果表侧重于数仓指标的累加与聚合。因此,我们直接采用聚合模型,并按照“天”或“小时”粒度设置分区。

-- 建表语句参考
CREATE TABLE ad_dsp_report
(__time DATETIME, 
account_id BIGINT, ...
`ad_dsp_cost` BIGINT SUM,
...) 
AGG KEY(__time,account_id,...) 
AUTO PARTITION BY RANGE(date_trunc(`__time`,'hour'))()
DISTRIBUTED BY HASH(account_id) BUCKETS 2;

04 大账户数据倾斜治理

在数据压测中,我们发现不同 Account ID 对应的数据量差异极大,小至个位数、大至百万级别,导致 BE 节点 CPU 负载严重不均。通过 SHOW DATA SKEW 命令进一步确认,Tablet 存储分布明显倾斜:大 Tablet 占用空间达 3–4 GB,小 Tablet 仅 100-200 MB,且大账户查询延迟较高。为此,我们实施了以下两点优化:

A:按账户范围进行分区

经分析,Account ID 为 5–8 位数字,且未来不会超过 10 位。因此使用 FROM_UNIXTIME 函数将 Account ID 转换为 Datetime 类型,按月对历史数据进行分区,共划分出 33 个历史分区。每个分区可容纳 2,592,000 个 Account ID,后续每新增约 200 多万个 Account ID 才会新增一个月份分区。同时,针对历史分区,根据数据存量进行手动分桶,新分区则默认设置为 256 个分桶。

该方案通过分区裁剪有效过滤了大量无关数据,同时为未来数据膨胀预留了扩展空间(物料表日均增量约 3 亿),显著降低分区增长对查询性能的影响。

B:对 Account ID 进行二次哈希

为缓解单个 Account ID 数据量差异过大导致的分布不均,我们选取与 Account ID 无关的 ID 字段,通过 ID MOD 7 计算得到一个取值在 0~6 之间的 mod 字段。将原本仅基于 account_id 的哈希分桶键调整为 (account_id, mod) 联合键,从而将同一 Account ID 的数据分散到 7 个 BE 节点上。

04 大账户数据倾斜治理.png

优化后,各 Tablet 大小基本均衡稳定在 1GB 左右,数据存储与查询负载得以在多个 BE 间均匀分布,有效解决了 此前 CPU 负载不均的问题。

05 万级分区下的查询优化

当分区数量达到万级别时,简单点查 SQL 的耗时达到 250 毫秒,远超 100 毫秒的预期。通过分析,耗时主要集中在 Plan 阶段,原因是 Doris(2.1 版本)在分区裁剪时,会遍历所有分区进行匹配,万级分区的顺序遍历开销巨大。

为此,我们将顺序遍历改为二分查找:对万级分区先进行排序,再利用二分查找快速定位目标分区,将时间复杂度从 O(n) 降至 O(log n)。优化后,该查询耗时从 250 毫秒降至 12 毫秒,性能提升超过 20 倍。目前,二分查找已在 Doris 3.1 版本中实现。

06 并发调优

在查询优化过程中,我们发现:多数查询经过条件过滤后,实际命中的数据量并不大,即便在大账户场景下,命中数据量也仅在百万级别。然而,Profile 显示这类查询的 Total Instance 数高达 800 个,其默认并发数为 32,存在明显的过度并发

为此,我们调整以下参数降低并发开销:

set global parallel_exchange_instance_num=5;
set global parallel_pipeline_task_num=2;

调整后,同一查询的 Total Instance 数量降至 17 个,查询耗时也显著缩短。这说明在小数据量点查场景下,适当降低并发可有效减少 RPC 开销,从而降低延迟(220ms 降至 147ms)。同时,这一优化也提升了系统的整体 QPS 承载能力。

收益及规划

经过上述架构迁移与深度优化,我们在三个核心维度取得了显著收益:

  • 查询性能大幅提升:关键词推广页平均查询延迟下降 64%,创意推广页延迟下降超过 90%,整体查询体验实现跨越式提升。
  • 写入能力显著增强:单节点写入承载能力提升 3 倍以上,单表实时导入峰值突破 300 万行/秒
  • 存储效率优化明显:通过分区策略与 ZSTD 压缩算法,存储效率较 Elasticsearch 提升约 60%,并可轻松支撑万亿级数据存储。

未来,我们将深度探索 Apache Doris ,重点围绕两方面展开:

  • 增强全文检索与分词能力:引入社区在 Doris 4.0 版本中推出的 BM25 打分功能,以及 IK 分词器等更多分词组件,实现按业务场景灵活选用最优分词方案。
  • 增强向量索引:基于 Doris 4.0 版本,在内表和数据湖外表场景下对向量检索的性能和边界能力做验证与优化。

本文完。您还可以阅读来自快手另一篇实践案以及中通快递、小米集团、顺丰科技用户故事来了解湖仓分析。

摘要:
爱奇艺卡券业务原采用 “MySQL 分库分表 + ES 异步同步” 架构,面临 TP/AP 分离导致的架构复杂、AP 查询分钟级延迟、数据一致性隐患等问题。如今借助 OceanBase 的 HTAP 能力,将 AP、TP 业务融合到一个数据库,在架构简化、成本控制与效率提升方面均取得了突破。

爱奇艺是国内知名的在线视频平台,每年都会推出上百部优质长视频内容,其中不乏如 2023 年现象级爆款《狂飙》这样的佳作。近两年,随着短视频、微剧的兴起,平台年处理视频内容数量级从上百部直接跃升至上万部。

每一部内容从立项、拍摄、生产、制作到上线播出,均需经过复杂流程,并依赖上百个业务模块协同支持。卡券业务是出于整个业务生态里面的中台位置,对上提供中台能力,如为创新型业务会员、云影院提供商业化变现和用户转化营销工具。

过去,卡券业务系统将 AP(分析处理)与 TP(事务处理)业务分开处理,架构复杂,需要较高的维护成本;如今,借助 OceanBase 的 HTAP 能力,将 AP、TP 业务融合到一个数据库,在架构简化、成本控制与效率提升方面均取得了突破。

解构卡券业务的数据架构困境

卡券是爱奇艺核心的营销与促销工具,贯穿爱奇艺的会员购买、云影院观影等商业化变现全链路。其底层数据库的性能直接关乎用户体验与业务敏捷性。

例如,促销发券、会员领券等场景均需要业务系统提供高并发事务处理(TP)能力。而在运营侧,则需要实时统计和分析发券数量、会员领券等指标,以便评估活动效果、优化营销策略,这依赖于高效的数据分析(AP)能力。

过去,卡券业务系统采用的是“MySQL 分库分表+ES 异步同步”的复杂架构:分库分表的 MySQL 来承载 TP 业务,以应对高并发海量请求;Elasticsearch(ES)来完成统计分析等 AP 类业务。

“这个卡券业务的架构基本上能为业务需求提供足够的支撑。不过,我们并不满意,一直在寻找新的解决方案。”爱奇艺高级总监张冲表示。

其最重要的原因就在于系统架构过于复杂,虽能满足业务需求,但每一个节点都需要研发投入大量精力维护,顶峰的时候研发资源占比近 80%,严重挤占了业务创新资源。

具体而言,在 TP 业务方面,通过分库分表的 MySQL 集群支撑高并发交易,但实际日常资源利用率仅约 10%,资源冗余明显。在 AP 业务方面,ES 进行运营统计分析时的数据源自订阅多个 MySQL 实例的 binlog,经消息队列 RMQ 异步同步至 ES,链路冗长,存在分钟级延迟。并且 ES 的清理归档代价较高,Reindex 开销也比较大。

此外,数据的一致性与准确性面临挑战,在异步同步过程中,甚至出现过 UV(访客数量)超过页面点击的异常,统计准确率难以保障。

张冲坦言,对现有架构进行升级更深层的原因,源于对技术进步的持续追求。“我们希望技术上再往前走一走,要和互联网行业最先进的技术保持对齐。”

从“分库分表+ES”到“单库双擎”,爱奇艺 HTAP 架构升级实践

随着新技术趋势的出现,爱奇艺也开始寻找能够简化架构、支撑业务更好发展的新发展。数据库的升级是这次架构升级的关键。

对于新一代数据库,爱奇艺提出了明确的要求:

第一,必须是一款兼顾 TP、AP,具备 HTAP 能力的数据库产品,无需管 MQ,无需处理异构的数据,尽量减少对数据平台的依赖,以简化数据底座;

第二,总体成本可控,和现有架构相比成本不能上升,符合公司降本增效的目标;

第三,云中立,在遇到故障的时候可以实现云逃逸,且在不同的云上均可提供一致性的服务。

根据上述三个基本要求,经过对多款主流数据库产品的调研与测试,OB Cloud 一体化云数据库凭借其卓越的性能与高度契合的需求满足度,赢得了爱奇艺的青睐,并且在高并发、高可用、安全、数据治理、低成本等方面的技术积累,都被浓缩到 OB Cloud 一体化云数据库的产品中。

张冲表示:“OceanBase 不仅提供了真正的 HTAP 融合能力,其原生分布式架构还与我们的云原生战略高度契合。同时,OB Cloud 在百度云上开服也是一个重要契机,因为爱奇艺的系统平台就部署在百度云上。”

完成数据库选型之后,爱奇艺迅速开始了数据和架构升级的准备工作。

升级工作分为两个阶段:

AP 升级:将 ES 集群中的百亿文档升级至 OB Cloud 集群。通过双写、迁移历史数据、切读、停双写等步骤,不仅完成数据升级,还从业务层面进行了逻辑去冗余和简化。最终,资源成本下降 60%,运营查询类 SQL 基本在 1 秒内返回。

TP 升级:将 16 个物理机数据库从原生 MySQL 分库分表形态升级至 OB Cloud 集群。借助 OceanBase 的 OMS 同步工具,顺利完成海量数据同步与校验工作。最终,存储成本下降 80%,且系统具备弹性伸缩能力,无需为大促提前预备资源。

张冲表示,为了尽量减少对业务的干扰,保持业务稳定性,升级过程尽可能少地修改代码,他们采取了一些措施:

  1. 汇聚到 OceanBase 的分区表、分区键与原来的分片逻辑一致,使得业务系统零改造切换;
  2. 保持 AP 业务不变,仅修改数据源订阅,通过全兼容的 binlog 直接订阅到同租户的 AP 表。此时还是多份存储,但依靠高压缩比,整体存储成本没有上升;
  3. 将 TP 业务的表异步修改为行列混存,不影响业务稳定性,同时运营统计只需简单修改库和表名即可快速上线。通过多副本读写分离,最终实现了单库双擎、支撑实时在线业务与数据分析的简洁架构。

化繁为简,打造卡券业务的现代化数据库底座

经过升级改造后,卡券业务系统架构变得非常简洁,只有基本的业务服务和数据中台的数据交互,不再需要维护额外的数据流服务,也无需担心存储不足等问题,归档清理的周期也相应延长,研发人员得以更加聚焦于业务需求的开发。

张冲表示,卡券业务系统架构升级带来了如下好处:

首先,链路极大简化。 去除了 MySQL 到 ES 的异步同步链路,消除了 ES 集群的运维与成本;张冲特别感慨此次架构的升级带来的简化,他表示“简单到只有计算、只有存储,简单到有点像互联网刚开始发展的那个阶段。”

其次,分析效率提升。 常规 AP 查询可直接在 OB Cloud 中完成,时间也从原来的准实时变成了实时,所有统计 SQL 的响应时间(RT)均小于 1 秒,性能大幅提升。而 BI 类需求以前需要数据中台部门支持,属于跨部门协作,最快也需数天;现在本部门内部就能完成,时间缩短为 2-3 天;

第三,存储成本显著节省。 借助 OceanBase 的高压缩能力,相比 MySQL 的存储成本下降了 80%,并且它可以弹性伸缩,不再需要提前为大促预备过量资源。

“相对于之前的架构,现在的架构非常简洁。这要得益于 OceanBase 把高并发、高可用、安全、数据治理、低成本等各种技术积累都浓缩到了这个数据库产品中。”张冲这样评价。

小结

张冲表示,未来爱奇艺计划将 OceanBase 的实践推广至更多在线交易型业务,如订单支付、会员中心等,并逐步探索其在 KV 存储、向量检索等场景的应用。

面对 AI 浪潮,张冲也提出了对未来数据库的期待:“知识图谱、AI 工作流等复杂场景,需要更智能的底层数据支撑。希望 OceanBase 能在这些方向持续演进,成为企业智能化转型的数据基石。借助 OceanBase 技术的不断完善和应用场景的拓展,爱奇艺将在科技创新的道路上走得更远。”

欢迎访问 OceanBase 官网获取更多信息:https://www.oceanbase.com/

前言

  • 本文对 Elasticsearch 8.19 适用
  • 在 Elasticsearch 8.19 中,混合搜索(Hybrid Search)主要有两种核心策略

    kNN + Query 组合搜索(通常指线性加权融合)
    RRF(Reciprocal Rank Fusion)搜索
  • 截至 2026.1.21, RRF 功能在 Elasticsearch 8.19 中属于收费功能

正文

  • Elasticsearch 向量搜索通常使用 dense_vector 数据类型
  • Elasticsearch 向量搜索通常使用 kNN 搜索
  • 基本的 kNN 搜索示例 k-nearest neighbor (kNN) search

    POST byte-image-index/_search
    {
      "knn": {
          "field": "byte-image-vector",
          "query_vector": [-5, 9],
          "k": 10,
          "num_candidates": 100
      },
      "fields": ["title"]
    }
  • kNN 中使用 filter 过滤

    POST image-index/_search
    {
      "knn": {
          "field": "image-vector",
          "query_vector": [54, 10, -2],
          "k": 5,
          "num_candidates": 50,
          "filter": {
              "term": {"file-type": "png"}
          }
      },
      "fields": ["title"],
      "_source": false
    }
  • kNN 与 query 组合

    POST image-index/_search
    {
      "query": {
          "match": {
              "title": {
                  "query": "mountain lake",
                  "boost": 0.9
              }
          }
      },
      "knn": {
          "field": "image-vector",
          "query_vector": [54, 10, -2], 
          "k": 5,
          "num_candidates": 50,
          "boost": 0.1
      },
      "size": 10
    }
  • RRF 搜索示例

    GET example-index/_search
    {
      "retriever": {
          "rrf": { 
              "retrievers": [
                  {
                      "standard": { 
                          "query": {
                              "term": {
                                  "text": "shoes"
                              }
                          }
                      }
                  },
                  {
                      "knn": { 
                          "field": "vector",
                          "query_vector": [1.25, 2, 3.5],
                          "k": 50,
                          "num_candidates": 100
                      }
                  }
              ],
              "rank_window_size": 50,
              "rank_constant": 20
          }
      }
    }

相关阅读

本文出自 qbit snap

这是一个基于 Elasticsearch 的游戏 NPC 记忆检索增强生成 (RAG) 系统,支持混合检索、异步索引和 Cloud Run 部署。作为未来可能实现的 ai based npc 的一部分。特点是具有高可拓展性和高并发量,可以撑起来大用户量的使用。

第一次发自己的项目,写得不对的地方还请各位佬友批评指正~


📌 转载信息
转载时间:
2026/1/4 09:57:15

这是一个基于 Elasticsearch 的游戏 NPC 记忆检索增强生成 (RAG) 系统,支持混合检索、异步索引和 Cloud Run 部署。作为未来可能实现的 ai based npc 的一部分。特点是具有高可拓展性和高并发量,可以撑起来大用户量的使用。

第一次发自己的项目,写得不对的地方还请各位佬友批评指正~


📌 转载信息
转载时间:
2026/1/3 21:22:53

简介

Frostmourne(霜之哀伤)是汽车之家经销商技术部监控系统的开源版本,用于帮助监控几乎所有数据库数据(包括Elasticsearch, Prometheus, SkyWalking, MySql 等等)。如果你已经建立起了日志系统, 指标体系,却苦恼于没有一个配套监控系统,也许它能帮到你。

支持数据源:Elasticsearch, HTTP, SkyWalking, Prometheus, InfluxDB, MySQL/TiDb, ClickHouse, SqlServer, PING, IotDB, Telnet

支持告警发送方式:钉钉(机器人)、企业微信(机器人)、飞书机器人、OneMessage机器人、Email、短信、HTTP。(text, markdown)

支持LDAP认证和自动创建用户。

Elasticsearch数据查询、分享和下载

报警消息抑制功能,防止消息轰炸;也有报警升级功能,避免故障相关方长时间得不到通知。

Github地址:https://github.com/AutohomeCorp/frostmourne

环境要求:JAVA8-14、Mysql 8数据库。

教程使用Linux版本:Rocky Linux 8 (关闭SELinux)

版本:部署1.0版本

注意:目前不支持ES8 的加密认证,需要等后期支持JAVA 17

使用ZIP包部署(使用Linux环境)

下载JDK(推荐使用JDK8)

dnf install wget tree
## 安装wget tree

cd /opt
mkdir java1.8
cd /opt/java1.8
wget --execute robots=off -nc -nd -r -l1 -A '*.gz' https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x64/linux/
## 下载OpenJDK8二进制包,源为清华大学源,会自动下载最新版。

tar -zxvf OpenJDK8U-jdk_*.tar.gz 
## 解压

tree -L 2 /opt/java1.8/
/opt/java1.8/
├── jdk8u362-b09
│   ├── ASSEMBLY_EXCEPTION
│   ├── bin
│   ├── include
│   ├── jre
│   ├── lib
│   ├── LICENSE
│   ├── man
│   ├── NOTICE
│   ├── release
│   ├── sample
│   ├── src.zip
│   └── THIRD_PARTY_README
└── OpenJDK8U-jdk_x64_linux_hotspot_8u362b09.tar.gz

7 directories, 7 files


## 查看当前文件树

PS:JDK也可以手动去https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x64/linux/ 目录下进行下载最新版。

部署Mysql(建议为8版本)

dnf install mysql-server

##Rocky 8源默认安装mysql8

systemctl enable --now mysqld

systemctl status mysqld.service 

## 设置开机并启动,查看启动状态
mysql_secure_installation 

## 初始化Mysql


## 如下,都选择Y即可,密码等级选择0,然后配置root密码。


Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No: y

There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 0
Please set the password for root here.

New password: 

Re-enter new password: 

Estimated strength of the password: 50 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done! 

创建数据库导入SQL文件

wget https://github.com/AutohomeCorp/frostmourne/blob/master/doc/mysql-schema/frostmourne.sql

## 可能需要挂国际代理,或浏览器下载,使用SCP上传即可.

mysql -uroot -p < frostmourne.sql

#输入密码即可导入创建数据库。

mysql -uroot -p
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| frostmourne        |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)


#查看数据库是否正常创建, quit命令退出。

下载frostmourne

cd /opt
mkdir frostmourne
cd frostmourne

wget https://github.com/AutohomeCorp/frostmourne/releases/download/1.0-RELEASE/frostmourne-monitor-1.0-RELEASE.zip

## 可能需要挂国际代理,或浏览器下载,使用SCP上传到opt目录即可.
## Github 下载地址 https://github.com/AutohomeCorp/frostmourne/releases

dnf install unzip 

unzip frostmourne-monitor*.zip 

tree 
.
├── application.properties
├── env
├── frostmourne-monitor-1.0-RELEASE.jar
├── frostmourne-monitor-1.0-RELEASE.zip
└── scripts
    ├── shutdown.sh
    └── startup.sh

1 directory, 6 files
## 文件树如上。

修改ENV 环境文件,配置java路径

vim /opt/frostmourne/env 


JAVA_HOME=/opt/java1.8/jdk8u362-b09
##配置文件上面操作解压的JDK路径即可

JAVA_OPTS="-Xms1200m -Xmx2000m -Xss1024K -XX:PermSize=128m -XX:MaxPermSize=256m -Dfile.encoding=utf-8"
##JAVA参数,可适当改大内存等参数。

修改启动app配置(也可以配置邮件发送服务器和LDAP)

vim /opt/frostmourne/application.properties 

alarmlog_reserve_days=30
#配置监控日志保留天数

datasource_frostmourne_url=jdbc:mysql://127.0.0.1:3306/frostmourne?characterEncoding=utf8
#配置mysql数据库IP地址、数据库名字、编码。

datasource_frostmourne_username=root
datasource_frostmourne_password=Wow@123
#配置mysql数据库账号密码


frostmourne_monitor_address=192.168.124.100

#配置为本机IP地址即可

frostmourne_message_title=Wow
#配置实例名字

启动测试

/opt/frostmourne/scripts/startup.sh 

./startup.sh: line 7: dos2unix: command not found
LOG_DIR: /opt/frostmourne/scripts/../logs
PID_FOLDER: /opt/frostmourne/scripts/../pid
Sun Mar 26 16:42:27 CST 2023 ==== Starting ==== 
Application is running as root (UID 0). This is considered insecure.
Started [5477]
Waiting for server startup..
Sun Mar 26 16:42:37 CST 2023 Server started in 10 seconds

ss -an | grep 10054
tcp   LISTEN 0      100                    *:10054           *:*                  

## 查看10054端口监听即可判断已正常启动。

/opt/frostmourne/scripts/shutdown.sh 

## 停止服务

Web访问: http://192.168.124.100:10054 即可测试,注意替换IP

admin 管理账号默认的账号密码是123456

注意:开启了LDAP认证,admin账号仍然可以用初始密码登录。

配置为Systemd自定义服务并设置开机启动

vim /usr/lib/systemd/system/frostmourne.service 


[Unit]
Description=frost
After=network.target mysqld.service

[Service]
User=root
Type=forking
ExecStart=/opt/frostmourne/scripts/startup.sh
ExecStop=/opt/frostmourne/scripts/shutdown.sh
RemainAfterExit=yes



[Install]
WantedBy=multi-user.target

##写入到文件保存。

systemctl daemon-reload
## 加载自定义服务
systemctl start frostmourne.service 
systemctl status frostmourne.service 

## 尝试启动,并查看状态。
systemctl enable frostmourne.service 

## 设置开启及并启动

注意:需要等待网络服务和mysql启动之后,才会启动。

技术架构

frostmourne-vue:前端项目,使用vue-element-template实现,打包时会把生成的资源文件构建到frostmourne-monitor

  • frostmourne-monitor:监控运行主体服务
    Frostmourne (霜之哀伤)日志监控系统部署安装

主要技术栈

  • springboot 2.x
  • element ui
  • vue-admin-template
  • xxl-job
  • mybatis
  • freemarker
  • elasticsearch
  • InfluxDB
  • jjwt
  • nashorn

    参考

官方文档:https://github.com/AutohomeCorp/frostmourne

注意:推荐配合https://songxwn.com/elk/ ES部署使用。