爲何要儘快到達用戶端呢?ios
由於消息具備時效性,在一個不恰當的時間給用戶消息,不只容易被忽略,並且會騷擾到用戶。mongodb
咱們須要解決幾個問題:json
一、用戶按活躍日期由新到舊順序排序。緩存
二、推送過程當中途中止後,能夠從新推送新消息。那麼就須要一個能夠重複消費的高性能消息隊列。服務器
三、消息推送過程,用戶可能網絡在那時間點沒鏈接上,因此須要存儲起來,等用戶鏈接上來的時候同步消息。因而,須要一個高性能的存儲。網絡
四、用戶能夠按條件篩選出指定的一部分用戶。(男/女)(主播/用戶)(商家/用戶)架構
存量用戶量級,咱們以5000W作爲目標。性能
如下爲架構圖:spa
首先,從點擊「消息推送」按鈕開始,須要儘快發送用戶。因而,用戶活躍排序不能是臨時排序,必須提早排好序。咱們採用天天凌晨4點,導出一份用戶活躍排序的數據。.net
其次,活躍用戶有必定量級,會產生大量的網絡鏈接/斷開鏈接(長鏈接架構)。若是是短鏈接架構可能會更多。每次用戶鏈接活躍就會記錄下這個用戶的活躍時間點,那麼也須要一個高寫入性能可擴展的存儲。
最後,排序導出的用戶活躍的過程,不能產生重複的用戶數據(快照),不然就會有用戶重複收到相同的消息。
這裏採用了mongodb的wiredtiger引擎來處理記錄用戶的活躍時間以及ios token等信息。高寫入性能,而且能夠支持按任意索引來排序導出快照。這裏存儲的用戶信息,除了提供給推送系統外,還會提供給其它系統使用。例如用來查詢userID與DeviceID之間的關係。
(mongodb分片按照用戶來區分)
導出了用戶活躍數據,就能夠把這個預先插入到消息隊列裏,等待隨時被消費。
消息可隨時終止推送,而且從新發送新消息。那麼就要求消息隊列裏的用戶數據在消費後不能立刻就刪除了,要可重用。
這裏採用Kafka做爲消息隊列,消息消費至關於遊標移動。當須要終止推送時,遊標從新迴歸初始值便可從新消費。不存在從新導出用戶活躍排序和從新加載進隊列的過程。
消息的特性是:
一、有時效性,因此須要有數據過時功能。
二、數據量很大,高寫入,高刪除,無更新。須要儘可能避免磁盤碎片。
三、基本都是冷數據,消息讀取一次,就不會再讀了。緩存無做用。
採用cassandra的一大緣由:
一、相比mongodb節約資源。cassandra採用DateTieredCompactionStrategy存儲策略,很是適合臨時性數據的刪除和回收。避免壓縮數據時,還須要預留一倍的內存來作壓縮操做。
二、架構相對mongodb層級要少,性能消耗更少,更容易管理。
(cassandra分片按照用戶來區分)
消息的重要性:
一、不只僅應用於消息推送,用戶之間的IM私信、訂閱的內容提醒等等。因此必需要可容災的。
二、當推送的速度很快,佔滿了消息存儲的資源怎麼辦?這是須要推送服務控制好速度的。
這種狀況若是要作出一個理想的方法比較難。咱們假設分爲兩種狀況:
一、條件比較少,篩選出來的用戶比較多。(商家/用戶)
二、條件比較多,篩選出來的用戶比較少。(廣州天河區的男性用戶)
第一種狀況,咱們依舊採起預處理的方法。與全局用戶的處理方法同樣,只是分了不一樣的隊列名。
第二種狀況,因爲數據量比較少了。咱們能夠動態篩選用戶,這須要耗費必定時間在篩選用戶上面,不能當即推送。但因爲用戶量少了,最終的完成時間也會在可控範圍內。
從效果上看,當運營操做人員點擊「推送消息」按鈕開始,最近活躍用戶就馬上陸續收到了消息推送。每一個環節都是可擴展的,以普通服務器爲評估,Kafka消費每秒6W+不成問題,cassandra寫入每秒4W+,推送服務每秒2W+(json解析格式比較耗時)(部署兩個實例)。比較容易就達到了4~5W的速度。1分鐘300W用戶;5000W用戶大約16分鐘能夠處理完成。固然,這是把資源耗光的計算方法了,實際上仍是須要預留資源的,並且也會擴展多個節點來擴展性能。
原創博客,轉帖請註明原出處:http://my.oschina.net/u/223522/blog/726417