技术探索的旅程:从问题出发,走向实践
在我这五年的开发工作中,技术从来不是孤立存在的一套工具或者框架,它更像是一个不断演进、适应实际需求的“活体”。我常常觉得,做技术的人最重要的能力之一,就是能发现问题的本质,并用最合理的方式去解决它。
今天想和大家分享的是我在一次真实项目中遇到的挑战,以及我们团队是如何一步步通过技术探索与实践找到解决方案的故事。这篇文章不会讲太多高深的理论,更多是基于业务场景的技术选型、实施过程和一些踩过的坑,希望对你在日常开发中有所启发。
项目背景:数据驱动的运营系统重构

2021年,我所在的是一家电商公司,当时的运营部门正在推动一场系统重构,目标是搭建一个以数据为核心的运营支撑平台,用于分析用户行为、制定个性化策略,并支持快速上线实验(A/B Test)。
这个平台需要具备几个关键能力:
- 实时采集用户行为日志
- 多维度数据建模
- 支持灵活的指标定义和实时计算
- 可视化报表 + 策略配置能力
- 快速上线和验证营销策略的能力
听起来是不是很像现在大家常说的 CDP(Customer Data Platform)?当时我们在做这个事情的时候还没有完全照搬现成方案的打算,因为业务太特殊,通用方案难以满足我们的需求。
问题描述:旧系统的瓶颈逐渐暴露

我们原本有一个日志采集系统,架构如下:
- 前端埋点 -> Kafka -> Spark Streaming 消费处理 -> 存入 ClickHouse/MySQL
- 上层依赖 BI 工具生成报表,策略系统则通过数据库查询动态判断用户分组执行逻辑
这套系统在初期还能满足需求,但随着数据量增长、策略复杂度提升、运营人员对数据的依赖加深,问题开始集中爆发:
数据延迟严重
Spark Streaming 是微批处理,虽然性能还不错,但实时性达不到预期。很多策略依赖的数据更新存在分钟级延迟,导致策略生效滞后。
查询复杂度剧增
运营同学经常提出“过去7天活跃+未购买+加购过X类商品”的用户画像筛选,这类组合条件多到让 SQL 写得异常复杂,响应速度也越来越慢。
系统扩展性差
每增加一种新的事件类型或字段,都需要调整 ETL 流程、重新构建宽表结构,迭代成本极高。
缺乏统一的数据语义层
前端展示、后端策略使用的是不同口径的数据,同一个“UV”在不同的模块下竟然会算出两个结果。这种不一致性带来了大量沟通和信任危机。
这些痛点积累到了必须重构的地步。我们决定推翻重来,尝试引入更现代化的技术栈来应对这些问题。
技术选型与架构设计

在项目启动之初,我们组织了多次技术评审会议,讨论的核心问题是:如何在兼顾灵活性的同时保证系统性能和可维护性?
架构整体目标
- 实时性强:支持秒级甚至亚秒级的响应延迟
- 扩展性强:新增事件类型或字段不需要大范围重构
- 语义清晰:建立统一的数据模型和指标体系
- 开放性强:对外提供标准 API 或 SDK,便于接入其他系统
技术栈选择过程
我们对比了多种技术方案,最终确定了一个相对折中的技术栈:
| 模块 | 技术选型 | 选择理由 |
|---|---|---|
| 数据采集 | Apache Kafka + 自研SDK | 成熟可靠,支持异步缓冲和错误重试 |
| 实时计算 | Flink + Stateful Processing | 更高的流式处理能力,状态管理灵活 |
| 数据存储 | Hologres + ClickHouse | 各取所长,Hologres 强在交互式查询,ClickHouse 适合批量聚合 |
| 数据建模 | 自研指标系统 + 维度建模 | 为统一语义服务,简化上层逻辑 |
| 策略引擎 | 自研DSL语言 + 规则引擎框架 | 实现规则可编辑、快速灰度发布 |
其中,最大的变化就是从 Spark 转向 Flink,以及引入自研指标系统作为数据语义层。
关键实现细节分享

