21CTO社區導讀:
紅包是我國國慶,婚宴等重大典禮上,一個最有喜氣的貨幣附送典禮,它的意義不在于有多少金額,而在于它包含的蘊涵與問候。
再到后來,紅包被用在互聯網電子商務上,拿來做為訂購商品做為現金抵用,實際上指的是代金券。
接出來微信創造了兩個現象級的產品:一是全民打客機,一是全民搶紅包。后者已經謝幕,搶紅包卻歷久彌新。
紅包不僅僅是娛樂和游戲。滿足人的貪、嗔、癡等欲望的同時,它也具備了打通社交、商業、公共服務任督二脈的威力。
騰訊有一個廣為人知的傳統:舊歷春節后下班第三天,馬化騰和公司高層要親自給職工派發紅包,職工把這個傳統稱作“刷總辦紅包”。
這個時侯,有人提出玩點不一樣的。延續現實世界的傳統,把公司內部發紅包的傳統,弄成一個應用,在微信好友之間傳播。于是,騰訊的產品總監提出了“搶紅包”的方案。當時距離節日只有不到兩個禮拜的時間。
微信將紅包的概念和使用場景進一步擴大,到目前為止,微信紅包有如下幾個類型:
也就是微信群里人們領取和爭搶的紅包;
兩個人在聊天界面時雙向發送的紅包;
兩個人之間免加好友,可直接給對方發紅包
人們常說的紅包,亦即是群紅包。現今群里搶紅包的行為也顯得很稀松平時,一言不合就開始來一發。
微信紅包從2014年被張小龍團隊發明,到2017年的現今,已兩年半多的時間。
2015年新年期間,微信紅包遇見收發困難等性能問題,甚至顯示發送成功,雖然是用了一些產品上的方法,存在較大的性能問題。
其構架至此開始快速進化。其中包括:
后端流量控制
主要思路是減短關鍵業務流程,分離可以通過異步、緩存等方法解決的問題,減少系統壓力,推動響應速率,在儲存層上面建上一座水壩。
CGI無狀態
接入層無狀態,邏輯層也無狀態,可以便捷地水平擴充。但依賴MySQL事務保證交易完整,保證紅包系統的精簡,降低困局的存在。
資源靜態化
盡量把動態內容轉為靜態資源。靜態資源和CGI分離,靜態資源通過CDN就近接入,降低用戶和CGI的交互,降低訪問延時和數據懇求。
業務流程異步化
關鍵流程精簡,非關鍵流程和后續業務邏輯步入異步隊列進行處理,降低了用戶的等待時間,也極大減少了峰值雪崩的機率。繁雜的非關鍵鏈路也不會影響到主流程。
過載保護
后端保護前端,能在后端處理,就不傳遞到前端。后端須要按前端能力做削峰限流;顧客端、接入層、邏輯層逐層控制流量;后端更容易容錯處理,竭力保護儲存層。微信的過載保護在顧客端已提早預埋件了策略,在聯接失敗或超時情況下會有相應提示,降低用戶重復懇求次數。接入層針對頻繁發出懇求的顧客端限制響應速率,并對系統負載界定出若干等級,達到不同閥值時引導顧客端使用不同限速速度;在異常情況出現時,異步限流降速減少服務器端壓力避免過載。
多級讀緩存
發一個群紅包,搶紅包的懇求量遠小于發紅包,假如早已領過完全可以拒絕。邏輯層降低緩存,類似可以緩存的懇求都緩存上去,進一步降低儲存層流量。
訂單寫緩存
微信紅包與訂單處理
訂單在完成支付前可以先落在緩存中,完成支付后再持久化。
如上圖所示,微信紅包的業務包含包、發、搶、拆、查詢發送紅包和收紅包數目,其中最關鍵的步驟是發紅包和搶紅包。
微信紅包是微信支付的商戶,微信紅包這個商戶轉讓的是錢。發紅包用戶在微信紅包平臺使用微信支付訂購一份錢,微信紅包將錢領取到相對應的微信群。群里的用戶搶紅包得到微信零錢。這個過程中,微信紅包和微信支付之間的關系是店家和第三方支付平臺的關系。
微信紅包和微信支付之間的交互,與普通店家與微信支付的交互一樣,須要經過六個步驟。用戶發紅包時,步入微信紅包下一筆訂單,系統記錄發紅包用戶、發紅包金額、紅包數目和要發送到的用微信群。之后微信紅包系統懇求微信支付服務器進行下單,用戶使用微信支付進行支付。
支付成功后,微信支付后臺系統通知微信紅包后臺系統支付成功結果,微信紅包后臺系統收到通知后推送微信紅包消息到微信群。微信群里用戶便可搶紅包。這就是微信紅包和微信支付的關系以及交互過程。
微信紅包系統構架
微信紅包的系統流程
上圖是微信紅包系統角度上的流程,業務主流程是包、發、搶、拆四個操作,每位操作包括幾個關鍵步驟。
包紅包,系統為每位紅包分配一個惟一ID,即紅包發送訂單號,之后將發紅包用戶、紅包個數、紅包數額寫入儲存,最后去微信支付下單。
發紅包,用戶使用微信支付完成付款,微信紅包后臺系統收到微信支付系統的支付成功通知。紅包系統將紅包發送訂單狀態更新為用戶已支付,并寫入用戶發紅包記錄(用戶發紅包記錄,就是微信皮夾中,查看到的用戶每一年總共發出及收到的紅包記錄)。最后微信紅包后臺系統發送微信紅包消息到微信群。
搶紅包,指微信群里的用戶收到微信紅包消息后,點開紅包消息。這個過程,微信紅包后臺系統會檢測紅包是否已被偷完,是否已過期,是否早已搶過。
拆紅包是最復雜的業務是操作。包括查詢這個紅包發送訂單,判定用戶是否可拆,之后估算本次可拆到的紅包金額。之后寫入一條搶紅包記錄。假如把拆紅包過程,類比為一個秒殺活動的過程,相當于扣庫存與寫入秒殺記錄的過程。更新庫存對應于更新紅包發送訂單,寫入秒殺記錄對應于寫入這個紅包的發放紅包記錄。另外,還要寫入用戶整體的紅包發放記錄。最后懇求微信支付系統給拆到紅包用戶轉到零錢,成功后更新搶紅包的訂單狀態為已匯款成功。
微信紅包的整體構架
上圖所示,是微信紅包系統之總體構架。
包括微信統一接入層,下邊是微信紅包系統API,包括發、搶、拆、查紅包詳情、查紅包用戶列表。再下邊是封裝微信紅包關鍵業務的邏輯服務;最下邊一層是數據儲存層,微信紅包最主要的數據是訂單數據,包括發紅包訂單和拆紅包訂單兩部份。業務邏輯和儲存服務器之間是數據接入層,它最重要的作用是封裝數據庫操作的領域邏輯,致使業務邏輯服務不須要感知對MySQL的聯接管理、性能、容災等問題。
微信紅包數據的訪問熱度,隨著時間流逝會隨之減少,也就是數據的訪問時間段十分集中,通常紅包發出兩天后,99%的用戶不會再去點開這個紅包了。因而微信紅包系統采取按時間做冷熱數據分離,增加數據的儲存成本,同時提高了熱數據的訪問性能。
數據平臺用于對紅包數據的剖析估算,例如同學圈里的文章,統計從2016年1月1日到2017年1月一個用戶總共搶紅包的金額,在全省的排行情況,發紅包數最多的城市等。另外一個作用就是對帳,紅包的訂單和微信支付的訂單須要對帳,以保證最終資金的一致性;訂單的數據和訂單的cache須要做對帳,以保證數據的完整性;訂單數據和用戶的收發記錄須要對帳,以保證用戶列表完整性。
微信紅包系統可用性實踐
系統可用性影響誘因
系統的可用性影響誘因可分成兩類,一類計劃外,一類計劃內。計劃外包含好多誘因,系統用到的所有東西都可能形成故障,都可能成功影響可用性的誘因。從這個角度上來講,可以說故障是難以避開的,系統的運作一定會形成故障,尤其是服務器有成千上萬個的時侯。計劃內的影響誘因,主要有與升級相關、運維相關的操作,以及日常的備份等。這一類影響誘因,通過精細地設計方案,是可以防止對可用性導致影響的。
微信紅包系統可用性設計方向
基于前面兩個剖析推論,可以總結出微信紅包后臺系統的可用性的設計方向。就是在不能防止意外故障的情況下,盡可能減少出現意外故障時對可用性的影響。另一方面,絕大多數計劃內的日常維護可以通過方案的設計避開影響可用性微信訂單系統,其中平行擴容特指關于儲存層的平行擴容。
下邊從減少故障影響和微信紅包系統的平行擴容兩方面進行剖析。
首先是減少意外故障的影響,重點講解訂單儲存層在訂單DB故障的情況下怎樣增加對紅包系統可用性的影響。
業務邏輯層-布署方案設計
首先是業務邏輯層的布署方案。業務邏輯層是無狀態的,微信紅包系統的業務邏輯層,布署在兩個城市,即兩地布署,每一個城市布署起碼三個園區,即三個IDC。而且每位服務須要保證三個IDC的布署均衡。另外,三個IDC總服務能力須要冗余三分之一,當一個IDC出現故障時,服務能力依然足夠。進而達到IDC故障不會對可用性形成影響。
業務邏輯層-異步化設計
第二是異步化設計。如上圖所示,微信紅包的個別步驟不實時完成也不會影響用戶對紅包業務可用性的體驗。例如拆紅包,正常的業務流程很長,但關鍵步驟只有訂單相關的幾步。至于轉零錢、寫紅包記錄等操作不須要實時。用戶搶到紅包時,通常不會實時去皮夾查看微信零錢,而是在微信群中點開消息查看本次搶到金額和別人搶紅包金額。
所以拆紅包時只須要從cache查詢用戶是否拆過紅包,之后寫入拆紅包的訂單記錄,更新發紅包訂單,其他的操作都可以異步化。其實,不是每位業務都可以進行異步化設計,須要進行業務剖析,判定是否存在非關鍵步驟之外的事情可以將其異步化,并通過異步對帳保證最終一致。
接出來是微信紅包訂單儲存設計。上圖是2014年微信紅包儲存層的模型。業務邏輯層懇求數據層操作時,使用訂單號hash路由到訂單服務器。訂單服務器與每一組MySQL數據庫聯接。
微信紅包的訂單號是在發紅包時系統生成惟一標示,使用序列號服務生成惟一ID,前面拼接三位微信紅包的訂單分庫表的標示。所以,總共可以分一百個邏輯庫,每位邏輯庫富含十張表。一百個邏輯庫均勻地分布到十組數學DB,每組DB存十個邏輯庫。
這個構架的最大問題是,一組DB故障時,會影響其他DB。
在2014-2015年期間,微信紅包量漲得非常快,擴容速率跟不上業務下降速率。一組DB的性能出現困局時,數據操作變慢,拆紅包的事務操作在MYSQL排隊等待。因為所有十組DB機器與所有的訂單服務器聯接,造成所有的訂單都被拖住,因而影響紅包整體的可用性。這個構架的另一個問題是擴容不便捷,旁邊會介紹。
為解決DB間的互相影響,須要將DB間互相隔離,訂單儲存層SET化。SET化指訂單DB和訂單接入垂直Stick一起。業務邏輯層訪問訂單時,依照訂單倒數第二、三位數字找到所屬訂單SET,一個SET的懇求不能路由到其他SET。
找到對應的訂單接入服務器以后,在服務器內的多個進程中找到指定進程,讓同個紅包的所有拆懇求串行化。當一組DB出現故障,只會影響該組DB對應的。
這兒有一個問題,DB故障拖住個別訂單,會不會也拖住更下層業務邏輯服務?業務邏輯層為何不一起SET化?業務邏輯層承載了用戶維度相關的業務操作,不可以根據訂單的維度分業務邏輯,比如務邏輯層會懇求用戶的頭像、昵稱等,假如繼續依照訂單分業務邏輯,會造成跨地域調用。
微信紅包系統采取的方案是,在訂單服務端降低快速拒絕服務的能力。服務器主動監控DB的性能情況,DB性能增長、自身的CPU使用下降,或則發覺其他的監控維度超標時,訂單直接向下層報錯,不再去訪問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的接入,最后在傍晚業務低峰時停服擴容。
這個擴容形式的復雜性,根本緣由是數據須要從舊SET遷到新SET。假如新形成數據與舊數據沒關系,這么就可以省掉這部份的遷移動作,不需停服輸。剖析發覺,須要把舊數據遷下來的緣由是訂單號段00-99已全部被用,每位化學數據庫包含了10個邏輯庫。假如將訂單號重新設計,預留三位空間,三位數字每一個代表獨立的化學DB,原先10組DB分別為000-009號段。
這些設計,縮容時,例如要縮掉000這組,只需在業務邏輯服務上不生成訂單號為000的紅包訂單。擴容時,例如擴為11組,只需多生成010的訂單號,這個數據便手動寫入新DB。其實,縮容須要一個前提條件,也就是冷熱分離,縮容后數據變為冷數據,可下線熱數據機器。以上就是紅包的平行擴縮容方案。
儲存層的高可用設計
讀寫分離
寫懇求須要在DB主機上,實時讀也須要走主機。有大量對延時不這么敏感,又影響性能的查詢,完全可以放在DB從機。讀寫分離策略是MySQL分布式的入門,簡約地提升了系統容量。
水平切分
數據的水平切分,實質就是分庫分表;選定一張數據表根據主要經度把數據拆分開。實現儲存層的平行擴充。有效減少了單臺數據庫機器的負載,也降低了服務不可用的可能性。單臺數據庫宕機只會造成部份數據不能訪問。主要須要考慮路由規則的選取,便捷擴縮容以及數據的均衡分布。
垂直切分
數據表不僅水平切分,行內數據可以按屬性進一步分開。核心表只保留最關鍵的數組,保證數據文件短小緊湊。以紅包為例,愛稱和問候語這類較長的信息,不屬于核心數據,完全可以切分到別的機器上,進一步提高核心數據庫的容量。不同數據適宜的儲存類型也不一樣,這類重復率高的長字符串更適宜NoSQL儲存,對儲存空間和性能都是節省極大。
空間換時間
按不同經度組織表,例如按訂單屬性和用戶屬性進行組織;適應不同的懇求場景,防止復雜的查詢。不同經度的表可以通過對帳對齊,非核心表可以適當冗余,降低多次懇求。
鎖的優化
多人爭搶紅包通過數據庫事物來保證,必然存在競爭MySQL行鎖。核心事物必須盡量精簡,防止死鎖。同一個訂單的所有懇求,盡量在邏輯層進程預排隊后通過一個聯接發送懇求到數據庫。
冷熱分離
核心數據庫儲存高頻數據,其他數據可以定時移到成本低的冷數據庫中。
這樣可以為核心數據庫使用最好的SSD設備,快速設備容量較小較貴,不可能在全量數據上使用。同時可以保證數據表的容量不會仍然積累,大表也會造成性能增長。
小結
微信紅包系統的可用性實踐微信訂單系統,主要包括了布署設計、SET化設計、異步化設計、紅包訂單儲存構架迭代,數據庫故障自愈能力建設、平行擴容設計。
在業務從起步到小跑再到騰飛的過程中,背后的海量服務能力將對其最終勝敗有著越來越深遠的影響。
在完成這種設計后,微信紅包系統的可用性得到了很大提高,在2017年元旦實現了0故障,在平時的運行中達到99.99%可用性。
免責聲明:部分文章信息來源于網絡以及網友投稿,本站只負責對文章進行整理、排版、編輯,出于傳遞更多信息之目的,并不意味著贊同其觀點或證實其內容的真實性,如本站文章和轉稿涉及版權等問題,請作者在及時聯系本站,我們會盡快為您處理。