1. 程式人生 > >揭秘微信紅包:架構、搶紅包算法、高並發和降級方案(轉載)

揭秘微信紅包:架構、搶紅包算法、高並發和降級方案(轉載)

spa 系統優化 因此 事務 賬戶 body 同步 傳統 2-0

與傳統意義上的紅包相比,近兩年火起來的“紅包”,似乎才是如今春節的一大重頭戲。歷經上千年時代傳承與變遷,春節發紅包早已成為歷史沈澱的文化習俗,融入了民族的血脈。按照各家公布的數據,除夕全天微信用戶紅包總發送量達到80.8億個,紅包峰值收發量為40.9萬個/秒。春晚直播期間討論春晚的微博達到5191萬條,網友互動量達到1.15億,網友搶微博紅包的總次數超過8億次。

為此,InfoQ策劃了“春節紅包”系列文章,以期為讀者剖析各大平臺的紅包活動背後的技術細節。本文為微信篇。

微信紅包在經過15年春晚搖一搖之後,2015年上半年業務量一度呈指數級增長。尤其是微信紅包活躍用戶數的大量增長,使得2016除夕跨年紅包成為極大挑戰。為了應對16年春節可預知的紅包海量業務,紅包系統在架構上進行了一系列調整和優化。主要包括異地架構、cache系統優化、拆紅包並發策略優化、存儲優化一系列措施,為迎接2016春節紅包挑戰做好準備。 下面介紹最主要的一些思路。

架構

微信用戶在國內有深圳、上海兩個接入點,習慣性稱之為南、北(即深圳為南,上海為北)。用戶請求接入後,不同業務根據業務特性選擇部署方式。微信紅包在信息流上可以分為訂單緯度與用戶緯度。其中訂單是貫穿紅包發、搶、拆、詳情列表等業務的關鍵信息,屬於交易類信息;而用戶緯度指的是紅包用戶的收紅包列表、發紅包列表,屬於展示類信息。紅包系統在架構上,有以下幾個方面:

南北分布

1、訂單層南北獨立體系,數據不同步

用戶就近接入,請求發紅包時分配訂單南北,並在單號打上南北標識。搶紅包、拆紅包、查紅包詳情列表時,接入層根據紅包單號上的南北標識將流量分別引到南北系統閉環。根據發紅包用戶和搶紅包用戶的所屬地不同,有以下四種情況:

1) 深圳用戶發紅包,深圳用戶搶

訂單落在深圳,深圳用戶搶紅包時不需要跨城,在深圳完成閉環。

2) 深圳用戶發紅包,上海用戶搶

訂單落在深圳,上海用戶搶紅包,在上海接入後通過專線跨城到深圳,最後在深圳閉環完成搶紅包。

3) 上海用戶發紅包,上海用戶搶

訂單落在上海,上海用戶搶紅包時不需要跨城,在上海完成閉環。

4) 上海用戶發紅包,深圳用戶搶

訂單落在上海,深圳用戶搶紅包,從深圳接入後通過專線跨城到上海,最後在上海閉環完成搶紅包。

系統這樣設計,好處是南北系統分攤流量,降低系統風險。

技術分享圖片

2、用戶數據寫多讀少,全量存深圳,異步隊列寫入,查時一邊跨城

用戶數據的查詢入口,在微信錢包中,隱藏的很深。這決定了用戶數據的訪問量不會太大,而且也被視為可旁路的非關鍵信息,實時性要求不高。因此,只需要在發紅包、拆紅包時,從訂單緯度拆分出用戶數據寫入請求,由MQ異步寫入深圳。後臺將訂單與用戶進行定時對賬保證數據完整性即可。

3、支持南北流量靈活調控

紅包系統南北分布後,訂單落地到深圳還是上海,是可以靈活分配的,只需要在接入層上做邏輯。例如,可以在接入層中,實現讓所有紅包請求,都落地到深圳(無論用戶從上海接入,還是深圳接入),這樣上海的紅包業務系統將不會有請求量。提升了紅包系統的容災能力。同時,實現了接入層上的後臺管理系統,實現了秒級容量調控能力。可根據南北請求量的實時監控,做出對應的調配。

4、DB故障時流量轉移能力
基於南北流量的調控能力,當發現DB故障時,可將紅包業務流量調到另外一邊,實現DB故障的容災。

預訂單

支付前訂單落cache,同時利用cache的原子incr操作順序生成紅包訂單號。優點是cache的輕量操作,以及減少DB廢單。在用戶請求發紅包與真正支付之間,存在一定的轉化率,部分用戶請求發紅包後,並不會真正去付款。

拆紅包入賬異步化

信息流與資金流分離。拆紅包時,DB中記下拆紅包憑證,然後異步隊列請求入賬。入賬失敗通過補償隊列補償,最終通過紅包憑證與用戶賬戶入賬流水對賬,保證最終一致性。

技術分享圖片

這個架構設計,理論基礎是快慢分離。紅包的入賬是一個分布事務,屬於慢接口。而拆紅包憑證落地則速度快。實際應用場景中,用戶搶完紅包,只關心詳情列表中誰是“最佳手氣”,很少關心搶到的零是否已經到賬。因為只需要展示用戶的拆紅包憑證即可。

