騰訊優測|優社區乾貨精選-手Q紅包後臺設計!

文 / 騰訊 鄧建俊算法

優測小優有話說:
  你覺得優社區只有測試相關的知識嗎?手機QQ大牛帶你走一波紅包後臺設計!數據庫

  1. 前言

2016除夕夜註定是一個不平凡的夜晚,除了陪家人吃團圓飯、看春晚,還得刷一刷、搖一搖、咻一咻,忙得不亦樂。相信大部分讀者也已經體驗過手Q的刷一刷搶紅包,玩法簡單中獎率高,獲得了許多用戶的好評。
後端

那麼對於後臺而言,要實現這個億萬級用戶的搶紅包系統,咱們將會面臨哪些問題?緩存

(1)海量的併發請求,預估峯值800w/s安全

800w/s的預估峯值請求,紅包系統必需要保證在如此高併發的請求下,可以對每個請求都及時正確的處理並作出響應。架構

(2)億萬數量的紅包如何派發併發

刷一刷紅包的獎品,除了現金紅包外,還有各類卡券(如京東券、滴滴打車券等)和個性裝扮類獎品(如明星氣泡、掛件等),如何保證億萬數量的獎品公平公正的發放,很少發、不錯發,而且保證獎品儘量的發放出去,是紅包系統面臨的一道難題。另外,與各種獎品相對應的業務,他們的能力也不盡相同,獎品發放速度的控制也成爲了後端業務系統正常運做的關鍵。運維

(3)安全如何保障分佈式

對於一個掌握着億萬資金髮放的系統,一些不法分子確定會千方百計利用各類漏洞來盜取資金,那麼一套完備的安全防禦措施就顯得及其重要。高併發

(4)異常狀況如何處理

刷一刷紅包系統部署上線,真正提供搶紅包服務也就幾個小時的時間,常規系統的灰度發佈、逐步優化的流程顯然不適用。因此咱們必須分析出各個可能過載或故障的節點,並對這些節點設計好柔性策略。

  1. 抽獎最小系統

在解決上面說起到的問題前,咱們先看看一個能基本運做的紅包最小系統,以下圖所示:

主要的處理流程以下:

首先,刷一刷是以活動的形式進行的,每輪活動的信息資源和商家素材資源會預先從CDN預下載到客戶端,客戶端在須要使用的時候,能夠直接從本地加載,避免在抽獎峯值時下載從而對CDN帶寬形成衝擊,同時本地取資源也能夠有更好的用戶體驗;

客戶端判斷到活動開始時,會展現出刷一刷的入口,用戶進行刷的操做,會產生抽獎請求,抽獎請求發送到手Q接入層SSO,而後轉發到抽獎邏輯層;

抽獎邏輯層通過一系列的邏輯判斷,給客戶端返回一個結果:中了現金、中了虛擬獎品或者沒中獎,中獎後相關信息會保存在存儲層;

若是是中了現金,交由財付通的支付系統對用戶進行充值併發送公衆號消息通知用戶中獎;

若是是中了虛擬獎品,會調用基礎IM後臺的接口發送公衆號消息通知用戶中獎並提供領取入口。用戶點擊領取獎品,抽獎系統會給對應的業務返回領用資格和設置已領用標誌。另外,對於某些內外部卡券類的獎品,抽獎系通通一隻對接增值部的禮包發貨系統,用戶領用這部分獎品,會調用禮包發貨系統接口,走MP營銷平臺進行發貨。

那麼,如何完善上述的系統,使之既可以知足業務的需求,又可以應對文章開頭所描述的幾個問題呢?

  1. 完善抽獎系統架構

3.1 緩存機制

業務要求在每一個刷一刷的活動中,能對用戶中獎次數、參與時間(30秒)進行限制。常規的實現裏,用戶的每一個抽獎請求到來時,先到存儲層獲取用戶的中獎歷史信息,斷定用戶是否還有資格進行抽獎,但在高併發的請求下,對存儲層勢必也會形成巨大的壓力。因此這裏咱們引入了本地內存緩存層,用於保存用戶的中獎歷史信息,每次請求到來時,會先到緩存層獲取用戶的中獎歷史信息,若是在緩存層沒找到,纔會到存儲層獲取,這樣就不會對存儲層形成大壓力,同時也能實現業務的需求。緩存層使用Memcached實現,但單靠這個緩存機制是否是就解決了存儲層訪問壓力的問題了呢?

3.2 一致性hash尋址

雖然引入緩存層可以緩解存儲層的訪問壓力,但別忘了,抽獎邏輯層是一個分佈式的系統,在使用普通的路由算法下,同一個用戶的請求不必定會落在同一臺邏輯機器處理,也就是說,不必定可以命中以前保存在本地的緩存。因此爲了使緩存生效,咱們在手Q接入層SSO使用了一致性hash的路由算法進行尋址,同一個uin的請求會落在同一臺邏輯機器進行處理。

3.3 存儲層選型

存儲層的設計向來都是後臺架構設計中的重點和難點。目前公司內部較成熟的存儲系統有CMEM、Grocery,通過一番對比咱們選擇使用Grocery,主要緣由有如下幾點:

(1)強大的帶條件判斷的分佈式原子算數運算

抽獎邏輯裏須要對每一個獎品進行計數,避免多發少發,因此一個高效可靠的分佈式原子加計數器顯得格外重要,Grocery支持帶條件判斷的原子加計數器,調用一次接口就能完成獎品計數值與配額的判斷以及獎品計數值的增長;

(2)靈活的數據類型

Grocery支持Key-Key-Row類型的數據存儲格式,能夠靈活的存儲用戶的紅包中獎信息,爲獲取用戶單個紅包或者紅包列表提供了豐富的接口;

(3)部署、擴容方便

Grocery在公司內部有專門的團隊支持,易於部署和擴容。

3.4 獎品配額系統設計

刷一刷紅包的玩法是以活動的形式存在的,業務要求每場活動要發放多少份的現金,多少份的虛擬獎品,每種獎品的發放比例是多少,這些都是該場活動的配額數據。另外,業務還要求獎品的發放額度要可以根據用戶參與數靈活配置,保證在用戶多的時候獎品多,並且無論在活動的任何一個有效時間點進來,都有機會中獎。

在活動期間,若是某個獎品對應的業務出現了故障,須要中止發放該獎品(發放比例修改成0),要求各臺抽獎邏輯機器可以快速穩定的同步到修改的配置。基於以上幾點咱們設計了這樣一個配額系統:

在當天活動開始前,根據產品給的配額數據生成一份當天全部活動的Json格式配置;

配額管理工具能夠對該Json配置進行相關合法性檢查,檢查OK後,把配置導入到Grocery數據庫,並更新Seq;

運行在各臺抽獎邏輯機器的配額agent會按期的檢查Grocery裏的Seq,若是Seq發生了變化,代表配額數據發生了變化,而後就會從Grocery獲取最新的配置,並更新到抽獎邏輯的本地共享內存shm;

抽獎邏輯的每一個進程也會按期檢查本地shm的內容,發現有變化,就會從新加載shm的配置。

這樣配額系統就實現了能夠秒級別控制獎品的發放額度,能夠隨時根據現場狀況調整發放比例,並在短期內(10s)同步配置到全部的抽獎邏輯機器。

3.5 獎品發放限頻設計

每一種獎品,對應的業務都有他們本身的能力,且各業務的能力也不盡相同(如黃鑽8w/s,京東1w/s)。通常的,咱們在配置配額時(按照100%的兌換率),都不會配置到各業務的峯值,但配額系統有一個風險的不可控制的,就是進來的用戶數是不肯定的,但爲了保證獎品都能發放出去,獎品前1秒沒發完的額度,會累加到下1秒發放,這樣獎品發放峯值就有可能超過業務能力。

舉個例子,黃鑽的處理能力爲8w/s,第1秒有5w的配額,第2秒有5w的配額,假如從第1秒開始就有足夠多的用戶參與抽獎,用戶中獎後100%會去兌換黃鑽,那麼就有5w/s的請求到達黃鑽業務,業務可以正常處理。假如因爲一些意想不到的狀況(例如xx寶在第1秒也在搞活動吸引走了部分用戶),第1秒只有1w的用戶,第2秒忽然涌進9w/s的用戶,那麼第2秒將有9w/s的請求到達業務導致業務過載。

基於以上緣由,獎品發放限頻邏輯就成爲了保障後端業務正常運做的關鍵。那麼,如何設計這個限頻邏輯呢?首先想到的方法就是到存儲層Grocery獲取當前獎品計數器的值,拿回本地與前1秒的值作判斷,便可保證不超峯值,但這種作法會對存儲層形成巨大的衝擊,顯然的不可行的。那麼如何在保證性能的前提下,精確實現這個限頻邏輯呢?

咱們是這麼作的,活動前抽獎邏輯層的機器數是肯定的,咱們只要控制每臺機器獎品的最高發放頻率,就能總體控制該獎品的發放頻率,最壞的狀況多是某些邏輯層機器故障了,可能會形成該獎品在配額充足的狀況下不能按峯值發放,但咱們能夠經過修改配置從新設置每臺機器該獎品最高的發放頻率來解決這個問題。對於單機獎品發放頻率計數咱們使用了Memcached的increment原子加操做,以時間和獎品ID做爲Key,計數值做爲Value存儲在內存裏,便可實現精確的計數。

上圖左側是咱們一開始的實現,當時時間是以秒做爲計數週期的,也就是說,若是配額和用戶數都充足的話,獎品會在這1秒的最開始所有發送出去,這樣的話,問題又來了,通常來講業務方給的能力例如8w/s,是指在這1秒內相對平均的來了8w的請求,業務方恰好可以正確處理這8w的請求。可是若是請求是在1秒的最開始所有涌到業務方,受限於業務方不一樣的架構實現,有可能會觸發業務方的頻率限制或者是過載保護。所以,咱們將計數週期調小到百毫秒,這樣獎品就會在1秒內相對平均的發放,從而解決了上述問題。

3.6 抽獎算法設計

抽獎算法的設計並不複雜,大致流程以下:

