如何查找REST API与数据库表数据的delta(数据差异)避免重复存储
差异计算与去重写入方案
以下是不同场景下可落地的实现方式,按实现成本从低到高、性能从低到高排序:
方案1:逐条幂等校验(适合单批数据量<1万的轻量场景)
这是实现成本最低的方案,核心依赖业务唯一标识做判断:
- 先为业务数据确定全局唯一的业务键,比如订单ID、用户ID、设备SN这类不会随数据更新变更的字段,给数据库表的该字段添加
UNIQUE唯一索引做兜底 - 每次从REST接口拉取到数据后,对每条数据单独处理:
- 按唯一键查询数据库中是否存在对应记录
- 不存在则直接执行插入操作
- 已存在则逐字段比对接口返回值和库中存储值,有差异就执行更新,无差异直接跳过
方案2:批量差异计算(适合单批数据量1万~100万的中量场景)
如果逐条查询数据库性能不足,用批量比对减少数据库交互次数:
- 提前在数据库表中新增
data_fingerprint字段,存储每条数据的哈希指纹,生成逻辑可使用MD5(CONCAT_WS('|', 字段1, 字段2, ..., 字段N)),数据更新时同步更新指纹 - 调度运行时先拉取接口返回的全量数据,提取所有唯一键和对应指纹存入内存集合
- 单次查询数据库,拉取当前表中对应业务范围的所有唯一键+指纹存入另一个内存集合
- 直接计算两个集合的差异:
- 接口返回有、数据库没有的唯一键,对应数据为新增数据,批量插入
- 两边都存在但指纹不同的唯一键,对应数据为更新数据,批量更新
- 指纹完全相同的数据直接丢弃
方案3:接口端增量拉取(最优方案,无数据量限制)
如果对接的REST API支持增量查询参数,优先使用该方案,完全不需要自行计算全量差异:
- 每次调度执行时,携带上次拉取成功的时间戳作为请求参数,接口仅返回该时间点之后新增、变更的数据
- 拉取到的增量数据直接按方案1的幂等逻辑写入即可,能大幅降低接口传输量、本地计算量和数据库压力
兜底优化建议
- 不管使用哪种方案,都必须给业务唯一键加唯一索引,避免逻辑异常导致重复数据写入
- 调度任务要加分布式锁,避免多实例同时运行重复拉取写入
- 每次拉取完成后记录拉取时间、成功条数、新增条数、更新条数等元数据,方便后续排查问题
内容的提问来源于stack exchange,提问作者Devendra Anchal
相关产品推荐
相关产品推荐