这部分内容是我认为最有价值的部分,很多技术博客只谈“用了什么”,不谈“为什么用这个”、“怎么用得好”。
1. 从 Spark 到 Flink 的迁移之路
背景问题
旧系统用的是 Spark Streaming 进行日志清洗和初步聚合,在流量高峰期经常出现数据堆积的情况。而且 Spark 的微批机制在面对“低延迟”场景时明显力不从心。
解决思路
我们调研了多个流式计算框架,Flink 在以下几个方面吸引了我们:
- 真正的实时流处理(Event Time & Watermark)
- 状态管理完善(如 RocksDB backend 对大状态的支持)
- 有丰富的窗口机制和CEP(复杂事件处理)API
实施难点
迁移过程中最大的挑战是:
- 如何保持历史数据的状态兼容?
- 怎么确保任务重启时不丢失状态?
- 性能调优,尤其是 checkpoint 和 state backend 的配置
我们最终采用了增量快照(Incremental Checkpoint)机制,并使用 RocksDB 作为状态后端,有效降低了 checkpoint 成本。
收益总结
迁移完成后,核心指标延迟从平均 3 分钟降到了 5 秒内,任务资源消耗也略有下降。最重要的是,我们可以用 event-time 来精确控制窗口计算,避免因网络延迟造成的误差。
2. 自研指标系统的设计与实现
为什么要做指标系统?
运营人员每天都在问:“某个行为在过去7天有没有发生?”、“有多少人在XX条件下转化了?”等等。每次我们都得写 SQL,效率极低且容易出错。
我们意识到,需要一套统一的指标管理系统,把常用的统计逻辑沉淀下来,形成标准化接口。
核心设计原则
- 所有指标都基于事件时间,而非处理时间
- 支持多种聚合方式:count、distinct count、avg、sum、topN等
- 提供灵活的时间区间设定(如最近 7 天、本周、上月同期)
- 支持指标复用(如 UV = unique count of user_id over time_range)
架构实现简述
我们基于 Flink 设计了一个指标计算引擎,核心流程如下:
- 配置中心下发指标定义
- 实时引擎解析定义,生成 DAG 计算图
- 每个节点对应一个原子指标(比如 count、filter)
- 输出结果写入 Hologres,供 API 查询
例如:
metric:
name: "recent_7d_active_users"
type: "user_distinct_count"
filters:
- event_type == "page_view"
time_window: "last 7 days"
这样的 DSL 表达非常直观,而且可以支持任意组合。
实际效果
有了这套系统后,运营策略同学可以通过可视化界面配置策略规则,不再需要等待研发排期。更重要的是,所有数据口径都是统一的,数据信任度大大提升。
小插曲:那次凌晨三点的日志丢失事件
说到这儿,我想起了一个小故事。
项目刚上线没多久,某天晚上突然发现部分用户的点击行为没有被记录。我们紧急排查后发现,Kafka 中某些分区的数据迟迟没有被消费。
进一步查日志发现,消费者在拉取数据时频繁触发 OutOfMemoryError。原因是我们的反序列化器在处理嵌套 JSON 时一次性加载整个文档,对于某些超大 payload 的请求来说,内存直接被打爆。
这个问题最后是怎么解决的?我们换成了 JsonParser 流式解析方式,逐层读取字段,避免一次性加载全量数据。同时限制了最大 payload 大小,防止恶意数据攻击。
这次事故给我很大教训:再好的架构设计,也得经得住现实世界的考验。 技术选型不能只看文档,要结合实际情况做压测和边界测试。
最终成果与收益回顾
项目上线半年后,我们做了个简单的效益评估:
| 指标 | 旧系统 | 新系统 | 提升幅度 |
|---|---|---|---|
| 数据延迟 | 平均3分钟 | <5秒 | ⬆️98% |
| 策略上线周期 | 2~3天 | 1小时内 | ⬆️95% |
| 查询QPS | <100 | >1000 | ⬆️10x |
| 人工干预次数 | 每周多次 | 几乎为零 | ⬇️显著降低 |
不仅如此,新系统还帮助我们实现了以下能力:
- 自动识别异常用户行为,提高反欺诈能力
- 实验平台接入更顺畅,AB 实验上线更快
- 运营策略系统具备自我优化能力(如自动选择最优投放人群)
这些成效背后,是我们对技术不断探索与实践的结果。
我的一些思考与建议
做技术这么多年,我越来越坚信一句话:解决问题比追求炫技更重要。
不要为了新技术而用新技术
很多人喜欢追热点,看到什么新框架就立刻想用到项目里。但我始终认为,适合当前业务的才是最好的。比如 Flink 很强大,但它并不是所有流处理场景的唯一解。只有当你真正理解了你面对的问题,才能选出合适的技术方案。
架构设计要留有余地,别一开始就追求完美
我们最初也犯过这个错误,试图打造一个“全能型”的系统。结果发现功能越堆越多,开发周期拉长,反而耽误了上线进度。后来我们采取了“最小可行性架构 + 快速迭代”的策略,先解决核心问题,再逐步扩展功能。
重视测试和监控,提前暴露问题
上线前我们花了不少精力在自动化测试和压力测试上。比如模拟百万级并发写入、构造异常数据、注入网络抖动等,这些都是在保障系统稳定性上起到了关键作用。
团队协作很重要,技术只是手段,人和流程才是核心
再好的架构如果没人维护,没人理解,终究还是会腐烂。我们在项目推进中特别注重文档建设、Code Review、技术培训,确保知识共享不成为瓶颈。
结语:技术的路很长,我们一起走
技术这条路,从来不轻松。你会遇到各种各样的问题,有时候是算法不够高效,有时候是框架不支持你的需求,有时候是你自己也不确定方向是否正确。
但我始终相信一点:只要坚持动手、勤于思考、敢于试错,就没有解决不了的问题。
我希望通过这篇文章,能带给大家一些真实的参考,让你在面临挑战时少走些弯路。技术探索的道路没有终点,愿我们都能在这条路上走得更远,也更稳。
如果你也在做类似的事情,或者对这套系统感兴趣,欢迎留言交流。一起成长,才是我们做技术的意义所在。

评论 0