揭露数据不一致的利器 —— 实时核对系统

本文首发于“Shopee技术团队”微信公众号。

摘要

随着企业业务发展,以及微服务化大趋势下单体服务的拆分,服务间的通信交互越来越多。与单体服务不同,微服务间的数据往往需要通过额外的手段来保障一致性,例如事务消息、异步任务补偿等。除了从机制上最大程度保障以外,如何观测并及时发现数据不一致也非常重要。

本文介绍 Shopee Financial Products 团队设计和开发的实时核对系统(Real-time Checking System),它接入简单,只需根据核对需求配置对应的核对规则,实现了规则热加载,并能在不侵入业务的前提下对系统数据进行实时监测对比,及时发现数据的不一致。系统落地至今,已在 Shopee 多个产品线推广使用,帮助不同团队快速发现线上数据不一致问题,为数据保驾护航。

1. 背景

1.1 系统数据的不一致性

在日常的开发迭代中我们能发现,系统的数据有时并不按照我们设想的那样进行变更。常见的场景如:用户进行了还款(Repay),系统 A 收到了还款请求后调用系统 B,将已冻结的账户进行解冻,但因为某些原因(如系统故障、网络分区等),解冻的请求没有抵达 B,或者解冻成功的响应没有返回给 A,此时会出现已经确定收款但未解冻,或未确认收款却已解冻的情况,从而引起用户投诉或资金损失。

Fig1. Data Inconsistency

造成这类问题的原因通常有:代码逻辑 Bug、并发场景处理不当、基础组件(网络、数据库、中间件)故障、跨系统间缺乏原生的一致性保障等等。随着业务扩展,企业内的应用越来越多,且有许多单体应用(Monolithic Application)向微服务(Microservices)拆分转型,分布式的场景下丢失了数据库事务的支持,需要解决数据一致性的问题。

保障数据一致的方案有很多种,在单体服务且缺少不同组件间(例如跨 Database、不同存储中间件)事务支持的场景下,可以使用本地事务表 + 补偿任务的组合,将主表数据与检查任务通过事务写入,再通过异步任务不断检查目标数据是否一致并进行补偿,可实现最终一致性;在跨服务场景下,Saga 模式通过可靠消息及服务提供回滚事务的能力,来实现分布式事务。

但是,对于重要的业务,不管使用何种一致性方案,提供额外的检查、核对、兜底手段都是必要的,由此衍生出了很多的业务核对、对账的需求。服务间通过特定手段保障数据一致性,并设计无侵入的旁路系统进行数据核对和校验,是微服务架构下的典型搭配。

Fig2. Data Consistency Insurance

1.2 离线核对的缺陷

常见的离线数据核对可以通过定时任务,按照一定的筛选条件,从不同数据源中获取特定数据,再进行比较。这种方案的伪代码如:

func Check() {
    // 获取上游 update_time 落在 [a, b) 的数据行
    upstreamRows := QueryUpstreamDB(a, b)

    for uniqueKey, sourceData := range upstreamRows {
        // 为每个上游数据查找对应的下游数据
        targetData := QueryDownstreamDB(uniqueKey)

        // 对比上下游数据
        Compare(sourceData, targetData)
    }
}

时效性低是这类查表方案的通病。核对操作通常放在异步任务中定时执行,执行时间和离数据变更时间有一定延迟,且定时任务的查询条件也会对核对目标造成影响。当出现异常数据时,不能及时发现问题,只能等待下次定时任务执行后才能发现。

引入了额外的扫表开销同样是个不容忽视的问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值