基於Redis的推薦瀑布流
阿新 • • 發佈:2018-12-19
前言:Redis在目前的網際網路公司的應用場景非常的豐富,最近公司為了給產品新增社交屬性,仿微信的朋友圈做了一個骨人云
,包括關注和發現兩個頻道,再加上本次改版之前的產品首頁的五個頻道頁中的四個頻道頁,都是推薦的瀑布流,我大量使用Redis
的SortedSet,這裡記錄一下,希望給在處理型別業務場景的同學提供一個方向,因為全是自己摸索的,不知道大廠是怎麼做的,有不對的地方歡迎指正。
-
SortedSet的簡介
- 說SortedSet,要先說一下Redis的另外一個數據型別Set,類似於Java的Set,Set是一個字串的集合,不允許重複的成員變量出現在一個
Set
中。而SortedSet和Set型別極為相似,它們之間的主要差別是SortedSet中的每一個成員都會有一個分數(score)與之關聯,Redis正是通過分數來為集合中的成員進行從小到大的排序。然而需要額外指出的是,儘管SortedSet中的成員必須是唯一的,但是分數(score)卻是可以重複的。在Sorted-Set中新增、刪除或更新一個成員都是非常快速的操作,其時間複雜度為集合中成員數量的對數。由於SortedSet中的成員在集合中的位置是有序的,因此,即便是訪問位於集合中部的成員也仍然是非常高效的。事實上,Redis所具有的這一特徵在很多其它型別的資料庫中是很難實現的,換句話說,在該點上要想達到和Redis同樣的高效,在其它資料庫中進行建模是非常困難的。
- 說SortedSet,要先說一下Redis的另外一個數據型別Set,類似於Java的Set,Set是一個字串的集合,不允許重複的成員變量出現在一個
-
應用場景
- 目前主流的就是排行榜,因為SortedSet自帶的排序功能,很容易根據按照根據score從小到大或者從大到小的取出一定數量的資料,還可以根據score的值取值在當前的值範圍內的資料。比如我們做全站資源的瀏覽的排行,我們就可以以資源的ID作為member成員,當資源被瀏覽一次後使用ZINCRBY給對應資源的score加1,這樣我們就可以隨時的查詢當前時刻排行較前的資料
-
推薦瀑布,下面詳細列出我的實現步驟
- 原理:後端介面返回的時候會返回前端返回資料的中的最大的score和最小的score兩個值,標識當前使用者資料的棧頂和棧底,後續使用者通過傳遞這兩個值的其中一個,並且告訴我們是上拉,還是下拉,我們就可以分頁取對應的資料,資料圖如下
- 步驟:
- 使用者第一次進入的時候,我們推薦給當前使用者的資料是100到115的資料,首屏載入後端返回前端五條資料即110到115,同時返回前端兩個score值drop(115)、up(110),前端展示對應資料的時候,同時儲存這兩個值,這個時候我們推薦給了使用者116到124的資料,這個時候沒有score值,直接使用
zrevrangeWithScores(customerId, 0,5)
,進行分頁取值, - 使用者如果執行了下拉動作,需要前端傳遞115這個score的值,同時告訴我們是下拉動作,我們會返回前端116到120的資料,同時返回前端兩個score值drop(120)、up(116),這個時候前端應該更新本地快取中的值,把drop更新為120,up保持110不變,目前前端一共顯示10條資料,根據score值獲取大於當前score值的資料,使用
zrangeByScoreWithScores(customerId, "115", "+inf")
- 如果使用者執行了上拉動作,需要前端傳遞110這個score值,同時告訴我們是下拉動作,後端需要返回105到109的資料,同時返回前端兩個score值drop(109)、up(105),這個時候前端應該更新本地快取中的值,drop保持120,up更新為105,目前前端一共顯示15條資料,根據score值獲取小於當前score值的資料,使用
zrevrangeByScoreWithScores(customerId, "110", "-inf")
- 如果使用者再一次下拉的時候,前端傳遞120這個score的值,其他的如2.。。。
- 使用者第一次進入的時候,我們推薦給當前使用者的資料是100到115的資料,首屏載入後端返回前端五條資料即110到115,同時返回前端兩個score值drop(115)、up(110),前端展示對應資料的時候,同時儲存這兩個值,這個時候我們推薦給了使用者116到124的資料,這個時候沒有score值,直接使用
- 原因:為什麼需要根據score的來決定獲取資料的位置,因為SortedSet中的值,隨時有可能會增加和刪除,雖然SortedSet本身是支援分頁獲取資料,但是這個列表隨時可能增加或者刪除資料,我們根據分頁獲取的資料,很可能和上次返回給前端的值是包含重複的。比如使用者首屏載入了110到115的資料,如果這個時候我們沒有給使用者推薦資料,下次我們分頁取的時候應該是105到109,但是我們把112從這個列表中刪除了,那樣就會取的是104到108這些資料,這樣導致資料丟失。同樣如果這個時候我們給使用者推薦了116,這個時候上拉的時候分頁取第二頁的資料,那就取的是106到110,這樣前端就會顯示出重複的資料了
- 優化:如果自己站內的資源非常的龐大,並且會不停的推薦給使用者,那就要做好定時清理資料的準備,避免SortedSet特別大的情況,我們可以每次在給使用者推薦資料的時候,使用
ZCARD
,計算當前的列表的量,如果超過一定的量可以先刪除一部分。