如何在高并發下使用Redis實現排行榜的功能,你學會了嗎?
在我們日常的生活中排行榜是常見的功能,如游戲的排行榜,銷售額的排行榜等等,排行榜不僅可以讓用戶有更多的激情參與到活動中來,而且可以更好的留存住用戶,如下所示的拉新排行榜:
圖片
排行榜是一個常見的業務需求,下面我們就來聊聊如何通過Redis來設計一套支持高并發的排行榜的功能。
1、支持高并發的Zset實現榜單方案
假設業務需要展示排名前10名的用戶在榜單上,假如在每一小時內前10名必然是在前200名之中產生,我們使用Redis的Zset數據結構來設計的方案如下所示:
(1)定時任務定期(如60分鐘執行一次)從數據庫中同步排名前200名用戶到Redis的Zset中。
(2)Redis實時維護前200名用戶數據,當榜單數據發生變化的時候,我們同步數據到Redis上和數據庫中,但是數據庫中數據的變化不會在下一次定時任務執行之前影響到當前的榜單數據。
(3)定時任務下一個周期到了之后,就重新同步數據庫中最新的前200名排名數據到Redis上。
本方案將排名靠前的數據(前200名)放到Redis中,這樣避免在Redis的Zset中實時維護全量數據的問題,同時定時任務更新數據到Redis上的周期是可以根據業務需要來變更的。
針對突發的熱點數據,當前的榜單設計就難以及時反映出來,需要等到下一個定時任務的周期才能同步到Redis上,當然本方案也是適應的,因為高并發下市面上的排行榜一般都是近實時的。
2、支持超高并發的榜單設計方案
在超大數據量、超高并發下,以至于超過了Redis單一節點的上限(單個Redis的寫入瓶頸在2w左右,讀瓶頸在10w左右),如果使用一個Zset來維護榜單數據的時候Redis是支撐不住的,即使Redis集群部署也是沒有意義的,因為一個Zset就是一個key,一個key只會落在集群的一個Redis節點上,針對這樣的場景,可以考慮采用分key的方案來實現榜單功能,如下圖所示:
圖片
(1)將Zset上原先的一個key拆分成多個小key,然后通過這些小key來存儲所有的榜單數據。拆分key的方案之前龍蝦也分享過,有興趣的小伙伴可以看一下:超高并發下Redis分key的實現原理
(2)實時維護Zset上的榜單數據變化
(3)定時任務定期從各Zset節點上各取前10名的數據,然后將各個節點報送過來的前10名匯總在一起后取出全局的前10名數據,最后同步到服務器的本地緩存上。
圖片
在超高并發、大數據量下通過分key的方案可以有效的解決單key無法支撐的問題,這就是一種分而治之的思想。
設計本地緩存是因為在超高并發下保護Redis節點的一種做法,所有的請求都會打到本地的緩存上,Redis通過定時任務將最新的數據定期同步到本地的緩存上。
總結:
(1)高并發下排行榜的功能我們可以通過定時任務+Redis的方式來實現
(2)針對超高并發、大數量的的業務場景,我們采用Redis分key+本地緩存的方案來實現。