我是如何用 Redis 做實時訂閱推送的?

作者:浮云騎士LIN

鏈接:https://www.cnblogs.com/linlinismine/p/9214299.html

前陣子開發(fā)了公司領(lǐng)劵中心的項目旨巷,這個項目是以redis作為關(guān)鍵技術(shù)落地的舶斧。

先說一下領(lǐng)劵中心的項目吧,這個項目就類似京東app的領(lǐng)劵中心督惰,當(dāng)然圖是截取京東的不傅,公司的就不截了。赏胚。访娶。

image

其中有一個功能叫做領(lǐng)劵的訂閱推送。什么是領(lǐng)劵的訂閱推送觉阅?就是用戶訂閱了該劵的推送崖疤,在可領(lǐng)取前的一分鐘就要把提醒信息推送到用戶的app中秘车。本來這個訂閱功能應(yīng)該是消息中心那邊做的,但他們說這個短時間內(nèi)做不了劫哼。所以讓我這個負(fù)責(zé)優(yōu)惠劵的做了-.-!叮趴。具體方案就是到具體的推送時間點了,coupon系統(tǒng)調(diào)用消息中心的推送接口权烧,把信息推送出去眯亦。

下面我們分析一下這個功能的業(yè)務(wù)情景。公司目前注冊用戶6000W+般码,是哪家就不要打聽了妻率。。板祝。比如有一張無門檻的優(yōu)惠劵下單立減20元宫静,那么搶這張劵的人就會比較多,我們保守估計10W+券时,百萬級別不好說孤里。我們初定為20W萬人,那么這20W條推送信息要在一分鐘推送完成革为!并且一個用戶是可以訂閱多張劵的扭粱。所以我們知道了這個訂閱功能的有兩個突出的難點:

1、推送的實效性:推送慢了震檩,用戶會抱怨沒有及時通知他們錯過了開搶時機(jī)琢蛤。

2、推送的體量大:爆款的神劵抛虏,人人都想搶博其!

然而推送體量又會影響到推送的實效性。這真是一個讓人頭疼的問題迂猴!

那就讓我們把問題一個個解決掉吧慕淡!

推送的實效性的問題:當(dāng)用戶在領(lǐng)劵中心訂閱了某個劵的領(lǐng)取提醒后,在后臺就會生成一條用戶的訂閱提醒記錄沸毁,里面記錄了在哪個時間點給用戶發(fā)送推送信息峰髓。所以問題就變成了系統(tǒng)如何快速實時選出哪些要推送的記錄!

方案1:MQ的延遲投遞息尺。MQ雖然支持消息的延遲投遞但尺度太大1s 5s 10s 30s 1m携兵,用來做精確時間點投遞不行!并且用戶執(zhí)行訂閱之后又取消訂閱的話搂誉,要把發(fā)出去的MQ消息delete掉這個操作有點頭大徐紧,短時間內(nèi)難以落地!并且用戶可以取消之后再訂閱,這又涉及到去重的問題并级。所以MQ的方案否掉拂檩。

方案2:傳統(tǒng)定時任務(wù)。這個相對來說就簡單一點嘲碧,用定時任務(wù)是去db里面load用戶的訂閱提醒記錄稻励,從中選出當(dāng)前可以推送的記錄。但有句話說得好任何脫離實際業(yè)務(wù)的設(shè)計都是耍流氓~呀潭。下面我們就分析一下傳統(tǒng)的定時任務(wù)到底適不適合我們的這個業(yè)務(wù)!

image

綜上所述我們就知道了一般傳統(tǒng)的定時任務(wù)存在以下缺點:

1钉迷、性能瓶頸。只有一臺機(jī)在處理钠署,在大體量數(shù)據(jù)面前力不從心!

2荒椭、實效性差谐鼎。定時任務(wù)的頻率不能太高,太高會業(yè)務(wù)數(shù)據(jù)庫造成很大的壓力趣惠!

3狸棍、單點故障。萬一跑的那臺機(jī)掛了味悄,那整個業(yè)務(wù)不可用了-草戈。- 這是一個很可怕的事情!

所以傳統(tǒng)定時任務(wù)也不太適合這個業(yè)務(wù)侍瑟。唐片。。

那我們是不是就束手無策了呢涨颜?其實不是的! 我們只要對傳統(tǒng)的定時任務(wù)做一個簡單的改造费韭!就可以把它變成可以同時多機(jī)跑,并且實效性可以精確到秒級,并且拒絕單點故障的定時任務(wù)集群庭瑰!這其中就要借助我們的強(qiáng)大的redis了星持。

方案3:定時任務(wù)集群

首先我們要定義定時任務(wù)集群要解決的三個問題!

1弹灭、實效性要高

2督暂、吞吐量要大

3、服務(wù)要穩(wěn)定穷吮,不能有單點故障

下面是整個定時任務(wù)集群的架構(gòu)圖逻翁。

image

架構(gòu)很簡單:我們把用戶的訂閱推送記錄存儲到redis集群的sortedSet隊列里面,并且以提醒用戶提醒時間戳作為score值,然后在我們個每業(yè)務(wù)server里面起一個定時器頻率是秒級酒来,我的設(shè)定就是1s卢未,然后經(jīng)過負(fù)載均衡之后從某個隊列里面獲取要推送的用戶記錄進(jìn)行推送。下面我們分析以下這個架構(gòu)

