Redis中SortSet使用不当导致的分页Bug怎么解决
这篇文章主要讲解了“中SortSet使用不当导致的分页Bug怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis中SortSet使用不当导致的分页Bug怎么解决”吧!
这篇文章主要讲解了“中SortSet使用不当导致的分页Bug怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis中SortSet使用不当导致的分页Bug怎么解决”吧!
创新互联公司是专业的龙泉网站建设公司,龙泉接单;提供网站建设、成都网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行龙泉网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
首先,我们线上的电商系统正在进行一个大促活动。买家非常的多,导致一时间产生了非常多的评论。开发人员在存储(保存)评论时,使用 Redis 中的 SortSet 这个数据结构。每新增一条评论,他都通过 zadd 命令将起保存至 Redis 和 中,查询时直接在 Redis 中取出来。代码抽象一下,如下所示:
顺便说一下,System.currentTimeMillis() 是毫秒,System.currentTimeMillis() / 1000 就相当于精确到秒。
这个活动是大促,参与活动的需要评论。活动比预期的热,导致同一秒的评论就比较多,导致 zrangeByScoreWithScores 在取出评论列表时,遇到同一秒的超过 10 条的评论,就会出现重复数据。
取出评论列表的逻辑大致抽象如下:
看到没?他每次拿 lastScore 记录,也就是上一页评论的最后一条数据的时间。来获取新的 10 条评论数据。由于同一秒评论的记录超过 10 条后,导致每次 APP 每次下拉刷新获取到重复数据的概率比较高。于是就有客户投诉,看评论中的数据都是一样的。无论怎么刷新都是 10 条一样的数据,和上一页的数据一样。
这个 zrangeByScoreWithScores 其实就是 Redis 中的 ZREVRANGEBYSCORE 指令。完整指令如下:
其中这个 limit 是可以分页的。这个分页对下拉刷新也有一个问题,那就是在你下拉刷新时,刚好新增了几个评论,所以刷新出来的数据也可能有重复的数据。
后来这个程序员针对这个问题有改了一下,每次拿到 lastScore 后加 1。我看到这个代码后,又找他了,这个做法肯定不行的。也就是说你每次拿到上一页最后一条的 lastScore 后,再加 1。就相当与时间上加了 1 秒,中间肯定会漏掉一些数据的。
那么该怎么办呢?如果你想使用 lastScore 进行分页,就必须保证它唯一。不然就有概率发生刷新列表时,出现重复数据。
我们这个和时事新闻还有些不一样,新闻的写入时间重复概率没有我们这个高。尤其是我们在大促的活动当中。
最后说一下这个问题的解决办法。一种就是保证 lastScore 唯一,或者说时间在进一步精确。还有一种就是 lastScore + limit 的组合来实现分页。或者就是单纯的使用 limit 来实现,但是也要注意不能刷新出重复数据。
我们的做法,最终是参考了上图。
将每个主题的 topicId 作为 set 的 key,将与该主题关联的评论的 createDate 和 commentId 分别作为 set 的 score 和 member,commentId 的顺序就根据 createDate 的大小进行排列。
当需要查询某个主题某一页的评论时,就可主题的 topicId 通过指令 zrevrange topicId (page-1)×10 (page-1)×10+perPage 这样就能找出某个主题下某一页的按时间排好顺序的所有评论的 commintId。page 为查询第几页的页码,perPage 为每页显示的条数。
当找到所有评论的 commentId 后,就可以把这些 commentId 作为 key 去 Hash 结构中去查询该条评论对应的内容。
这样就利用 SortSet 和 Hash 两种结构在 Redis 中达到了分页和排序的目的。
分享文章:Redis中SortSet使用不当导致的分页Bug怎么解决
分享URL:http://azwzsj.com/article/sppsgj.html