4. 混合架构设计原则:数据一致性、容错性、可扩展性、成本控制
聊到混合架构的设计原则,我脑子里第一个蹦出来的词就是「平衡」。你想想看,实时和批量两条腿走路,走快了容易扯着蛋,走慢了又跟不上业务。我在好几个金融项目里都踩过坑,说白了,核心就四个字:取舍有道。
下面我把这四个原则掰开揉碎了讲。嗯,都是真金白银换来的经验。
4.1 数据一致性:实时与批量的「握手协议」
数据一致性是金融系统的命根子。实时流处理数据,批量任务也处理数据,两边结果不一样怎么办?
我个人习惯用 「最终一致性 + 校验补偿」 的策略。实时链路保证秒级可见,批量链路保证天级对账。两条线各自跑,最后用一张对账表来「握手」。
我在项目中遇到过这么个事:实时计算出的当日交易总额,和批量跑出来的差了 0.01 元。查了半天,发现是浮点数精度问题。后来我们统一了精度策略——所有金额字段用 DECIMAL(18,4) 存储,计算时用 ROUND 函数截断。
具体怎么做?我建议用 「双写 + 对账」 模式:
-- 实时链路:写入实时表
INSERT INTO dwd_trade_real_time
SELECT trade_id, amount, status, create_time
FROM kafka_stream
WHERE event_type = 'trade';
-- 批量链路:写入批量表
INSERT INTO dwd_trade_batch
SELECT trade_id, amount, status, create_time
FROM ods_trade
WHERE dt = '2024-01-15';
-- 对账任务:比对两条链路
SELECT a.trade_id, a.amount AS real_amount, b.amount AS batch_amount
FROM dwd_trade_real_time a
FULL OUTER JOIN dwd_trade_batch b ON a.trade_id = b.trade_id
WHERE a.amount != b.amount OR b.amount IS NULL OR a.amount IS NULL;
对账发现不一致怎么办?别慌。我们设计了一个 「补偿任务」,每天凌晨跑一次,以批量结果为准,修正实时表里的脏数据。
4.2 容错性:别让一个节点拖垮整个架构
金融系统最怕什么?怕单点故障。实时链路断了,批量任务挂了,数据就断了。我见过最惨的一次,Kafka 集群磁盘写满,实时链路停了 3 小时,业务方直接炸锅。
容错性设计,说白了就是 「冗余 + 降级」。冗余保证不丢数据,降级保证系统还能用。
我常用的三板斧:
- 实时链路双活:两个 Kafka 集群互备,一个挂了自动切到另一个。切换时间控制在 30 秒内。
- 批量任务重试机制:每个任务最多重试 3 次,间隔 5 分钟。如果还失败,发告警给值班人员。
- 数据落盘保护:实时数据在内存处理的同时,必须写一份到本地磁盘。万一 Flink 挂了,重启后能从 checkpoint 恢复。
这里有个小技巧:「熔断机制」。当某个下游系统响应时间超过 5 秒,实时链路自动降级,把数据先写到临时队列,等系统恢复后再回放。这样不会因为一个慢节点拖垮整个链路。
4.3 可扩展性:架构要能「长胖」也能「长高」
金融业务增长快,数据量说翻倍就翻倍。我见过很多架构,一开始设计时没考虑扩展性,后来数据量上来,改得痛不欲生。
可扩展性分两种:水平扩展(加机器)和 垂直扩展(换更强的机器)。我建议优先考虑水平扩展,因为成本更低,也更灵活。
具体怎么做?我总结了几条经验:
- 数据分片:按交易日期、客户 ID 等字段分片,每个分片独立处理。这样加机器就能线性提升吞吐量。
- 无状态设计:实时任务尽量无状态,状态存到外部存储(如 Redis、HBase)。这样任务重启或扩缩容时,不需要迁移状态。
- 批量任务拆分:一个大任务拆成多个小任务,每个小任务处理一个分片。并行度可以动态调整。
你想想看,如果一开始就把所有数据塞到一个表里,后面想拆分就难了。我建议用 「分库分表 + 分区表」 的策略。比如交易表按日期分区,每天一个分区。这样查询和清理都方便。
4.4 成本控制:别让架构「烧钱」
说到成本,很多人的第一反应是「省」。但我觉得,成本控制不是一味省钱,而是 「把钱花在刀刃上」。
金融数据仓库的三大成本大头:计算资源、存储资源、网络带宽。我分享几个实战经验:
| 成本类型 | 优化策略 | 效果 |
|---|---|---|
| 计算资源 | 实时任务和批量任务错峰运行。白天跑实时,晚上跑批量。 | 节省 30% 的集群资源 |
| 存储资源 | 冷热数据分离。热数据存 SSD,冷数据存 HDD 或对象存储。 | 存储成本降低 50% |
| 网络带宽 | 数据压缩传输。使用 Snappy 或 Zstd 压缩算法。 | 带宽占用减少 60% |
我在项目中遇到过这么个事:实时任务用了全量数据加载,每天凌晨都要把几十 TB 的历史数据重新算一遍。后来改成增量加载,只处理当天新增的数据,计算量直接降了 90%。
还有一个容易被忽略的点:「数据生命周期管理」。不是所有数据都需要永久保存。我建议制定一个数据保留策略:
- 实时数据:保留 7 天
- 明细数据:保留 90 天
- 汇总数据:保留 3 年
- 历史归档:保留 10 年,存到廉价存储
这样既能满足监管要求,又不会让存储成本失控。
4.5 四个原则的协同关系
这四个原则不是孤立的,它们之间互相影响。比如,为了提升数据一致性,你可能需要增加对账任务,这就会增加计算成本。为了提升容错性,你可能需要双活集群,这就会增加存储成本。
我画了一张图,帮你理清它们之间的关系:
你看这张图,四个原则围成一个圈,中心是「平衡」。说白了,没有完美的架构,只有最适合业务的架构。数据一致性要求高了,成本就上去了;容错性做得好,扩展性可能受影响。你需要根据业务场景,找到那个「刚刚好」的点。
我个人习惯在项目初期就定好 「原则优先级」。比如:
- 核心交易链路:数据一致性 > 容错性 > 可扩展性 > 成本
- 报表分析链路:可扩展性 > 成本 > 容错性 > 数据一致性
这样设计时就有方向了,不会纠结。
公众号:蓝海资料掘金营,微信deep3321