1、性能:除去帶寬等其它因素辽社,基本與機(jī)器數(shù)成線性相關(guān)伟墙。機(jī)器數(shù)量越多吞吐量越大,機(jī)器數(shù)量少時相對的吞吐量就減少滴铅。

2戳葵、實效性:提高到了秒級,效果還可以接受汉匙。

3拱烁、單點故障?不存在的噩翠!除非redis集群或者所有server全掛了戏自。。伤锚。擅笔。

這里解析一下為什么用redis?

第一redis 可以作為一個高性能的存儲db屯援,性能要比MySQL好很多猛们,并且支持持久化,穩(wěn)定性好狞洋。

第二redis SortedSet隊列天然支持以時間作為條件排序弯淘,完美滿足我們選出要推送的記錄。

ok~既然方案已經(jīng)有了那如何在一天時間內(nèi)把這個方案落地呢吉懊?是的我設(shè)計出這個方案到基本編碼完成庐橙,時間就是一天。惕它。怕午。因為時間太趕鳥。

首先我們以user_id作為key淹魄,然后mod隊列數(shù)hash到redis SortedSet隊列里面郁惜。為什么要這樣呢,因為如果用戶同時訂閱了兩張劵并且推送時間很近甲锡,這樣的兩條推送就可以合并成一條~兆蕉,并且這樣hash也相對均勻。下面是部分代碼的截圖:

image

然后要決定隊列的數(shù)量缤沦,一般正常來說我們有多少臺處理的服務(wù)器就定義多少條隊列虎韵。因為隊列太少,會造成隊列競爭缸废,太多可能會導(dǎo)致記錄得不到及時處理包蓝。

然而最佳實踐是隊列數(shù)量應(yīng)該是可動態(tài)配置化的驶社,因為線上的集群機(jī)器數(shù)是會經(jīng)常變的。大促的時候我們會加機(jī)器是不是测萎,并且業(yè)務(wù)量增長了亡电,機(jī)器數(shù)也是會增加是不是~。所以我是借用了淘寶的diamond進(jìn)行隊列數(shù)的動態(tài)配置硅瞧。

image

我們每次從隊列里面取多少條記錄也是可以動態(tài)配置的

image

這樣就可以隨時根據(jù)實際的生產(chǎn)情況調(diào)整整個集群的吞吐量~份乒。 所以我們的定時任務(wù)集群還是具有一個特性就是支持動態(tài)調(diào)整~。

最后一個關(guān)鍵組件就是負(fù)載均衡了腕唧。這個是非常重要的或辖!因為這個做得不好就會可能導(dǎo)致多臺機(jī)競爭同時處理一個隊列,影響整個集群的效率枣接!在時間很緊的情況下我就用了一個簡單實用的利用redis一個自增key 然后 mod 隊列數(shù)量算法颂暇。這樣就很大程度上就保證不會有兩臺機(jī)器同時去競爭一條隊列~.

image

最后我們算一下整個集群的吞吐量

10(機(jī)器數(shù)) * 2000(一次拉取數(shù)) = 20000。然后以MQ的形式把消息推送到消息中心但惶,發(fā)MQ是異步的蟀架,算上其它處理0.5s。

其實發(fā)送20W的推送也就是10幾s的事情榆骚。

ok~ 到這里我們整個定時任務(wù)集群就差不多基本落地好了。如果你問我后面還有什么可以完善的話那就是:

1煌集、加監(jiān)控妓肢, 集群怎么可以木有監(jiān)控呢,萬一出問題有任務(wù)堆積怎么辦~

2苫纤、加上可視化界面碉钠。

3、最好有智能調(diào)度卷拘,增加任務(wù)優(yōu)先級喊废。優(yōu)先級高的任務(wù)先運行嘛。

4栗弟、資源調(diào)度污筷,萬一機(jī)器數(shù)量不夠,力不從心乍赫,優(yōu)先保證重要任務(wù)執(zhí)行瓣蛀。

目前項目已上前線,運行平穩(wěn)~雷厂。


以上惋增,便是今天的分享,希望大家喜歡改鲫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诈皿,一起剝皮案震驚了整個濱河市林束,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稽亏,老刑警劉巖壶冒,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異措左,居然都是意外死亡依痊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門怎披,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胸嘁,“玉大人,你說我怎么就攤上這事凉逛⌒院辏” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵状飞,是天一觀的道長毫胜。 經(jīng)常有香客問我,道長诬辈,這世上最難降的妖魔是什么酵使? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮焙糟,結(jié)果婚禮上口渔,老公的妹妹穿的比我還像新娘。我一直安慰自己穿撮,他們只是感情好缺脉,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悦穿,像睡著了一般攻礼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上栗柒,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天礁扮,我揣著相機(jī)與錄音,去河邊找鬼傍衡。 笑死深员,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛙埂。 我是一名探鬼主播倦畅,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绣的!你這毒婦竟也來了叠赐?” 一聲冷哼從身側(cè)響起欲账,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芭概,沒想到半個月后赛不,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡罢洲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年踢故,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惹苗。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡殿较,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桩蓉,到底是詐尸還是另有隱情淋纲,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布院究,位于F島的核電站洽瞬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏业汰。R本人自食惡果不足惜伙窃,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望样漆。 院中可真熱鬧对供,春花似錦、人聲如沸氛濒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舞竿。三九已至,卻和暖如春窿冯,著一層夾襖步出監(jiān)牢的瞬間骗奖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工醒串, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留执桌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓芜赌,卻偏偏與公主長得像仰挣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缠沈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容