因为业务十分复杂,简化描述问题如下
假设现在有一个 A 表,字段如下 ID 主键,自增 BILL_NO 单据编号 BILL_NAME 单据名称 BACKUP_COLUMN 备用列,用于存储外部系统传递的单据编号 TASK_TYPE 数据类型 …… 其余字段
接口:
外部系统传递 BACKUP_COLUMN,根据 BACKUP_COLUMN 从我们系统的 B、C 表中查询数据拼接并插入 A 表。 此类接口进入 A 表的时候 TASK_TYPE 为 002,且只有通过这个接口进来的是 002
问题:
此接口因为外部系统原因经常会在几毫秒甚至几纳秒内重发 N 次,导致 A 表出现重复数据
目前解决思路
方式 1:
一开始打算 BACKUP_COLUMN 加唯一约束,但是因为这个表还存其他业务数据,其他数据中 BACKUP_COLUMN 的值允许重复(例如 TASK_TYPE 为 001 时 BACKUP_COLUMN 允许为空或者重复),改动代价太大,时间及人员上不允许,故此放弃增加唯一约束的方式
方式 2:
在插入之前做一次查询,如果存在则不插入,本地及测试环境简单测试发现拦截住了,就部署到了生产环境 上了生产环境之后发现,还是有重复数据,经过查询日志发现,对方系统多次重复请求在几毫秒甚至及纳秒之内(数据库日志只记录到秒,最后还是通过打印时间发现的时间这么短) 这么短的间隔导致了第一次请求的数据还没执行到 inser 之前第二个请求就进来了,此时第二个请求的查重还是没有数据,最终第一次、第二次都插入成功。 这种情况只适用于两次重发间隔不是很短的情况
方式 3:
基于方式 2 的拦截失败,我们在数据插入成功之后,根据 BACKUP_COLUMN、TASK_TYPE 进行一次查重,如果有多个,保留时间最早的一个,删除(业务回退)其余重复数据,暂时没发现问题
** **
目前我们是通过方式 2 和方式 3 结合的方式保证数据不重复推送 因为现在方式 3 中的删除(回退)逻辑并不复杂,但是之后这里逻辑会变的超级复杂,或者出现复杂接口,个人个感觉方式 3 并不是很合适
请问各位大佬是否还有其他方式保证接口的幂等性或者说让重复数据不入库
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.