search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

微信紅包後台系統可用性設計實踐

作者:

方樂明

(現任微信支付應用產品系統負責人,主要從事微信紅包、微信轉賬、微信群收款等支付應用產品的系統設計、可用性提升、高性能解決方案設計等,曾負責 2015、2016 和 2017 年春節微信紅包系統的性能優化與穩定性提升,取得良好的效果。)


微信紅包業務量級的高速發展,對後台系統架構的可用性要求越來越高。在保障微信紅包業務體驗的前提下,紅包後台系統進行了一系列高可用方面的優化設計。本次演講介紹了微信紅包後台系統的高可用實踐經驗,主要包括後台的 set 化設計、非同步化設計、訂單異地存儲設計、存儲層容災設計與平行擴縮容等。聽眾可以了解到微信紅包後台架構的設計細節,共同探討高可用設計實踐上遇到的問題與解決方案。

微信紅包介紹

微信紅包從 2014 年開始發展到現在 2017 年,中間經歷了 3 年時間。在這三年的時間裡,整個系統可用性產生了較大的提升。2015 年年初的時候,每天晚上九點鐘是微信紅包的業務高峰期,系統經常性地出現性能問題。到了 2017 年的今天,即使在節假日高峰期,系統也不會出現問題。

如上圖所示,微信紅包的業務包含包、發、搶、拆、查詢發送紅包和收紅包數量,其中最關鍵的步驟是發紅包和搶紅包。

微信紅包是微信支付的商戶,微信紅包這個商戶出售的是錢。發紅包用戶在微信紅包平台使用微信支付購買一份錢,微信紅包將錢發放到相對應的微信群。群里的用戶搶紅包得到微信零錢。這個過程中,微信紅包和微信支付之間的關係是商家和第三方支付平台的關係。

微信紅包和微信支付之間的交互,與普通商家與微信支付的交互一樣,需要經過六個步驟。用戶發紅包時,進入微信紅包下一筆訂單,系統記錄發紅包用戶、發紅包金額、紅包數量和要發送到的用微信群。然後微信紅包系統請求微信支付伺服器進行下單,用戶使用微信支付進行支付。

支付成功后,微信支付後台系統通知微信紅包後台系統支付成功結果,微信紅包後台系統收到通知后推送微信紅包消息到微信群。微信群里用戶便可搶紅包。這就是微信紅包和微信支付的關係以及交互過程。

微信紅包系統架構

微信紅包的系統流程

上圖是微信紅包系統角度上的流程,業務主流程是包、發、搶、拆四個操作,每個操作包括幾個關鍵步驟。

包紅包,系統為每個紅包分配一個唯一 ID,即紅包發送訂單號,然後將發紅包用戶、紅包個數、紅包數額寫入存儲,最後去微信支付下單。

發紅包,用戶使用微信支付完成付款,微信紅包後台系統收到微信支付系統的支付成功通知。紅包系統將紅包發送訂單狀態更新為用戶已支付,並寫入用戶發紅包記錄(用戶發紅包記錄,就是微信錢包中,查看到的用戶每一年總共發出及收到的紅包記錄)。最後微信紅包後台系統發送微信紅包消息到微信群。

搶紅包,指微信群里的用戶收到微信紅包消息后,點開紅包消息。這個過程,微信紅包後台系統會檢查紅包是否已被搶完,是否已過期,是否已經搶過。

拆紅包是最複雜的業務是操作。包括查詢這個紅包發送訂單,判斷用戶是否可拆,然後計算本次可拆到的紅包金額。然後寫入一條搶紅包記錄。如果把拆紅包過程,類比為一個秒殺活動的過程,相當於扣庫存與寫入秒殺記錄的過程。更新庫存對應於更新紅包發送訂單,寫入秒殺記錄對應於寫入這個紅包的領取紅包記錄。另外,還要寫入用戶整體的紅包領取記錄。最後請求微信支付系統給拆到紅包用戶轉入零錢,成功后更新搶紅包的訂單狀態為已轉賬成功。

微信紅包的整體架構

上圖所示,是微信紅包的系統架構。包括微信統一接入層,下面是微信紅包系統 API,包括發、搶、拆、查紅包詳情、查紅包用戶列表。再下面是封裝微信紅包關鍵業務的邏輯服務;最下面一層是數據存儲層,微信紅包最主要的數據是訂單數據,包括發紅包訂單和拆紅包訂單兩部分。業務邏輯和存儲伺服器之間是數據接入層,它最重要的作用是封裝資料庫操作的領域邏輯,使得業務邏輯服務不需要感知對 MySQL 的連接管理、性能、容災等問題。

