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