第二章:系统架构设计
好,咱们直接进入正题。实时风险监控系统,说白了就是一个「数据进来,结果出去」的管道。但这条管道怎么搭,决定了它能跑多快、多稳、多抗造。我这些年踩过的坑,十有八九都跟架构设计有关。
今天咱们聊四个核心层:采集层、计算层、存储层、告警层。外加技术选型和高可用设计。嗯,内容不少,但都是干货。
核心观点:分层不是目的,解耦才是。每一层只干一件事,干到极致。
一、采集层:数据的入口,也是最容易出问题的地方
采集层负责把各种数据源的数据「拽」进来。日志、数据库变更、网络流量、第三方API回调……你想想看,来源五花八门,格式千奇百怪。
我个人习惯,在采集层前面加一层「接入网关」。它不干别的,就做三件事:协议转换、数据校验、流量整形。我在项目中遇到过,某次第三方接口突然暴量,直接把Kafka打挂了。从那以后,我所有项目都会在采集层做限流和背压处理。
避坑指南:我曾经以为采集层就是「收数据」,后来发现数据乱码、字段缺失、时间戳格式不统一才是常态。建议在采集层就做一次「数据清洗」,别把脏数据往下游传。
技术选型上,日志采集用Filebeat或Fluentd,消息队列用Kafka(高吞吐场景)或Pulsar(低延迟场景)。我个人更倾向Kafka,生态成熟,社区活跃,踩坑也有人问。
二、计算层:实时性的核心战场
数据进来了,怎么算?计算层就是干这个的。实时风险监控对延迟要求极高,通常要求在秒级甚至毫秒级完成计算。
计算层我一般分两条线:
- 流计算引擎:Flink是首选。状态管理、Exactly-Once语义、事件时间处理,这些特性在风险监控场景下太重要了。我记得有一次,因为没处理好乱序事件,导致风控结果错了整整两个小时……嗯,后来全量回刷,那叫一个酸爽。
- 规则引擎:Drools或自研的轻量级规则引擎。规则变化频繁,不能每次都改代码重启。我建议把规则配置化,存到配置中心,热加载。
关键设计:计算层一定要支持「动态扩缩容」。流量高峰来了,能自动加并行度;低谷时,能缩回去省钱。别问我怎么知道的——双十一那晚,我手动扩容扩到手抽筋。
三、存储层:读写分离,冷热分层
存储层是很多人的盲区。大家总觉得「存数据嘛,找个数据库不就完了?」但实时风险监控的数据特点很特殊:写多读少、最近数据访问频繁、历史数据需要归档。
我的做法是:
| 数据类型 | 存储方案 | 说明 |
|---|---|---|
| 实时指标 | Redis / Memcached | 毫秒级读写,用于实时计算中的状态查询 |
| 时序数据 | InfluxDB / TimescaleDB | 按时间维度存储,支持降采样和聚合查询 |
| 事件明细 | Elasticsearch | 全文检索,用于事后分析和审计 |
| 冷数据 | HDFS / 对象存储 | 超过30天的数据,压缩归档,成本低 |
你想想看,如果把所有数据都放一个库里,查询慢不说,存储成本也扛不住。冷热分离是必须的。我习惯用TTL自动清理热数据,超过时间窗口的就往冷存储迁移。
注意:存储层的「一致性」和「可用性」之间需要权衡。实时场景下,我通常选择最终一致性,而不是强一致性。因为风险监控允许几秒钟的数据延迟,但不能接受系统不可用。
四、告警层:别让告警变成噪音
告警层是系统的「嘴」,它告诉人:出事了。但很多系统的告警层做得一塌糊涂——告警太多,全是噪音,最后运维直接静音了。
我设计告警层时,遵循三个原则:
- 告警分级:P0(立即处理)、P1(15分钟内响应)、P2(1小时内处理)、P3(记录即可)。不同级别走不同通知渠道。
- 告警抑制:同一个根因引发的告警,只发一条。我曾经见过一个故障,发了2000多条告警,全是同一个数据库连接池满了导致的。
- 告警聚合:把相似告警合并,按时间窗口聚合。比如「5分钟内CPU超过90%的机器列表」,而不是每台机器单独发一条。
个人经验:告警通知渠道要「冗余」。短信、电话、邮件、钉钉/企微,至少配两个。我遇到过短信通道挂了,结果P0告警没人看到,业务损失惨重。从那以后,我每个项目都配「主+备」两条通道。
五、技术选型原则:别追新,要追稳
很多同学问我:「老师,XX新技术要不要上?」我的回答永远是:看场景。
技术选型我一般看这几点:
- 社区活跃度:GitHub Star、Issue响应速度、Release频率。太冷门的库,踩坑没人救。
- 团队熟悉度:再好的技术,团队没人会用,也是白搭。我习惯选团队「跳一跳够得着」的技术栈。
- 运维成本:Kafka和Pulsar都能用,但Kafka的运维工具链更成熟。说白了,选那个让你半夜少爬起来几次的。
- 生态兼容性:Flink + Kafka + Redis + ES,这套组合我用了五年,基本没出过大问题。生态互通,API兼容,省心。
我的原则:用成熟技术解决80%的问题,用自研解决20%的定制需求。别为了炫技而引入新技术。
六、高可用设计:别让单点毁了整个系统
高可用不是「加个备份」那么简单。它是一整套设计思想。
我总结了几点核心做法:
- 无状态设计:计算节点尽量无状态,状态外移到Redis或数据库。这样扩缩容就是加机器减机器的事。
- 多副本部署:每个组件至少2个副本,跨可用区部署。Kafka的Partition副本数设3,Flink的TaskManager设至少2。
- 熔断降级:下游挂了,上游不能跟着挂。用Hystrix或Sentinel做熔断,保护核心链路。
- 灰度发布:新版本先上10%的流量,观察5分钟没问题再全量。我吃过一次亏,新规则上线直接导致全量误报,那叫一个惨。
血的教训:高可用设计一定要做「故障演练」。别等到真出事了才发现备份也挂了。我每季度做一次混沌工程,随机杀进程、断网络、降磁盘,看看系统能不能扛住。
好了,架构设计这块就聊到这儿。分层架构的核心就四个字:各司其职。每一层做好自己的事,别越界,别耦合。技术选型别追新,高可用别偷懒。嗯,这些经验都是真金白银换来的,希望能帮到你。
公众号:蓝海资料掘金营,微信 deep3321