微信紅包數據的訪問熱度,隨著時間流逝會急劇降低,也就是數據的訪問時間段非常集中,一般紅包發出三天後,99% 的用戶不會再去點開這個紅包了。因此微信紅包系統採取按時間做冷熱數據分離,降低數據的存儲成本,同時提升了熱數據的訪問性能。

數據平台用於對紅包數據的分析計算,比如朋友圈裡的文章,統計從 2016 年 1 月 1 日到 2017 年 1 月一個用戶總共搶紅包的金額,在全國的排名情況,發紅包數最多的城市等。另外一個作用就是對賬,紅包的訂單和微信支付的訂單需要對賬,以保證最終資金的一致性;訂單的數據和訂單的 cache 需要做對賬,以保證數據的完整性;訂單數據和用戶的收發記錄需要對賬,以保證用戶列表完整性。

微信紅包系統可用性實踐

系統可用性影響因素

系統的可用性影響因素可分成兩類,一類計劃外,一類計劃內。計劃外包含很多因素,系統用到的所有東西都可能產生故障,都可能成功影響可用性的因素。從這個角度上來講,可以說故障是無法避免的,系統的運作一定會產生故障,尤其是伺服器有成千上萬個的時候。計劃內的影響因素,主要有與升級相關、運維相關的操作,以及日常的備份等。這一類影響因素,通過精細地設計方案,是可以避免對可用性造成影響的。

微信紅包系統可用性設計方向

基於上面兩個分析結論,可以總結出微信紅包後台系統的可用性的設計方向。就是在不能避免意外故障的情況下,儘可能降低出現意外故障時對可用性的影響。另一方面,絕大多數計劃內的日常維護可以通過方案的設計避免影響可用性,其中平行擴容特指關於存儲層的平行擴容。

下面從降低故障影響和微信紅包系統的平行擴容兩方面進行分析。

首先是降低意外故障的影響,重點講解訂單存儲層在訂單 DB 故障的情況下如何降低對紅包系統可用性的影響。

業務邏輯層 – 部署方案設計

首先是業務邏輯層的部署方案。業務邏輯層是無狀態的,微信紅包系統的業務邏輯層,部署在兩個城市,即兩地部署,每一個城市部署至少三個園區,即三個 IDC。並且每個服務需要保證三個 IDC 的部署均衡。另外,三個 IDC 總服務能力需要冗餘三分之一,當一個 IDC 出現故障時,服務能力仍然足夠。從而達到 IDC 故障不會對可用性產生影響。

業務邏輯層 – 非同步化設計

第二是非同步化設計。如上圖所示,微信紅包的某些步驟不實時完成也不會影響用戶對紅包業務可用性的體驗。比如拆紅包,正常的業務流程很長,但關鍵步驟只有訂單相關的幾步。至於轉零錢、寫紅包記錄等操作不需要實時。用戶搶到紅包時,一般不會實時去錢包查看微信零錢,而是在微信群中點開消息查看本次搶到金額和他人搶紅包金額。所以拆紅包時只需要從 cache 查詢用戶是否拆過紅包,然後寫入拆紅包的訂單記錄,更新發紅包訂單,其他的操作都可以非同步化。當然,不是每個業務都可以進行非同步化設計,需要進行業務分析,判斷是否存在非關鍵步驟之外的事情可以將其非同步化,並通過非同步對賬保證最終一致。

接下來是微信紅包訂單存儲設計。上圖是 2014 年微信紅包存儲層的模型。業務邏輯層請求數據層操作時,使用訂單號 hash 路由到訂單 SERVER。訂單 SERVER 與每一組 MYSQL 資料庫連接。

微信紅包的訂單號是在發紅包時系統生成唯一標識,使用序列號服務生成唯一 ID,後面拼接三位微信紅包的訂單分庫表的標識。所以,總共可以分一百個邏輯庫,每個邏輯庫含有十張表。一百個邏輯庫均勻地分佈到十組物理 DB,每組 DB 存十個邏輯庫。

這個架構的最大問題是,一組 DB 故障時,會影響其他 DB。2014-2015 年期間,微信紅包量漲得特別快,擴容速度跟不上業務增長速度。一組 DB 的性能出現瓶頸時,數據操作變慢, 拆紅包的事務操作在 MYSQL 排隊等待。由於所有十組 DB 機器與所有的訂單 SERVER 連接,導致所有的訂單 SERVER 都被拖住,從而影響紅包整體的可用性。這個架構的另一個問題是擴容不方便,後面會介紹。