發拆落地,其他操作雙層cache

1、Cache住所有查詢,兩層cache

除了使用ckv做全量緩存,還在數據訪問層dao中增加本機內存cache做二級緩存,cache住所有讀請求。

查詢失敗或者查詢不存在時,降級內存cache;內存cache查詢失敗或記錄不存在時降級DB。

DB本身不做讀寫分離。

2、DB寫同步cache,容忍少量不一致
DB寫操作完成後,dao中同步內存cache,業務服務層同步ckv,失敗由異步隊列補償,定時的ckv與DB備機對賬,保證最終數據一致。

高並發

微信紅包的並發挑戰,主要在於微信大群,多人同時搶同一個紅包。這種情況,存在競爭MySQL行鎖。為了控制這種並發,團隊做了以下一些事情:

1、請求按紅包訂單路由,邏輯塊垂直sticky,事務隔離

按紅包訂單劃分邏輯單元,單元內業務閉環。服務rpc調用時,使用紅包訂單號的hash值為key尋找下一跳地址。對同一個紅包的所有拆請求、查詢請求,都路由到同一臺邏輯機器、同一臺DB中處理。

技術分享圖片

2、Dao搭建本機Memcache內存cache,控制同一紅包並發個數

在DB的接入機dao中,搭建本機內存cache。以紅包訂單號為key,對同一個紅包的拆請求做原子計數,控制同一時刻能進DB中拆紅包的並發請求數。

這個策略的實施,依賴於請求路由按紅包訂單hash值走,確保同一紅包的所有請求路由到同一邏輯層機器。

3、多層級並發量控制
1) 發紅包控制

發紅包是業務流程的入口,控制了這裏的並發量,代表著控制了紅包業務整體的並發量。在發紅包的業務鏈路裏,做了多層的流量控制,確保產生的有效紅包量級在可控範圍。

2) 搶紅包控制

微信紅包領取時分為兩個步驟,搶和拆。搶紅包這個動作本身就有控制拆並發的作用。因為搶紅包時,只需要查cache中的數據,不需要請求DB。對於紅包已經領完、用戶已經領過、紅包已經過期等流量可以直接攔截。而對於有資格進入拆紅包的請求量,也做流量控制。通過這些處理,最後可進入拆環節的流量大大減少,並且都是有效請求。

3) 拆時內存cache控制

針對同一個紅包並發拆的控制,上文已經介紹。

4、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分,計算本輪的上水位。

為了使紅包金額不要太懸殊,使用紅包均值調整上水位。如果上水位金額大於兩倍紅包均值,那麽使用兩倍紅包均值作為上水位。換句話說,每一輪搶到的紅包金額,最高為兩倍剩下紅包的均值。

最後,獲取隨機數並用上水位取余,如果結果比下水位還小,則直接使用下水位,否則使用隨機金額為本輪拆到金額。

柔性降級方案

系統到處存在發生異常的可能,需要對所有的環節做好應對的預案。下面列舉微信紅包對系統異常的主要降級考慮。

1、 下單cache故障降級DB

下單cache有兩個作用,生成紅包訂單與訂單緩存。緩存故障情況下,降級為直接落地DB,並使用id生成器獨立生成訂單號。

2、 搶時cache故障降級DB

搶紅包時,查詢cache,攔截紅包已經搶完、用戶已經搶過、紅包已經過期等無效請求。當cache故障時,降級DB查詢,同時打開DB限流保護開關,防止DB壓力過大導致服務不可用。

另外,cache故障降級DB時,DB不存儲用戶頭像、用戶昵稱等(上文提到的優化),此時一並降級為實時接口查詢。查詢失敗,繼續降級為展示默認頭像與昵稱。

3、 拆時資金入賬多級柔性

拆紅包時,DB記錄拆紅包單據,然後執行資金轉賬。單據需要實時落地,而資金轉賬,這裏做了多個層級的柔性降級方案:

大額紅包實時轉賬,小額紅包入隊列異步轉賬 所有紅包進隊列異步轉賬 實時流程不執行轉賬,事後憑單據批量入賬。

總之,單據落地後,真實入賬可實時、可異步,最終保證一致即可。

4、 用戶列表降級

用戶列表數據在微信紅包系統中,屬於非關鍵路徑信息,屬於可被降級部分。

首先,寫入時通過MQ異步寫,通過定時對賬保證一致性。

其次,cache中只緩存兩屏,用戶查詢超過兩屏則查用戶列表DB。在系統壓力大的情況下,可以限制用戶只查兩屏。

調整後的系統經過了16年春節的實踐檢驗,平穩地度過了除夕業務高峰,保障了紅包用戶的體驗。

作者介紹

方樂明,2011年畢業於華南理工大學通信與信息系統專業,畢業後就職於財付通科技有限公司。微信支付團隊組建後,主要負責微信紅包、微信轉賬、AA收款等支付應用產品的後臺架構。

揭秘微信紅包:架構、搶紅包算法、高並發和降級方案(轉載)