龙空技术网

业务二三事——时间范围分页取数的坑

避夏 145

前言:

此刻姐妹们对“分页代码规定五页”大体比较看重,看官们都需要知道一些“分页代码规定五页”的相关内容。那么小编在网上汇集了一些对于“分页代码规定五页””的相关内容,希望大家能喜欢,各位老铁们快快来学习一下吧!

一场由时间戳范围取数引发的血案

背景

接手了一个系统,该系统需要对下游提供数据,因此在数据变化时,需要告知下游系统。原开发人员可能为了系统解耦,没有采用同步调用的方式进行通知,提供了一个按照最后变更时间范围的查询接口进行查询,接口契约大概如下:

{    "datachangeLasttimeFrom":1,    "datachangeLasttimeTo":2,    "pageIndex":1,    "pageSize":10}

取数据最后变更时间大于1 小于等于2的数据。

系统正常运行了一段时间,但是某一天突然下游说我们的系统有些数据没有正常同步过去,这就令人头大了。

事件分析

接到事件之后,捋了一遍接口逻辑,竟然一时没有发现什么问题。T^T

查看日志也没有找到问题,最后又过了一遍代码,才明白为什么了系统在平稳运行一段时间后,才出现上述的问题。

系统上线初期,用户量小,不存在并发读写的问题;当运行一段时间后,用户量变多,在下游调用接口进行数据同步的时候,出现并发的写请求,会出现数据丢失的情况。

具体情况如下图所示:

①分页查询:符合查询条件的有10条记录,分页取第1页,分页大小为5

通过时间戳范围进行查询的SQL语句

通过时间戳范围进行查询的SQL语句

分页查询,符合条件的有10条记录,取第1页,5条

②并发更新:已被取到的数据,在此时进行了更新,如图中记录5

已被取到的数据,在此时进行了更新,如图中记录5

③继续分页取数:此时继续根据时间戳范围进行取数,数据6丢失了

此时继续根据时间戳范围进行取数,数据6丢失了

解决方案

定位到问题的原因,解决起来就简单多了。我们对接口增加一个偏移量,每次取数后将偏移量回传,每次都取第一页数据,这样就不会产生数据丢失的问题。

将上次获取到的主键ID进行回传

此时,就能成功取到数据6了

问题复盘

原本的开发同学为了系统的解耦,提供了这样一个接口,想法是好的,但是没有考虑全面,因此造成了生产的事件。经过我们的优化后,加上偏移量,这个方法仍然不是一个很好的方法,因为下游仍需要定时轮询接口,当接口方增多时,对接口的访问压力会直线上升;同时,即使不存在数据变更,下游系统仍需要轮询接口,造成资源的浪费。

本质上这是一个多系统间数据同步的问题,系统间的解耦我们通常使用消息队列。大致的实现方法就是发生数据变更的时候进行抛出消息,下游系统自行监听消息,调用查询接口进行数据同步。

消息队列的功能:①应用解耦 ②流量削峰

we can do it better

如何用MQ进行数据同步呢?

方案①:在所有保存接口和审核接口的地方手动抛出消息

方案②:在Service层中所有调用DAO层的地方横切,添加发送数据消息的逻辑

方案③:监听Canal,抛出消息

方案①和方案②在本质上是没有区别的,但是方案①需要开发人员的自我约束,在新增接口时,容易遗漏消息的抛出;方案①和方案②都无法解决DBA直接操作数据库的场景,因此我们采用方案③进行消息的发送。

标签: #分页代码规定五页