架构师必备:实时对账与离线对账

背景

在跨系统之间的数据写入场景下,上下游系统极有可能因为网络超时/抖动、或写本地DB与调外部接口不能同时成功等原因,而出现数据不一致的问题,因此需要有及时发现不一致问题、并自动修复的能力。下面结合笔者的经验,把对账做个总结。

需要注意的是,这里提的对账不特指资金对账,而是跨系统的字段对账,如B端与C端系统之间的对账。

对账的指标

判断对账是否做得好,主要看这几个指标:

  • 完备性:确保所有字段都有对账
  • 时效性:越高越好,秒级 > 分钟级 > 小时级 > 天级
  • 自动修复:对账发现不一致后自动修复,然后再次对账,确保修复后是最终一致的,形成闭环

下面分别介绍一下实时对账、离线对账,最好是两个都做。

1. 实时对账(秒级到分钟级对账)

实时对账可以尽快发现不一致,一般由数据写入方发起对账,数据接收方提供对账查询接口(例如查从库)。

触发方式分2种:

  • (不推荐)数据库变更事件触发:监听业务主表的binlog变更
  • (推荐)业务消息触发:监听业务消息变更

推荐由业务消息触发,是因为数据库变更事件触发有局限:

  • 如果有的写入操作不更新业务主表,比如只更新了扩展表,则需要新消费扩展表的binlog事件消息。
  • 如果存在中间状态,则需要等到记录变成终态后才能对账,需要过滤很多无效消息。

实现方案:

  1. 监听业务消息变更。业务消息需做成事务消息,即业务操作完成必发出、不完成不发出。业务消息可以携带多个表的信息,能减少一定的查DB请求。
  2. 延迟、批量消费变更消息,然后批量查询本地DB数据、以及上下游接口。
  3. 最后逐个字段做比较。

之所以要写入方发起对账,而不是接收方,是因为写入方调接收方的接口可能失败,接收方在写入失败时无法触发对账。

之所以要延迟消费,是为了避免短时间内的不一致造成误告警(例如数据库主从延迟、接口超时重试等原因),比如延迟15秒再消费。

之所以要积攒一批消息做批量消费,是为了避免对账查询qps过高,给本服务和上下游系统带来较大负载。

2. 离线对账(小时级到天级对账)

有了在线对账,为什么还需要离线对账呢?

  • 离线对账作为在线对账的兜底,可以定期跑历史存量数据
  • 离线对账不影响在线业务的稳定性
  • 外部第三方系统,一般只能定期提供离线数据,无法提供对账查询接口。典型的如第三方支付系统的对账单

实现方案:

  1. 离线采集:导出各系统的数据到hive表,可以是mysql表、或者是对账单
  2. 归一化数据:解析出所有的对账字段,按统一格式生成新的宽表a、宽表b
  3. 离线对比:
    (1)需要比较条数是否一致
    (2)以及数据内容是否一致:通过左连接找到只存在于左表的数据,通过右连接找到只存在于右表的数据,通过内连接并比较各个字段来找到存在差异的数据

下面看sql例子。

sql 复制代码
-- (1)比较两个表的条数是否一致
select count(1) from table_a; -- 查出左表的条数
select count(1) from table_b; -- 查出右表的条数

-- (2)比较数据内容是否一致
-- (2.1)只存在于左表的数据:左连接查询,左表记录都会保留,右表字段为空则说明右表缺少数据:
select * from
table_a left outer join table_b
on table_a.biz_field=table_b.biz_field
where table_b.biz_field is null;

-- (2.2)只存在于右表的数据:右连接查询,右表记录都会保留,左表字段为空则说明左表缺少数据:
select * from
table_a right outer join table_b
on table_a.biz_field=table_b.biz_field
where table_a.biz_field is null;

-- (2.3)两个表存在差异的数据,内连接查询,比对各个字段是否一致:
select * from
table_a inner join table_b
on table_a.biz_field=table_b.biz_field
where
(table_a.field_1 <> table_b.field_1
or table_a.field_2 <> table_b.field_2
or table_a.field_3 <> table_b.field_3);

3. 自动修复

一般是写入方发现不一致后,需要做自动修复。流程如下:

  1. 记录差异,供后续定位排查
  2. 自动修复
  3. 修复后再次对账,确保数据最终一致

结论

实时对账和离线对账,互为补充、缺一不可。新需求除了保证功能正确性,还要同时做好对账,避免有不一致问题时发现不了,或很久才发现。

对账发现不一致后自动修复,能保证系统的最终一致性。

相关推荐
潇凝子潇32 分钟前
如何在不停机的情况下,将MySQL单库的数据迁移到分库分表的架构上?
数据库·mysql·架构
Seven971 小时前
Mysql的索引数量是否越多越好?为什么?
mysql
自由的疯1 小时前
Java 11 新特性之 飞行记录器(JFR)
java·后端·架构
DemonAvenger3 小时前
构建实时应用:WebSocket+Go实战
网络协议·架构·go
智江鹏3 小时前
Android 之 MVVM架构
android·架构
aningxiaoxixi3 小时前
安卓audio 架构解析
java·架构·ffmpeg
掘根10 小时前
【MySQL集群架构与实践5】使用Docker实现水平分片
mysql·docker·架构
爬山算法11 小时前
MySQL(173)MySQL中的存储过程和函数有什么区别?
数据库·mysql
Ruimin051911 小时前
Mysql集群技术
数据库·mysql