須要注意的是,每一個獎品都有發放的時間段,只有在該時間段內,纔會把該獎品放入獎池裏。另外,從獎池裏按照比例挑選獎品,只要該獎品未成功派發,就繼續從獎池再次挑選,直到獎池空爲止,這樣就能保證獎品儘量的派發出去。

3.7 流水系統設計

流水系統主要用於活動後對獎品發放和設置領用進行統計和對帳。同時,該系統還對設置領用失敗的請求進行重作,確保獎品發放到用戶帳戶裏。流水系統架構以下:

因爲流水須要記錄用戶中獎的信息和設置領用的的狀況,數據量巨大,因此抽獎邏輯層本地採用順序寫文件的方式進行記錄。抽獎邏輯層會按期的把本地的流水文件同步到遠程流水系統進行彙總和備份,同時,流水系統會對領用失敗的流水進行重作,發送請求到抽獎邏輯層,抽獎邏輯層會調用支付系統的接口完成領用操做。

3.8 安全防禦設計

安全防禦對於抽獎系統來講,也是必不可少的,咱們有如下幾種措施來保障系統的安全:

(1)帳號鑑權

對於到達抽獎系統的請求,都要求帶上登陸態,利用基礎IM後臺完善的PTLogin接口,對用戶進行身份驗證。

(2)實時安全審計

對於每個抽獎請求,咱們都會記錄必要的信息(如客戶端IP、版本、序列號等),加上原始請求一併轉發到安所有門,由安所有門對全部的抽獎請求進行多維度的監控,對惡意請求進行打擊。

(3)uin請求頻率限制

對於每一個用戶(uin)的每種請求(抽獎、設置領用等),咱們都作了請求頻率限制,超過頻率限制的請求會直接返回錯誤。頻率限制必要的信息(時間、令牌)存儲在Memcached裏。

3.9 完善後的抽獎系統

  1. 異常處理策略

4.1 接入層SSO過載

接入層SSO是手Q終端使用後臺服務的大門,若是SSO出現問題,後果將不堪設想。抽獎請求在SSO預估的峯值爲800w/s,雖然評估預留了必定的餘量,但評估的數據仍是具備風險的,因此在接入層SSO咱們作了如下保護措施:

(1)錯峯機制

抽獎活動開始後,用戶會隨機被錯峯必定的時間,避免大量用戶在同一時間發起抽獎。錯峯的最大時間配置會隨活動配置一塊兒保存在CDN資源庫中,在活動開始前預下載到客戶端本地。獎品的配額數據也會根據錯峯後的用戶模型進行合理配置,保證公平性。

(2)實時可調的抽獎間隔

客戶端發起抽獎請求是有時間間隔的,默認間隔也是保存在活動配置裏。若是發現SSO即將過載,SSO能夠在抽獎回包裏帶上新的抽獎時間間隔,從而達到減小抽獎請求的目的。

4.2 抽獎邏輯層過載

抽獎邏輯層設計的峯值能力爲300w/s,假如即將超過該峯值,會使用以下措施進行保護:

(1)SSO調整請求透過率

SSO設計了一個抽獎請求透過率的配置,默認100%透過,正常狀況下,客戶端發起的抽獎請求到達SSO後,都會轉發到抽獎邏輯層。假如抽獎邏輯層即將過載,SSO調整該透過率,就會按照比例隨機對請求進行直接回包,回包內容指示用戶未中獎。

4.3 存儲層Grocery過載

Grocery若是即將過載,也能夠經過調整SSO透過率來減小請求。

4.4 財付通現金充值接口過載

財付通現金充值接口能力爲20w/s,配額系統配置該峯值也是配置成20w/s,若是發現20w/s財付通出現異常,能夠減少峯值,而後經過配額系統快速同步修改後的峯值到全部的邏輯層機器。

4.5 虛擬獎品對應業務過載

每一個虛擬獎品對應的業務都有本身的峯值能力,配額系統也是按照業務給定的峯值能力進行配置,若是業務反饋異常,能夠實時修改業務對應獎品的峯值或直接關閉該獎品的發放。

4.6 其餘異常處理

其餘模塊的異常通常都是能夠經過調整中獎率、關閉開關或關閉重試進行處理:

  1. 運營部署

接入層和抽獎邏輯層IDC級容災部署;

業務接入織雲運維自動化平臺,支持平滑擴容,進程實時監控並支持秒起;

存儲層數據雙份容災。

騰訊優測(utest.qq.com)
騰訊優測是專業的移動雲測試平臺,爲應用、遊戲,H5混合應用的研發團隊提供產品質量檢測與問題解決服務。
不只在線上平臺提供「全面兼容測試」、「雲手機」「缺陷分析」等多種自動化測試工具,同時在線下爲VIP客戶配備專家團隊,提供定製化綜合測試解決方案。真機實驗室配備上千款手機,覆蓋億級用戶,7*24小時在線運行,爲各種測試工具提供支持。
(據說關注公衆號立刻就有騰訊內部移動研發及測試彩蛋哦~)
感興趣能夠立刻加官羣勾搭客服妹妹哦~ 優測官方羣:214483489

相關文章
相關標籤/搜索