本文由轉轉平臺業務負責人王計寬分享,原題“轉轉push系統的演進之路”,下文有修訂和重新排版。
1、引言
顧名思義,push就是就是借助廠商通道把消息發送給用戶的一種方式,一般用于用戶的召回和活動觸達,和即時通訊IM在業務上稍有區別,但技術邏輯上是相通的,不在此處贅述。
本文將從0開始講講轉轉千萬級用戶量消息推送系統的架構演進和迭代過程,以及遇到的常見問題的解法,希望能帶給你啟發。

技術交流:
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK(備用地址點此)
2、術語解釋
以下是本文涉及到的一些技術術語的解釋:
- 1)業務屬性:運營、業務、功能類推送;
- 2)推送范圍: 月活、全量、定向推送、個性化推送;
- 3)目標端:一般是安卓、ios客戶端;
- 4)通道:小米、華為、魅族、apns等手機廠商的常駐連接;
- 5)token: 用于設備的唯一標識,由APP本身生成;
- 6)devicetoken:用于推送的唯一標識,一般由廠商提供;
- 7)推送量:推送消息的數量;
- 8)到達率:消息到達手機的數量/推送量;
- 9)點擊率:用戶點擊量/推送量。
3、當前架構概覽

現有的架構支持后臺推送、業務推送以及個性化推薦推送。
以下是相關推送業務的特點:
- 1)后臺推送:一般會有標準的格式,特點是時間短、推送量大,比如8點秒殺活動;
- 2)業務推送 :一般都是業務觸發,特點是實時性強、優先級高,如訂單支付消息;
- 3)個性化推送:經常會和用戶畫像相關,特點是策略復雜、內容多樣,需要有風控管理,如猜你喜歡等推薦策略。
4、技術背景——PM想推送運營活動
步驟:
- 1)PM從大數據平臺上導出一部分用戶集合;
- 2)RD寫程序調用push接口。
問題:
- 1)N個PM都有需求,RD..........;
- 2)8點有一個突發情況,9點來一波;
- 3)每周末都要活動,推送。
解決方案:
- 1)搭建一個后臺,支持根據用戶ID上傳,解放開發資源;
- 2)支持按照時間推送,支持文案可配;
- 3)支持安卓、IOS分端推送。
遺留的問題:PM上傳了一個瀏覽過手機類目用戶的數據集合,數據量太大,上傳超時。PS:用戶量大概在1000w左右+,大約300M左右的文件。
提示:
- 1)上傳的時間大約在1分鐘左右, 需要聯系運維設置最長的鏈接時間,否則nginx會主動斷開;
- 2)上傳由同步上傳,改成進度條的方式,讓上傳者可以看到進度;
- 3)上傳和數據處理分開(我們當時是邊上傳,邊解析文件比較慢)。
5、希望重大節日能夠即時通知到活躍用戶
5.1 實時推
問題描述:重大節日,推送全量用戶、月活、周活數據,每次僅是文案不同,PM都需要跑大數據系統,效率太低,當天數據不可獲得,平均推送需要1個多小時。
要求:
- 1)1億的數據能夠在一小時內推送完畢;
- 2)要覆蓋到某一個周期內的用戶(比如一個月);
- 3)支持預覽,支持暫停。
分析-數據量(以2000w月活為例):
- 1) 全量用戶認定為近3個月(90天)內訪問過轉轉的用戶;
- 2) 預估所有設備數量在5000w左右;
- 3) 預計占用的空間為5G。
分析-性能(以2000w月活為例):
- 1) 老系統push的平均QPS是2000;
- 2) 2000W/2000/60/2=83~=1小時20分鐘,希望能夠在12分鐘內推送完畢(一個小時推送1億的指標)。
難點分析:
- 1) 數據做到準實時,怎么算準實時;
- 2)2000千萬的數據12分鐘內推送完畢,QPS~=2.7w, 如何讓性能提升13.5倍(2k提升到2.7w的并發)。
解決方案:
- 1) 數據的準實時:實時接收kafka日志消息,每分鐘把清洗的數據進行合并;
- 2)需要存儲的數據要素:用戶的token信息(注意不是devicetoken);此token的活躍時間(時間戳);
- 3)用戶數據存儲選型。

