分页问题
分页问题
前文已经叙述了基于时间线的 Feed 流常见设计方案,但实操起来会比理论要麻烦许多。接下来专门讨论一个困难点:Feed 流的分页。不管是读扩散还是写扩散,Feed 流本质上是一个动态列表,列表内容会随着时间不断变化。传统的前端分页参数使用 page_size 和 page_num,分表表示每页几条,以及当前是第几页。对于一个动态列表会有如下问题:
在 T1 时刻读取了第一页,T2 时刻有人新发表了“内容 11”,在 T3 时刻如果来拉取第二页,会导致错位出现,“内容 6”在第一页和第二页都被返回了。事实上,但凡两页之间出现内容的添加或删除,都会导致错位问题。为了解决这一问题,通常 Feed 流的分页入参不会使用 page_size 和 page_num,而是使用 last_id 来记录上一页最后一条内容的 id。前端读取下一页的时候,必须将 last_id 作为入参,后台直接找到 last_id 对应数据,再往后偏移 page_size 条数据,返回给前端,这样就避免了错位问题。如下图:
采用 last_id 的方案有一个重要条件,就是 last_id 本身这条数据不可以被硬删除。设想一下上图中 T1 时刻返回 5 条数据,last_id 为内容 6;T2 时刻内容 6 被发布者删除;那么 T3 时刻再来请求第二页,我们根本找不到 last_id 对应的数据了,也就无法确认分页偏移量。通常碰到删除的场景,我们采用软删除方式,只是在内容上置一个标志位,表示内容已删除。由于已经删除的内容不应该再返回给前端,因此软删除模式下,找到 last_id 并往后偏移 page_size 条,如果其中有被删除的数据会导致获得足够的数据条数给前端。这里一个解决方案是找不够继续再往下找,另一种方案是与前端协商,允许返回条数少于 page_size 条,page_size 只是个建议值。甚至大家约定好了以后,可以不要 page_size 参数。