背景
系统有一个发布文章的功能,前端要求根据发布时间来进行排序。发布文章的频率还是蛮高的。后台还可以定时发布。
开始的分页
前端传size(每页显示条数),current(当前页),获取发布时间小于当前时间的文章。后台根据current进行分页。
其中的判断条件:publish_time<=当前时间
缺点:如果后台频繁发布,那么前端在分页的时候会看到已经看过的数据;如果后台把某一篇文章取消发布或删除,那么会有数据丢失。
理想状态下:
假设一页5条数据,数据按发布时间倒叙,在分页过程中没有新增数据,不会有问题。
数据重复:
如果在获取第二页的时候,新增了两条数据(红色表示新增的数据),那么在获取第二页的时候,会把之前的7、6的数据查出来。这就导致了数据的重复加载。
数据丢失:
如果在获取第二页的时候,有数据减少(黄色表示数据减少),那么在获取第二页的时候,会有数据丢失。
一般会出现在数据更新比较快的场景,如:咨询、文章等。
解决方案
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字段是接口中需要传的值。
注意:本文归作者所有,未经作者允许,不得转载