最終選擇redis的zset進行存儲。
5.2 如何提高發送性能
首先分析之前之所以慢的原因:
- 1) 單線程發送;
- 2) 受到廠商通道的限制,單接口耗時100ms+(IOS通道)。
解決方案:
- 1)區分安卓、IOS單獨發送,原始程序只負責從redis拿到數據后拼裝成固定結構(簡單拼接操作速度很快);
- 2)把數據推送到MQ中(可以不用MQ嗎?);
- 3)多個消費訂閱者,進行消費(容易擴展),通過廠商 通道推送出去。
注意:iOS通道,我們用的pushy開源工具,特定情況下無法持續推送消息,需要定時檢查,重新創建通道。
最后的效果:push推送的QPS達到3w+,推送能力提升的同時,也引發了以下問題。
5.3 業務服務器扛不住瞬時流量
問題描述:當push的推送能力上去了之后, 用戶的瞬時訪問問題隨之而來
- 1)瞬時的流量高峰,導致超時增多;
- 2)部分請求到達性能瓶頸,超時增多,頁面打不開~,見下圖。
push落地效果:

解決辦法:
- 1)最簡單的辦法:加機器;
- 2)業務接口多線程、服務治理,消峰(ratelimit);
- 3)app核心功能增加緩存,保證不會出現白屏的情況;
- 4)減少活動路徑。(一般push都會落地到某一個活動頁面。但是正常打開push,都會先進入首頁,在跳轉到活動頁面。給push的消息增加特殊埋點,如果是此類push消息,就直接 跳轉到特定頁面,減少中間環節。)
6、AB實驗室
問題描述:有一天晚上9點推送了一個運營類的push,發現居然點擊率超級高,是文案優秀?還是流量高峰?
要求:存在多個推送文案,系統能夠擇優選擇點擊率最好的進行推送?
解決方式:加入AB測的能力,先進行少量用戶推送,根據AB的效果,擇優推送.
7、整合全部手機廠商級ROOM推送通道
新的問題:之前安卓的通道我們僅有小米通道+個推(個推達到率一般,做托底), 如果我們向華為手機推送消息,也是通過小米通道是很難到達的。
要求:
- 1)希望能夠把大廠的廠商通道都接進來;
- 2)推送的消息能夠根據用戶最后登錄的通道進行優化推送;
- 3)速度不能慢下來。
解決方式:
- 1) 搭建tokens服務,能夠批量判定devicetoken的最后使用的廠商(需要依賴轉轉客戶端上報);
- 2) 分庫分表的方式進行存儲;
- 3) 數據熱備到緩存中。
效果:當年統計能夠提高10%的達到率。
8、消息送達監控
一般的監控維度包含:
- 1)產品線:轉轉、找靚機等等;
- 2)客戶端:安卓、IOS;
- 3)指標:發送、到達、點擊的數量和比例;
- 4)數據對比:模板、周期;
- 5)通道:小米、華為、vivo、apns。

9、 本文小結
現狀:
- 1) 推送月活10分鐘;
- 2) 支持暫停、預覽,實時查看推送數據量;
- 3) 支持提前AB看效果;
- 4) 支持不在線,微信通知;
- 5) 支持防打擾;
- 6) 支持優先級和廠商高優通道。
提高速度:預加載+緩存+多線程+合理的數據結構+批量處理+合理布局+特殊埋點。
折中方案:異步上傳、限流控制、降級處理、分層解耦、補償通知。
10、 參考資料
[2] 魅族2500萬長連接的實時消息推送架構的技術實踐分享
[3] 專訪魅族架構師:海量長連接的實時消息推送系統的心得體會
[4] 基于WebSocket實現Hybrid移動應用的消息推送實踐(含代碼示例)
[7] Go語言構建千萬級在線的高并發消息推送系統實踐(來自360公司)
[10] 技術干貨:從零開始,教你設計一個百萬級的消息推送系統
[13] 消息推送技術干貨:美團實時消息推送服務的技術演進之路
[14] 揭秘vivo百億級廠商消息推送平臺的高可用技術實踐
[15] 得物從零構建億級消息推送系統的送達穩定性監控體系技術實踐
(本文已同步發布于:http://www.52im.net/thread-4852-1-1.html)
作者:Jack Jiang (點擊作者姓名進入Github)
出處:http://www.52im.net/space-uid-1.html
交流:歡迎加入即時通訊開發交流群 215891622
討論:http://www.52im.net/
Jack Jiang同時是【原創Java
Swing外觀工程BeautyEye】和【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
本博文
歡迎轉載,轉載請注明出處(也可前往 我的52im.net 找到我)。