高频发布分页数据重复问题解决方案

  |   0 评论   |   452 浏览

背景

系统有一个发布文章的功能,前端要求根据发布时间来进行排序。发布文章的频率还是蛮高的。后台还可以定时发布。

开始的分页

前端传size(每页显示条数),current(当前页),获取发布时间小于当前时间的文章。后台根据current进行分页。

其中的判断条件:publish_time<=当前时间

缺点:如果后台频繁发布,那么前端在分页的时候会看到已经看过的数据;如果后台把某一篇文章取消发布或删除,那么会有数据丢失。

理想状态下:
imagepng
假设一页5条数据,数据按发布时间倒叙,在分页过程中没有新增数据,不会有问题。

数据重复:
imagepng
如果在获取第二页的时候,新增了两条数据(红色表示新增的数据),那么在获取第二页的时候,会把之前的7、6的数据查出来。这就导致了数据的重复加载。

数据丢失:
imagepng
如果在获取第二页的时候,有数据减少(黄色表示数据减少),那么在获取第二页的时候,会有数据丢失。

一般会出现在数据更新比较快的场景,如:咨询、文章等。

解决方案

1、新建一个发布时间戳字段,这个字段与发布时间是相对应的。存的是发布时间的微妙再后面加2位,组成一个19位的数。
2、发布或者保存时同步修改这个字段。
3、前端按照这个发布时间戳字段进行排序,查询第二页的时候,把第一页返回的发布时间戳传给列表接口。接口这边只获取一页的数据。
4、如果发布时间相同,那么生成一个7位数的随机数,加到微妙后面,可以解决定时发布时间相同的问题。
5、如果你的后台操作用户很多,并发很高的话,可以对发布时间戳进行分布式锁的控制。如果是单库可以使用表的唯一索引来控制。
注意:这个方案的核心就是发布时间戳不能重复。

对已有发布时间生成19位数。

private long getByPublishTime(Date publishTime){
    //主要是为了返回一个19位的数字  相同的概率减少
  return publishTime.getTime()/1000*100000000 + Long.parseLong(RandomUtil.randomNumberString(7));
}

获取微妙

/**
 * 获取微妙 
 * @return Long 返回微秒
 */
 public static Long getMicTime() {
    // 微秒
  long milliseconds = System.currentTimeMillis() * 1000;
  // 纳秒
  long nanoTime = System.nanoTime();
 return milliseconds + (nanoTime - nanoTime / 1000000 * 1000000) / 1000;
}

在获取微妙后再乘以100。

列表接口返回:

{"code":200,"data":{"list":[{...}],"more":true,"next":154382653109016663,"totalCount":75}}

前端根据more来判断是否还有新数据。next字段是接口中需要传的值。

也可以关注我的公众号:程序之声

关注公众号,领取更多资源

本文为博主原创文章,未经博主允许不得转载。

评论

发表评论