與傳統意義上的紅包相比,近兩年火起來的「紅包」,彷佛纔是現在春節的一大重頭戲。歷經上千年時代傳承與變遷,春節發紅包早已成爲歷史沉澱的文化習俗,融入了民族的血脈。按照各家公佈的數據,除夕全天微信用戶紅包總髮送量達到80.8億個,紅包峯值收發量爲40.9萬個/秒。春晚直播期間討論春晚的微博達到5191萬條,網友互動量達到1.15億,網友搶微博紅包的總次數超過8億次。算法
爲此,InfoQ策劃了「春節紅包」系列文章,以期爲讀者剖析各大平臺的紅包活動背後的技術細節。本文爲微信篇。數據庫
微信紅包在通過15年春晚搖一搖以後,2015年上半年業務量一度呈指數級增加。尤爲是微信紅包活躍用戶數的大量增加,使得2016除夕跨年紅包成爲極大挑戰。爲了應對16年春節可預知的紅包海量業務,紅包系統在架構上進行了一系列調整和優化。主要包括異地架構、cache系統優化、拆紅包併發策略優化、存儲優化一系列措施,爲迎接2016春節紅包挑戰作好準備。 下面介紹最主要的一些思路。緩存
架構
微信用戶在國內有深圳、上海兩個接入點,習慣性稱之爲南、北(即深圳爲南,上海爲北)。用戶請求接入後,不一樣業務根據業務特性選擇部署方式。微信紅包在信息流上能夠分爲訂單緯度與用戶緯度。其中訂單是貫穿紅包發、搶、拆、詳情列表等業務的關鍵信息,屬於交易類信息;而用戶緯度指的是紅包用戶的收紅包列表、發紅包列表,屬於展現類信息。紅包系統在架構上,有如下幾個方面:服務器
南北分佈微信
一、訂單層南北獨立體系,數據不一樣步架構
用戶就近接入,請求發紅包時分配訂單南北,並在單號打上南北標識。搶紅包、拆紅包、查紅包詳情列表時,接入層根據紅包單號上的南北標識將流量分別引到南北系統閉環。根據發紅包用戶和搶紅包用戶的所屬地不一樣,有如下四種狀況:併發
1) 深圳用戶發紅包,深圳用戶搶異步
訂單落在深圳,深圳用戶搶紅包時不須要跨城,在深圳完成閉環。高併發
2) 深圳用戶發紅包,上海用戶搶post
訂單落在深圳,上海用戶搶紅包,在上海接入後經過專線跨城到深圳,最後在深圳閉環完成搶紅包。
3) 上海用戶發紅包,上海用戶搶
訂單落在上海,上海用戶搶紅包時不須要跨城,在上海完成閉環。
4) 上海用戶發紅包,深圳用戶搶
訂單落在上海,深圳用戶搶紅包,從深圳接入後經過專線跨城到上海,最後在上海閉環完成搶紅包。
系統這樣設計,好處是南北系統分攤流量,下降系統風險。
二、用戶數據寫多讀少,全量存深圳,異步隊列寫入,查時一邊跨城
用戶數據的查詢入口,在微信錢包中,隱藏的很深。這決定了用戶數據的訪問量不會太大,並且也被視爲可旁路的非關鍵信息,實時性要求不高。所以,只須要在發紅包、拆紅包時,從訂單緯度拆分出用戶數據寫入請求,由MQ異步寫入深圳。後臺將訂單與用戶進行定時對帳保證數據完整性便可。
三、支持南北流量靈活調控
紅包系統南北分佈後,訂單落地到深圳仍是上海,是能夠靈活分配的,只須要在接入層上作邏輯。例如,能夠在接入層中,實現讓全部紅包請求,都落地到深圳(不管用戶從上海接入,仍是深圳接入),這樣上海的紅包業務系統將不會有請求量。提高了紅包系統的容災能力。同時,實現了接入層上的後臺管理系統,實現了秒級容量調控能力。可根據南北請求量的實時監控,作出對應的調配。
四、DB故障時流量轉移能力
基於南北流量的調控能力,當發現DB故障時,可將紅包業務流量調到另一邊,實現DB故障的容災。
預訂單
支付前訂單落cache,同時利用cache的原子incr操做順序生成紅包訂單號。優勢是cache的輕量操做,以及減小DB廢單。在用戶請求發紅包與真正支付之間,存在必定的轉化率,部分用戶請求發紅包後,並不會真正去付款。
拆紅包入帳異步化
信息流與資金流分離。拆紅包時,DB中記下拆紅包憑證,而後異步隊列請求入帳。入帳失敗經過補償隊列補償,最終經過紅包憑證與用戶帳戶入帳流水對帳,保證最終一致性。
這個架構設計,理論基礎是快慢分離。紅包的入帳是一個分佈事務,屬於慢接口。而拆紅包憑證落地則速度快。實際應用場景中,用戶搶完紅包,只關心詳情列表中誰是「最佳手氣」,不多關心搶到的零是否已經到帳。由於只須要展現用戶的拆紅包憑證便可。
發拆落地,其餘操做雙層cache
一、Cache住全部查詢,兩層cache
除了使用ckv作全量緩存,還在數據訪問層dao中增長本機內存cache作二級緩存,cache住全部讀請求。
查詢失敗或者查詢不存在時,降級內存cache;內存cache查詢失敗或記錄不存在時降級DB。
DB自己不作讀寫分離。
二、DB寫同步cache,容忍少許不一致
DB寫操做完成後,dao中同步內存cache,業務服務層同步ckv,失敗由異步隊列補償,定時的ckv與DB備機對帳,保證最終數據一致。
高併發
微信紅包的併發挑戰,主要在於微信大羣,多人同時搶同一個紅包。這種狀況,存在競爭MySQL行鎖。爲了控制這種併發,團隊作了如下一些事情:
一、請求按紅包訂單路由,邏輯塊垂直sticky,事務隔離
按紅包訂單劃分邏輯單元,單元內業務閉環。服務rpc調用時,使用紅包訂單號的hash值爲key尋找下一跳地址。對同一個紅包的全部拆請求、查詢請求,都路由到同一臺邏輯機器、同一臺DB中處理。
二、Dao搭建本機Memcache內存cache,控制同一紅包併發個數
在DB的接入機dao中,搭建本機內存cache。以紅包訂單號爲key,對同一個紅包的拆請求作原子計數,控制同一時刻能進DB中拆紅包的併發請求數。
這個策略的實施,依賴於請求路由按紅包訂單hash值走,確保同一紅包的全部請求路由到同一邏輯層機器。
三、多層級併發量控制
1) 發紅包控制
發紅包是業務流程的入口,控制了這裏的併發量,表明着控制了紅包業務總體的併發量。在發紅包的業務鏈路裏,作了多層的流量控制,確保產生的有效紅包量級在可控範圍。
2) 搶紅包控制
微信紅包領取時分爲兩個步驟,搶和拆。搶紅包這個動做自己就有控制拆併發的做用。由於搶紅包時,只須要查cache中的數據,不須要請求DB。對於紅包已經領完、用戶已經領過、紅包已通過期等流量能夠直接攔截。而對於有資格進入拆紅包的請求量,也作流量控制。經過這些處理,最後可進入拆環節的流量大大減小,而且都是有效請求。
3) 拆時內存cache控制
針對同一個紅包併發拆的控制,上文已經介紹。
四、DB簡化和拆分
DB的併發能力,有不少影響因素。紅包系統結合紅包使用情境,進行了一些優化。比較有借鑑意義的,主要有如下兩點:
1) 訂單表只存關鍵字段,其餘字段只在cache中存儲,可柔性。
紅包詳情的展現中,除了訂單關鍵信息(用戶、單號、金額、時間、狀態)外,還有用戶頭像、暱稱、祝福語等字段。這些字段對交易來講不是關鍵信息,卻佔據大量的存儲空間。
將這些非關鍵信息拆出來,只存在cache,用戶查詢展現,而訂單中不落地。這樣能夠維持訂單的輕量高效,同時cache不命中時,又可從實時接口中查詢補償,達到優化訂單DB容量的效果。
2) DB雙重緯度分庫表,冷熱分離
使用訂單hash、訂單日期,兩個緯度分庫表,也即db_xxx.t_x_dd這樣的格式。其中,x表示訂單hash值,dd表示01-31循環日。訂單hash緯度,是爲了將訂單打散到不一樣的DB服務器中,均衡壓力。訂單日期循環日緯度,是爲了不單表數據無限擴張,使天天都是一張空表。
另外,紅包的訂單訪問熱度,是很是典型的冷熱型。熱數據集中在一兩天內,且隨時間急劇消減。線上熱數據庫只須要存幾天的數據,其餘數據能夠定時移到成本低的冷數據庫中。循環日表也使得歷史數據的遷移變得方便。
紅包算法
首先,若是紅包只有一個,本輪直接使用所有金額,確保紅包發完。
而後,計算出本輪紅包最少要領取多少,才能保證紅包領完,即本輪下水位;輪最多領取多少,才能保證每一個人都領到,即本輪上水位。主要方式以下:
計算本輪紅包金額下水位:假設本輪領到最小值1分,那接下來每次都領到200元紅包能領完,那下水位爲1分;若是不能領完,那按接下來每次都領200元,剩下的本輪應所有領走,是本輪的下水位。
計算本輪紅包上水位:假設本輪領200元,剩下的錢還足夠接下來每輪領1分錢,那本輪上水位爲200元;若是已經不夠領,那按接下來每輪領1分,計算本輪的上水位。
爲了使紅包金額不要太懸殊,使用紅包均值調整上水位。若是上水位金額大於兩倍紅包均值,那麼使用兩倍紅包均值做爲上水位。換句話說,每一輪搶到的紅包金額,最高爲兩倍剩下紅包的均值。
最後,獲取隨機數並用上水位取餘,若是結果比下水位還小,則直接使用下水位,不然使用隨機金額爲本輪拆到金額。
柔性降級方案
系統處處存在發生異常的可能,須要對全部的環節作好應對的預案。下面列舉微信紅包對系統異常的主要降級考慮。
一、 下單cache故障降級DB
下單cache有兩個做用,生成紅包訂單與訂單緩存。緩存故障狀況下,降級爲直接落地DB,並使用id生成器獨立生成訂單號。
二、 搶時cache故障降級DB
搶紅包時,查詢cache,攔截紅包已經搶完、用戶已經搶過、紅包已通過期等無效請求。當cache故障時,降級DB查詢,同時打開DB限流保護開關,防止DB壓力過大致使服務不可用。
另外,cache故障降級DB時,DB不存儲用戶頭像、用戶暱稱等(上文提到的優化),此時一併降級爲實時接口查詢。查詢失敗,繼續降級爲展現默認頭像與暱稱。
三、 拆時資金入帳多級柔性
拆紅包時,DB記錄拆紅包單據,而後執行資金轉帳。單據須要實時落地,而資金轉帳,這裏作了多個層級的柔性降級方案:
大額紅包實時轉帳,小額紅包入隊列異步轉帳 全部紅包進隊列異步轉帳 實時流程不執行轉帳,過後憑單據批量入帳。
總之,單據落地後,真實入帳可實時、可異步,最終保證一致便可。
四、 用戶列表降級
用戶列表數據在微信紅包系統中,屬於非關鍵路徑信息,屬於可被降級部分。
首先,寫入時經過MQ異步寫,經過定時對帳保證一致性。
其次,cache中只緩存兩屏,用戶查詢超過兩屏則查用戶列表DB。在系統壓力大的狀況下,能夠限制用戶只查兩屏。
調整後的系統通過了16年春節的實踐檢驗,平穩地度過了除夕業務高峯,保障了紅包用戶的體驗。
做者介紹
方樂明,2011年畢業於華南理工大學通訊與信息系統專業,畢業後就任於財付通科技有限公司。微信支付團隊組建後,主要負責微信紅包、微信轉帳、AA收款等支付應用產品的後臺架構。