小小的分页问题引发的加班血案!
作者:菜v菜
微信公众号:架构师修行之路
一、问题分析
通过以上的对话,身为程序员的你是否也遇到过妹子这样的问题呢?传统的而且网上到处充斥着的也是这类方式,客户端根据自己的滚动不断的更新pagesize和pageindex两个参数,然后上传给服务端接口获取数据,而且网络上也很少说明这种方式是否有问题,那到底有没有问题呢?
谈到分页,无论程序怎样写,分页这个业务的核心动作是根据开始位置和结束位置来获取一段数据,无论你的排序规则有多复杂,最终的目的总是获取总列表数据中一段连续的数据。无论你是直接用的sql语句分页,还用的搜索引擎(比如es),最终在客户端体现的效果就是下一页的数据展现。
当然体现在客户端的UI上的交互操作可以有很多样式:
如果是瀑布流或者app段滚动展示的方式,或者其他不需要数据总个数的情况下,菜菜认为服务端千万不要查询这个总个数数据,展示方完全可以以下一页有无数据作为是否继续拉取下一页数据的依据。
话题回归,如果客户端依据pagesize和pageindex参数来进行分页需求,有没有问题呢?当然有,要不然菜菜写这篇文章意义何在,我又不是一个喜欢爱扯淡的程序员~~
二、问题所在
这里以最简单也是最基本的sql 语句分页为例,假如现在数据库现有数据为:
<p style="margin-top: 15px;margin-bottom: 15px;line-height: 2em;"><span style="font-size: 15px;">1,2,3,4,5,6,7</span></p>
排序的规则是按照大小倒序,即数据的全部列表为:
<p style="margin-top: 15px;margin-bottom: 15px;line-height: 2em;"><span style="font-size: 15px;">7,6,5,4,3,2,1</span></p>
假如现在是获取第二页数据,pagesize为2,pageindex为2,正确结果为 “5,4” 。这无可厚非,在数据未发生改变的情况下,正确结果确实如此,那如果数据发生的变化呢,假如现在新加入一条数据 8,列表数据会变为:
<p style="margin-top: 15px;margin-bottom: 15px;line-height: 2em;"><span style="font-size: 15px;">8,7,6,5,4,3,2,1</span></p>
那依据以上分页原则,第二页获取的数据就变为了“6,5”,聪明的你是不是发现了问题,这也可能是D妹子引发加班的原因。
分页的操作是建立在动态数据上的操作!
三、解决问题
分页操作的数据源是动态变动的,有时候变动的部分正好发生在你获取的数据范围内,就会发生数据重复或者错误的情况。那怎么解决呢?
3.1、客户端
作为数据的需求方和展示方,客户端需要记住已经加载的数据的主键列表,如果某条数据已经展示过,根据业务需求来确定是否要重复展示,一般情况下需要去重。
如果数据量非常大,客户端维护一个数据池的方案其实也不够理想。
3.2、服务端
(1)服务端分页接口参数新增上一页最后一条数据id参数lastId,去掉pageindex参数,因为在多数情况下,pageindex参数在服务端的作用是确定数据的起点而已,如果有了lastid,pageinde在很多情况下其实已经不需要了。
(2)服务端把所有的数据做缓存,这样动态数据在一定时间内静态化,但是这样也是治标不治本。
(3)如果业务上对于排序无要求的话,服务端可以采用顺序分页,把获取的数据落在不会变动的数据段上
服务端要想把动态的数据搞成静态有点难度。
3.3、业务方
无论程序怎么优化也改变不了数据是在不停变动的本质,如果业务方(产品,运营)能够接受数据在偶尔情况下能重复的现象,那能大幅度减少程序员的工作了。
有时候你认为的数据bug,在其他业务部门不一定是什么重大问题。