為解決 DB 間的相互影響,需要將 DB 間相互隔離,訂單存儲層 SET 化。SET 化指訂單 DB 和訂單接入 SERVER 垂直 stick 一起。業務邏輯層訪問訂單時,根據訂單倒數第二、三位數字找到所屬訂單 SET,一個 SET 的請求不能路由到其他 SET。

找到對應的訂單接入伺服器之後,在伺服器內的多個進程中找到指定進程,讓同個紅包的所有拆請求串列化。當一組 DB 出現故障,只會影響該組 DB 對應的 SERVER。

這裡有一個問題,DB 故障拖住某些訂單 SERVER,會不會也拖住更上層業務邏輯服務?業務邏輯層為什麼不一起 SET 化?業務邏輯層承載了用戶維度相關的業務操作,不可以按照訂單的維度分業務邏輯,例如務邏輯層會請求用戶的頭像、昵稱等,如果繼續按照訂單分業務邏輯,會導致跨地域調用。

微信紅包系統採取的方案是,在訂單 SERVER 服務端增加快速拒絕服務的能力。SERVER 主動監控 DB 的性能情況,DB 性能下降、自身的 CPU 使用升高,或者發現其他的監控維度超標時,訂單 SERVER 直接向上層報錯,不再去訪問 DB,以此保證業務邏輯層的可用性。

一組 DB 故障不會影響整個系統的可用性。有影響的,只有十分之一,若擴成 100 組,影響便只有一百分之一。所以通過 SET 化得到的好處是,控制 DB 連接數、隔離故障影響和分流併發。

完成 SET 化之後,DB 故障仍對業務有十分之一影響,那麼這十分之一該怎麼解決?通過對系統進行研究分析之後,發現 DB 可以做到故障自愈。

如上圖所示,所設尾號 90-99 的 SET 故障時,如果業務邏輯服務後續不再生成屬於這個 SET 的訂單,那後續的業務就可以逐漸恢復。

也就是在發生故障時,業務邏輯層發布一個版本,屏蔽故障號段的單號生成,就可以恢復業務。進一步想,除了人為發版本,有沒有方法可以讓 DB 故障時自動恢復?在 DB 故障導致業務失敗時,業務邏輯層可獲取到故障 DB 的號段,在發紅包時,將這些故障的號段,換一個可用的號段就可恢復業務。訂單號除了最後三位,前面的部分已能保證該紅包唯一性,後面的數字只代表著分庫表信息,故障時只需要將最後三位換另外一個 SET 便可自動恢復。

完成這個設計后,即使 DB 出現故障,業務的可用性也不會有影響。這裡還有一點,新的發紅包請求可避免 DB 故障的影響,但那些故障之前已發出未被領取的紅包,紅包消息已發送到微信群,單號已確定,拆紅包時還是失敗。對這種情況,由於不會有增量,採用正常的主備切換解決即可。

平行擴縮容設計

上圖是微信紅包早期的擴縮容方式。這個擴容方式,對擴容的機器數有限制。前面講到,紅包系統按紅包單號後面兩個數字分多 SET,為了使擴容后數據保持均衡,擴容只能由 10 組 DB 擴容到 20 組、50 組或者 100 組。另外,這個擴容方式,過程也比較複雜。首先,數據要先從舊資料庫同步複製到新擴容的 DB,然後部署 DB 的接入 SERVER,最後在凌晨業務低峰時停服擴容。

這個擴容方式的複雜性,根本原因是數據需要從舊 SET 遷到新 SET。如果新產生數據與舊數據沒關係,那麼就可以省掉這部分的遷移動作,不需停服輸。分析發現,需要把舊數據遷出來的原因是訂單號段 00-99 已全部被用,每個物理資料庫包含了 10 個邏輯庫。如果將訂單號重新設計,預留三位空間,三位數字每一個代表獨立的物理 DB,原來 10 組 DB 分別為 000-009 號段。

這種設計,縮容時,比如要縮掉 000 這組,只需在業務邏輯服務上不生成訂單號為 000 的紅包訂單。擴容時,比如擴為 11 組,只需多生成 010 的訂單號,這個數據便自動寫入新 DB。當然,縮容需要一個前提條件,也就是冷熱分離,縮容后數據變為冷數據,可下線熱數據機器。以上就是紅包的平行擴縮容方案。

寫在最後

微信紅包系統的可用性實踐,主要包括了部署設計、SET 化設計、非同步化設計、DB 故障自愈能力建設、平行擴容設計。在完成這些設計后,微信紅包系統的可用性得到了很大提升,在 2017 年春節實現了 0 故障,在平常的運行中達到 99.99% 可用性。



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