得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践
bigegpt 2025-05-16 11:53 4 浏览
一、摘要
在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障 Web 应用和移动端的可用性与性能。传统方案往往依赖代理 Agent → 消息队列 → 流计算引擎 → OLAP 存储的多级架构,虽然能满足基本数据接入与查询需求,但面临以下困难与挑战:
分层架构的精细化演进
当前分层模型在支撑多业务场景时,需要为分钟级、小时级、天级等不同时间粒度的数据视图分别构建计算链路。这种模式在保障灵活性的同时,可能存在存储与计算资源的重复消耗现象,如何通过增量计算或动态视图技术实现"一次计算多级复用",或将成为提升资源利用效率的关键突破点。
复杂分析场景的效能平衡
在应对全量 Join、多维交叉分析等高复杂度场景时,现有的按量计费机制与计算资源调度策略,可能在高频业务周期(如大促活动)中面临成本曲线的非线性增长挑战。探索预计算加速、智能冷热分层与弹性资源调度的深度结合,或许能进一步释放大规模分析场景的性价比潜力。
生产环境的安全加固
基于 SQL 的敏捷开发模式在提升数据处理效率的同时,也对企业级数据资产管理提出了更高要求。通过强化语法预校验、分区保护机制、操作审计追溯等防护手段,构建覆盖开发、测试、发布全流程的可靠性护城河,将有效降低误操作风险并提升数据治理成熟度。
本文聚焦将前端可观测后端数据分析场景演进到 GreptimeDB 的实践,深入剖析如何利用 GreptimeDB Flow 引擎实现 10s、1m、10m 等多粒度持续聚合,结合HyperLogLog 与 UDDsketch 函数,为前端可观测场景提供高性能、低成本且易于运维的端到端解决方案。
二、部署架构
为解决前述痛点,逐步将时序/观测数据场景迁移至 GreptimeDB,并借助其内置的Flow引擎(SQL)自动维护秒级、分钟级、小时级等多精度下采样表,可极大简化分层建模和物化视图运维。
GreptimeDB分布式架构
采用 GreptimeDB 开源的分布式模式,在这种模式下,GreptimeDB 的节点可以分为如下角色:
Frontend:负责协议处理、请求校验和鉴权、初步查询优化,是一个无状态节点,可以根据负载任意扩缩容。
Datanode:负责管理数据分片、处理数据写入和持久化以及执行具体的查询。
Flownode:对于配置了流计算任务的集群,Flownode 负责接受 Frontend 镜像而来的写入请求并执行流计算任务。流计算的结果最终会被写入到 Datanode 中进行持久化。
Metasrv:GreptimeDB 的控制面组件,负责管理集群的元数据(如表的分片路由信息等)。Metasrv 本身是无状态的,这里我们采用 PostgreSQL 作为后端存储。
透明数据缓存
GreptimeDB 对数据访问层进行了高度的抽象,负责管理数据分片的 Datanode 并不需要感知到数据文件位于本地磁盘还是对象存储。但是考虑到当使用对象存储时数据文件的访问延迟会大大增加,因此 GreptimeDB 设计了多层的透明数据缓存来解决此问题。
(GreptimeDB 的缓存结构)
GreptimeDB 的缓存结构如上图所示。从缓存所在位置可以分为磁盘缓存和内存缓存两类:
磁盘缓存的数据来源通常是对象存储,其类似于操作系统的 page cache,只不过 page cache 是利用内存加速磁盘数据的访问,而 GreptimeDB 的这部分缓存则是利用磁盘加速对象存储的访问,将频繁访问的文件按范围缓存到磁盘可以实现更低的查询延迟,并且能够智能根据访问模式实现预取(prefetch)、IO 合并等优化。
内存缓存除了原始的文件内容之外也包括从磁盘/对象存储的原始内容反序列化出来的数据结构,如字段的 min/max,bloomfilter 等等。
而从数据类型来分可以分为结构化和非结构化两类:
非结构化缓存的内容通常是文件的二进制内容,而缓存的 key 则是文件名加上字节范围。比如在 flush 的过程中写入到对象存储的文件往往是大概率很快就会被查询的热数据,因此可以在本地缓存一份避免查询请求穿透到对象存储。
结构化缓存则是文件、索引的内容或元数据反序列化得到的结构体,这些数据在查询剪枝时频繁被用到,因此 GreptimeDB 缓存了反序列化之后的结构,避免频繁反序列化带来的开销。
尽管 GreptimeDB 的缓存机制较为复杂,但是用户无需过多了解细节,只需要给定特定的缓存大小,GreptimeDB 会自动分配各类缓存的配额以及管理缓存的分配和释放,具体调优指南请参考附录[1]。
无畏扩缩容
GreptimeDB 的最小数据读写单元是表的数据分片(称之为 region)。Region 可以在不同的节点之间进行迁移。目前开源版本的 GreptimeDB 支持手动通过 migrate_region函数进行 region 的迁移(详见附录[3])。当监控发现某些 datanode 的负载较高时,可以将部分 region 迁移到其他较为空闲的 datanode 上避免可用性的降级。
此外,GreptimeDB 是面向云原生基础设施设计的数据库,其 Metasrv 节点能够实时采集各个节点的负载并且将流量在不同节点之间进行分配。对于不同的负载读写特性,还可以利用 Kubernetes 的弹性调度特性来调整不同节点组的副本数量来实现读写分离。关于 GreptimeDB 读写分离的实践,可以参考附录[2]。
三、GreptimeDB Flow 流计算实践
GreptimeDB Flow 是一个专为时序场景设计的轻量级流计算引擎。 它特别适用于提取 - 转换 - 加载 (ETL) 过程或执行即时的过滤、计算和查询,例如求和、平均值和其他聚合。通过在 Frontend 将写入流量镜像一份到 Flownode 进行计算再写回 Frontend 并进行持久化,它可以确保数据被增量和连续地处理,根据到达的新的流数据更新最终结果。
更加重要的是,编写一个 Flow 流计算任务无需额外的学习成本,它完全使用 SQL 语句定义计算任务。如以下语句:
定义了一个名叫 ngx_status_count 的任务,它负责流式地统计 ngx_access_log 表中每分钟内每个不同状态码的访问日志数量。在AS 之后的任务定义部分是一个标准的 SQL,因此对于熟悉 SQL 的开发者来说极容易上手。
多级持续聚合架构
10s 粒度热数据层
CREATE FLOW rpc_cost_10s
SINK TO rpc_cost_10s_agg
EXPIRE AFTER '12hours'::INTERVAL
AS SELECT
app_name,
url,
date_bin('10s'::INTERVAL, timestamp) AS time_window,
uddsketch(cost_time_ms, 0.01, 0.001) AS cost_sketch
FROM rpc_cost_time
GROUP BY app_name, url, date_bin('10s'::INTERVAL, timestamp);
说明:每 10s 计算一次 UDDsketch,近似捕获耗时分布,并写入“热表”,支持毫秒级查询。
1m 粒度中层 Roll-up
CREATE FLOW rpc_cost_1m
SINK TO rpc_cost_1m_agg
EXPIRE AFTER '30days'::INTERVAL
AS SELECT
app_name,
url,
date_bin('1m'::INTERVAL, time_window) AS time_window_1m,
uddsketch_merge(cost_sketch) AS cost_sketch_1m
FROM rpc_cost_10s_agg
GROUP BY app_name, url, date_bin('1m'::INTERVAL, time_window);
说明:周期性合并 10s 粒度的 sketch,生成分钟级聚合,保留 30 天。
10m 粒度冷层
CREATE FLOW rpc_cost_10m
SINK TO rpc_cost_10m_agg
EXPIRE AFTER '180days'::INTERVAL
AS SELECT
app_name,
url,
date_bin('10m'::INTERVAL, time_window_1m) AS time_window_10m,
uddsketch_merge(cost_sketch_1m) AS cost_sketch_10m
FROM rpc_cost_1m_agg
GROUP BY app_name, url, date_bin('10m'::INTERVAL, time_window_1m);
说明:进一步合并至 10 分钟级,存入低成本对象存储,保留 180 天。
UV 近似统计:HyperLogLog
和耗时分布统计类似,统计各个 URL 的独立访问量(UV)也是常见的需求。不过想要精确统计特定时间段的 UV 成本是极高的,因此业界往往使用近似算法来实现 UV 计算,如 HyperLogLog。GreptimeDB v0.12 提供了对 HyperLogLog 相关函数的支持,结合 Flow 可以实现强大的任意时间段 UV 近似统计。
10s UV 状态
CREATE FLOW uv_hll_10s
SINK TO uv_state_10s
EXPIRE AFTER '12hours'::INTERVAL
AS SELECT
app_name,
url,
date_bin('10s'::INTERVAL, ts) AS time_window,
hll(user_id) AS uv_state
FROM access_log
GROUP BY app_name, url, date_bin('10s'::INTERVAL, ts);
hll 函数: Flow 任务中我们通过 hll 函数将同一时间窗口内的 user_id 进行散列并写入到 uv_state_10s 的 uv_state 字段中。
uv_state BINARY 类型: 是一个二进制字段(BINARY 类型),无法直接进行查询。如果要查询某个10 秒的时间窗口内的独立访问用户量,需要通过 hll_count 函数来进行查询。
SELECT
`app_name`,
`url`,
hll_count(`uv_state`) as uv_count
FROM uv_state_10s
WHERE time_window = 1743479260;
1m UV 聚合
如果用户需要进一步将 10 秒的访问数据聚合到 1 分钟或者直接需要查询特定时间段内的用户访问数量,则可以通过hll_merge 函数来对二进制的 HyperLogLog 状态进行合并。
CREATE FLOW uv_hll_1m
SINK TO uv_state_1m
EXPIRE AFTER '180days'::INTERVAL
AS SELECT
app_name,
url,
date_bin('1m'::INTERVAL, time_window) AS time_window_1m,
hll_merge(uv_state) AS uv_state
FROM uv_state_10s
GROUP BY app_name, url, date_bin('1m'::INTERVAL, time_window);
查询示例:
SELECT
app_name,
url,
hll_count(uv_state) AS uv_count
FROM uv_state_1m
WHERE time_window_1m = '2025-04-20T15:23:00Z';
GROUP BY app_name, url;
效果与收益
查询性能显著提升:
预聚合 + 多级 Roll-up,避免全量扫描,P99 查询延迟从秒级降至毫秒级。
存储与成本可控:
不同粒度数据设置差异化 TTL:10s 热表保留 1 天,1m 中表保留 7 天,10m 冷表保留 180 天,冷热分离降低存储成本。
资源解偶 & 弹性扩缩容:
Frontend、Flownode、Datanode 独立伸缩,流计算、存储、查询三者互不干扰。
开发效率提升:
Flow 编写使用标准 SQL,上手难度低,Roll-up、HyperLogLog、UDDsketch 等内置函数无需额外学习曲线。
四、最佳实践与落地建议
合理划分数据分层:根据监控场景与 SLA 要求确定不同粒度保留策略。
调整 sketch 精度:UDDsketch 支持自定义误差范围(α、β 参数),可根据业务侧对 P50/P99 精度要求调优。
监控与告警:为各级聚合任务配置失败重试与告警机制,确保持续计算的稳定性。
资源规划:根据写入 QPS 与聚合复杂度合理预估 Flownode 与 Datanode 数量,结合对象存储带宽设计分区策略。
参考文档:
1.性能调优技巧 | GreptimeDB Documentation(
https://docs.greptime.com/zh/user-guide/administration/performance-tuning-tips/#
%E5%A2%9E%E5%A4%A7%E7%BC%93%E5%AD%98%E5%A4%A7%E5%B0%8F)
2. 【使用指南】在 Kubernetes 上部署读写分离的 GreptimeDB 集群
3. Region Migration | GreptimeDB Documentation(https://docs.greptime.com/zh/user-guide/administration/manage-data/region-migration/#select-a-datanode-as-the-migration-destination)
往期回顾
1. 得物新一代可观测性架构:海量数据下的存算分离设计与实践
2. RUST练习生如何在生产环境构建万亿流量|得物技术
3. 得物业务参数配置中心架构综述
4. 得物增长兑换商城的构架演进
5. 得物自研DGraph4.0推荐核心引擎升级之路
文 / 南风
关注得物技术,每周更新技术干货
要是觉得文章对你有帮助的话,欢迎评论转发点赞~
未经得物技术许可严禁转载,否则依法追究法律责任。
- 上一篇:warm-flow新春版:网关直连和流程图重构
- 已经是最后一篇了
相关推荐
- 得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践
-
一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...
- warm-flow新春版:网关直连和流程图重构
-
本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...
- 扣子空间体验报告
-
在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...
- spider-flow:开源的可视化方式定义爬虫方案
-
spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...
- solon-flow 你好世界!
-
solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...
- 新一代开源爬虫平台:SpiderFlow
-
SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...
- 通过 SQL 训练机器学习模型的引擎
-
关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...
- 鼠须管输入法rime for Mac
-
鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...
- Go语言 1.20 版本正式发布:新版详细介绍
-
Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...
- iOS 10平台SpriteKit新特性之Tile Maps(上)
-
简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...
- 程序员简历例句—范例Java、Python、C++模板
-
个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...
- Telerik UI for iOS Q3 2015正式发布
-
近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...
- ios使用ijkplayer+nginx进行视频直播
-
上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...
- IOS技术分享|iOS快速生成开发文档(一)
-
前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...
- macOS下配置VS Code C++开发环境
-
本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- httperror403.14-forbidden (63)
- logstashinput (65)
- hadoop端口 (65)
- dockernetworkconnect (63)
- esxi7 (63)
- vue阻止冒泡 (67)
- c#for循环 (63)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- java大写转小写 (63)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)