本文做者:友盟+技術專家 劉章軍小程序
前言:App推送在平常運營場景中常常用到,如:資訊類的新聞及時下發、生活服務類優惠券精準推送、 電商類的貨品狀態或是促銷優惠等,一般開發者會根據運營的需求經過自建消息推送通道或使用第三方消息推送平臺實現,但自建消息推送的開發成本和人力成本很是高, 不少App開發者選擇第三方消息推送。今天就以友盟+消息推送U-Push,詳細解讀在海量業務背景下如何保證服務的穩定性以及功能豐富的觸達服務。緩存
========安全
友盟+消息推送U-Push日均消息下發量百億級,其中篩選任務日均數十萬,篩選設備每分鐘峯值可達7億+,本文將分享友盟+技術架構團隊在長期生產實踐中沉澱的篩選架構解決方案。微信
友盟+U-Push篩選是Push產品的核心功能,其中實時篩選是面向推送要求較高的付費Pro用戶提供的核心能力之一,實現了用戶實時打標、篩選、分發、觸達的功能。友盟+U-Push的設備識別以device_token爲基準,爲保證儘量的觸達咱們留存了近期全部可能觸達客戶的device_token,以10億真實設備爲例,每一個設備安裝10個集成友盟+SDK的應用能夠產生10個device_token,牽扯到硬件環境變更致使的device_token漂移問題,可能產生更多device_token。數據結構
( 圖1.1.1 友盟+U-Push業務數據流簡圖)架構
圖1.1.2 友盟+U-Push功能清單併發
================app
U-Push服務由兩個關鍵鏈路組成,下行鏈路保證客戶消息的觸達,上行鏈路承載終端採數和與客戶服務端的數據同步。其中下行鏈路主要分爲任務調度、篩選中心,上行鏈路主要服務是多種收數通道(爲兼容歷史問題)和設備中心,上行經過設備中心實現跟下行橋接。高併發
圖2.1.1 友盟+U-Push篩選業務場景工具
在U-Push服務中,依照業務場景不一樣定義了多種任務類型,其中除單播、列播直接下發外組播、廣播、自定義播、自定義文件播均須要經過篩選服務處理後纔可執行下發,下行鏈路中(如圖2.1.2)優先級最高是的任務受理和任務發送流程(紅色鏈路),即不管發生什麼狀況都要保證客戶消息的正確下發,是U-Push服務穩定性的底線。出於融災考慮,篩選服務在架構上與主鏈路解耦。
圖2.1.2 篩選和核心鏈路隔離
提到篩選,其本質是經過創建合理的標籤索引系統實現數據的快速定位。篩選的目標是U-Push核心設備庫,可是爲避免篩選請求影響到核心庫穩定須要將待篩選集合分庫冗餘存儲,與通常OLAP,OLTP場景不一樣,U-Push篩選的應用場景更加苛刻。
篩選本質仍是在線場景,具備必定的併發能力,併發壓力主要在於壓榨系統IO上,經過合理的中間件使用、嚴謹的服務調度、針對性場景的差別化設計下降單次篩選的執行時間,提升併發。
篩選提供了多種分析維度(圖2.2.2),支持靈活的語法組合。篩選服務不只要知足對海量數據的實時查詢分析,還要支持對單次可能破億的結果集作低成本傳輸。
圖2.2.2 篩選支持的字段類型
========
一切問題都是成本問題,從行業看全民上雲後服務架構的成本問題更是備受關注,尤爲在友盟+龐大的業務量下成本問題更加劇要。
=================
友盟+U-Push的發送層集羣用於大量的發送節點,最理想的設計就是在任務篩選階段即完成數據切片、分發、調度,下游直接並行發送以達到最高效率。
U-Push篩選在持續的技術迭代中,和多領域專業團隊深度合做,充分利用不一樣組件的特性,經過整合Tair、AnalyticDB for MySQL(ADS)、OSS、MaxCompute(ODPS)、Lindorm、HBase、SchedulerX等產出了一套兼顧穩定、性能、和成本的均衡解決方案。
篩選分爲離線和實時兩部分,離線經過ODPS生成設備主庫快照,導入ADS。實時經過消費數據上行服務的設備信息更新事件,實時更新ADS或者RDB庫。在執行篩選時候,對於較大結果集經過upload或者dump到OSS的方式輸出多個小文件,傳輸給發送鏈路下游執行並行發送。
圖2.2.4 篩選服務數據流向
上述業務鏈路和數據結構介紹了篩選目前的總體設計,可是要應付複雜的客情和多變的業務場景還須要作更多細節設計。
從上面的概覽能夠看出,篩選架構中的主要矛盾就是消息下行鏈路中海量數據的讀和上行鏈路中設備屬性更新的高頻寫的矛盾,解決這個矛盾須要大量的資源來保證數據一致性和性能,在常規的設計思路中在目前的成本資源下幾乎是不可行。大數據三大寶,冷熱分離分庫分表,經過業務分析調研,U-Push將業務分紅若干場景,基於客戶的不一樣生命週期的業務訴求和服務能力將客戶指向不一樣場景,儘可能優化客戶體驗。
圖3.1.1 篩選庫的場景設計
組播和廣播篩選咱們主要圍繞ADS來建設,ADS提供了實時和離線兩種更新方式,在產品形態上只對Pro客戶開放實時篩選能力,在架構設計上經過分庫的方式隔離不一樣層客戶的數據,提供差別化服務,提升穩定性。
離線部分:經過離線主庫保證了全部客戶的T+1篩選能力。在實際業務中離線主庫只有讀請求做爲全部極端場景下的兜底,離線主庫以device_token分區,能夠實現徹底打散可是聚合查詢的時候性能稍差。爲了提升部分客戶尤爲是新客戶的體驗咱們設計了新客戶離線庫,修改成客戶分區,提升了單客戶聚合查詢的效率。可是新客戶離線庫因客戶間的規模差別容易引起分區傾斜,生產中這個表須要持續關注,及時清理和轉移,不然在跑ads_loader的時候可能破線。
圖3.1.2 離線主庫的分區狀態
圖3.1.3 以客戶爲分區的分區傾斜狀況
實時部分:保證明時篩選服務體驗是整個系統的重點,將實時篩選再細分爲VIP實時庫、測試設備庫(方便客戶接入階段實時獲取測試效果)、新客戶實時庫(新增客戶通常設備量很小,U-Push會免費提供一段時間的實時篩選服務)。與離線分區相似,在分區設計上一樣對大規模場景數據和較少規模場景的數據分表,特別的測試設備庫可能產生大量髒數據,總體隔離出來。
圖3.1.2 客戶場景遷移
新客戶接入伊始基於客戶規模區分,在不一樣的生命週期節點會被引入特定的場景,在保證大盤能力的前提下儘可能輸出更優質的客戶體驗。
在上述設計中經過離線和實時的區分,下降了高頻寫可能對設備庫形成的影響。可是始終繞不過海量數據的傳輸問題,爲規避這個問題U-Push採用差別化的設計思路,以結果集規模作區分,對大結果集直接經過ADS dump到OSS,基於不一樣客戶的並行度作遠程切分,在OSS完成upload和split操做後返回文件路徑集合,後續鏈路只保留文件路徑集,直至進入發送層執行並行發送。對小結果集經過select拉取到內存整合消息報文傳輸,後續鏈路直接發送設備ID。經過OSS作中間存儲,極大的下降冗餘的IO損耗。
ADS3.0因爲總體架構改動改成經過外部表的方式dump到OSS,與2.0能夠dump出單個文件不一樣3.0在dump後會產生一系列小文件直接致使原有的方案不可行,在經過和ADS團隊溝通後ADS特意在3.0版本完善了dump單個文件的功能,致謝ADS的同窗。
圖3.2.1 篩選查詢中的性能瓶頸風險
談到查詢場景,必然會有緩存的一席之地,與通常設計思路不一樣,U-Push直接放棄了針對實時篩選能力的查詢緩存,由於在這樣的設備量級下隨時的設備更新是必然。U-Push的實時篩選庫是一個高頻寫低頻讀的場景,可是對單次讀的要求比較苛刻,首先對未開啓實時功能的離線客戶,由於設備庫是快照形式,一天內的屢次讀拿到的結果必然相同這時候設置緩存就頗有意義,好比新聞、氣象、工具類客戶的習慣,一天內發送屢次廣播,就沒必要每次再去從新生成篩選集文件。
圖3.3.1 查詢緩存邏輯流程圖
預篩選功能的開發是個小插曲,前面講到U-Push放棄了對實時的查詢緩存,致使客戶的每次消息發送都要從新去生成文件,在保證數據實時性的角度考慮無可非議,可是遇到「較真」的客戶就頗有壓力。好比新聞類客戶極度關注消息下發的時效性,經過開發者控制檯能夠查看每一個任務的篩選時間,有時候同類消息2s的差別也會引起客戶在DING羣的"客訴"。客戶的訴求能夠理解可是這也耗費了團隊大量的精力。經過和個別客戶溝通U-Push開發了預篩選功能,在客戶習慣性發送消息的前一段時間預先調度執行篩選邏輯生成設備ID集合,經過損失少許的數據時效性來壓縮消息下發時間,爭取消息發送速度。
圖3.3.1 友盟+U-Push消息軌跡
Alias功能簡介:Alias容許開發者爲設備綁定別名,別名由alias_type,alias兩個屬性組成,譬如開發者能夠標識設備A,爲他增長alias_type=telephone_number, alias=13900000000以此來給設備A增長手機號的屬性。在發送消息時候能夠繞開device_token,直接經過服務端指定alias實現觸達,alias是一個典型的NVN ID Mapping場景,一個設備在同一個alias_type下面同時只能擁有一個alias。這也是符合通常業務場景的,好比上例通常一個設備只有一個手機號,設置新手機號後會覆蓋原alias。若是須要知足雙卡雙待的功能,須要設置兩個alias_type,即alias_type=telephone_number_main,alias_type=telephone_number_secondary。alias的通常使用場景是開發者經過自定義文件播上傳一批文件,文件內容爲某個alias_type下若干設備alias的集合(百萬千萬級)。篩選服務掃描文件後依次找出alias值mapping的device_token。
說到Mapping,輪詢,高吞吐查詢,首當其衝選Redis,早期的U-Push也是如此。
圖3.5.1 alias早期數據結構設計
alias利用Redis的Set和Hash結構實現正查和反差的功能,爲何反差用hash,前面講到1個設備在1個alias_type下只保存最新的alias。這也是出於保護用戶的目的,若是1個設備同時存在多個alias下,在開發者執行圈選的時候可能會屢次選出這個設備形成屢次無效觸達。
這個設計平淡無奇,的確也能夠知足絕大部分客戶的篩選場景,可是隨着業務量的增長有幾個問題逐漸暴露
分庫的確是很好的思路可是仍然沒法知足性能問題和持久化問題,並且隨着行業對大數據的關注,數據返還也成爲更多開發者的訴求。打通數據返還鏈路作好客戶數據的存、取、管、用已是一個重要的行業方向。爲了解決這個問題U-Push經過離線和實時相結合制定措施
用寬表代替Redis的Set設計作正查,用普通表基於設備ID的聯合主鍵作反查,在查詢時候經過將單次輪詢改成屢次mget儘可能壓縮IO損耗尋找響應性能和服務穩定的中間值,Lindorm的磁盤存儲能夠知足業務需求的同時經過exporter的配置實現lindorm數據T+1同步至ODPS。
圖3.5.2 基於Lindorm款表的分層設計
數據遷移是在不少業務架構中都是痛中之痛,如何保證穩定、平滑、安全的遷移須要付出大量的成本。U-Push在Alias的數據遷移中作了多種方案的研究和思考。
第三種方法能夠實現存量數據的完美遷移,對線上服務幾乎沒影響,可是在百億級設備下,以1wTPS計算仍然須要10天的時間,好在該方案能夠實現單個客戶的灰度與回滾。
======
U-Push篩選服務只是U-Push衆多服務中的一環,在友盟+巨大的業務量下,爲知足形形色色的各行業需求輸出了大量精緻的設計,本文列出的只是冰山一角,日均消息下發量百億級作到遊刃有餘離不開其餘技術架構團隊在篩選服務迭代中的共同協做。
目前U-Push已經以Push通道爲基礎,整合了微信、短信、隱私短信升級爲多通道觸達服務,爲衆多知名的App如:今日頭條、澎湃新聞、做業幫、易車等提供了觸達能力,後續持續接入支付寶小程序、頭條號等更多運營場景通道,持續爲客戶提供穩定、高性能、低成本的觸達能力保證。
友盟+,國內領先的第三方全域數據智能服務商,截至2020年6月已累計爲200萬移動應用和890萬家網站提供十年的專業數據服務。