您好,登錄后才能下訂單哦!
這篇文章主要講解了“Redis中SortSet使用不當導致的分頁Bug怎么解決”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Redis中SortSet使用不當導致的分頁Bug怎么解決”吧!
首先,我們線上的電商系統正在進行一個大促活動。買家非常的多,導致一時間產生了非常多的評論。開發人員在存儲(保存)評論時,使用 Redis 中的 SortSet 這個數據結構。每新增一條評論,他都通過 zadd 命令將起保存至 Redis 和 MySQL 中,查詢時直接在 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怎么解決”的內容了,經過本文的學習后,相信大家對Redis中SortSet使用不當導致的分頁Bug怎么解決這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。