高并发资金交易系统设计方案—百亿双十一、微信红包背后的技术架构
21CTO社區導讀 :
今天帶來的是一個長篇文章。主要講解高可用的互聯網交易系統架構,包括雙十一、支付寶&微博紅包技術架構,以及微信紅包的技術架構,希望能給各位提供價值。
概述
話說每逢雙十一節或春節等節假日,對大家來講是最歡樂的日子,可以在微信群中收發紅包,此外今年微信還推出了面對面紅包,讓大家拜年時可直接收發,對于用戶來講很爽也很方便。但對于技術架構側的考量,這使得微信紅包的收發數據成幾何倍數上升,處理的復雜度也增加了很多。
2017年微信紅包發送量最大的時間段是除夕夜,達到了142億個。如此大規模、高并發、高峰值的業務場景,怕是在美帝互聯網的技術團隊,包括EBay、Amazon等也無法想象,在這種巨大的流量與并發后面,需要什么樣級別的技術架構支撐?當達百億級別的資金交易規模時,我們該怎樣來保證系統的并發性能和交易安全?
當今中國的電子商務平臺,有兩個場景稱得上億級以上的并發量:一個是阿里的雙十一,一個是微信的紅包,都是在一個單位時間達到億萬以以上的請求負載。
阿里交易系統與紅包體系架構
我們先來回顧一下阿里『雙十一』的業務場景。
中國移動互聯網的完全普及,使得電商業務每年都幾百倍甚至更高倍速的增長,包括農村用戶也對電商逐漸認可。電商巨頭們每年創造出的新節日,無論是『雙十一』還是『雙十二』,都最大化點染了用戶的消費欲望,人們在這一天瘋狂下單和參與秒殺活動,期望用最便宜的價格購買到心儀的商品,這導致一些平臺后端商品超賣,服務器負載過高拒絕服務等問題頻頻出現。
網站以及各個客戶端帶來巨大的流量對后端技術架構的要求越來越苛刻。比如某個電商網站宕機,對用戶和訂單的損失是無法估量的,就算老板拿著把刀放在桌子也無法根本上解決問題,關鍵還是看技術團隊的架構、能力,同時也包括軟硬件等相關資源投入。
我們拿剛剛過去的2016年『雙十一』來講,阿里巴巴&淘寶網的當天交易額為1207億元,而2015年的數字為912.17億元,成交額足足增長了32.32%。1207億的巨大交易量,背后是阿里巴巴的云平臺提供的技術支撐。馬云同志說,所有的創新都是被逼出來的,不管是被他逼,還是用戶逼,阿里的技術平臺就是這樣被倒逼了出來。
在2016年的阿里技術棧中,和往年比技術平臺也發生了很大變化,一部分變成了數據挖掘,有一部分演變了人工智能計算。除了傳統的Web后端,還增加了直播平臺流媒體應用。
視頻直播系統與Web系統有相同也有不同之處,來看大部分視頻直播平臺的存在著一些技術瑕疵。如下圖示:
以上的問題在后端需要實施不同的技術解決方案,需要進行日志采集實時監控,比如對終端類、后臺類以及CDN的運行日志進行分析等。
阿里的直播端,視頻傳播使用了H.265編碼壓縮。H265編碼在壓縮比以及清晰度上要超過目前主流的H.264標準。阿里云使用了自己的ApsaraVideo平臺完成了這些任務。這個APsaraVideo提供了以下子系統:
1、客戶端推流sdk
2、云端OpenAPI
3、CDN分發
阿里通過上面一系列產品,將推流、轉碼、分發、播放等問題全部解決。
關于流量的負載均衡,阿里雙十一采用了雙專線的CDN,20T以上的帶寬,這樣可支撐1000萬人同時在線下單和觀看視頻直播。
在視頻的傳播壓縮,阿里率先使用H.265編碼壓縮。H265在壓縮比以及清晰度上要超過目前主流采用的H.264標準。
數據存儲
在手機淘寶中的用戶關注信息存儲在云服務器的Redis中,訂單等持久化數據保存在RDS(阿里云的MySQL集群)中。
在阿里的電商平臺,從雙11節開始后,每筆交易隊列都是通過消息中間件系統來做流轉,包括消息發布訂閱,狀態,定時,監控報警等消息服務——這個消息系統是阿里自研的產品稱為AliwareMQ(內核為RocketMQ),當然我們也可以使用ActiveMQ,RabbitMQ等開源軟件。
商品支付成功后的訂單完成后,發給各個物流公司的訂單數據采用了PetaData的產品,支持OLTP和OLAP。不需要把一份數據進行多次復制,然后再進行數據分析,免去在線與離線數據倉庫之間海量數據的傳輸和加載時間,實現在線分析決策。
支付寶與微博紅包架構
支付寶紅包通過性能較高的分布式文件系統保證用戶數據的高可靠與高可用。分布式文件系統需要考慮多機集群之間的一致性與效率問題。
新浪微博紅包在2017年除夕的發搶數量也達到了16億個以上,參與的用戶有不同的類型與地域,對架構、監控與性能優化具有一定的挑戰。除了通過CDN,分布式圖片系統等處理性能問題,另外還有系統底層的內核進行優化,安全修復以及軟硬件擴容。
微信紅包技術架構
2017年1月28日,正值農歷正月初一,騰訊微信平臺公布了在除夕當天用戶收發微信紅包的數量達到142億個,收發峰值為76萬/秒。
2015年的春節數據:除夕搖一搖總次數110億次,峰值1400萬次/秒,8.1億次每分鐘,微信紅包收發達10.1億次,除夕紅包為1.2億個。
2014年的紅包峰值每分鐘被拆開紅包數量為2.5萬個。我們可以看到,2017年是2014峰值的5000倍,紅包數量達到百億級別。
保障并發性能與資金交易安全,帶來了超級挑戰。
微信技術平臺總結過紅包技術有三大難點:
快——如何保證用戶快速搖到紅包?
準——如何保證搖到的紅包能成功拆開?
穩——如何保證拆開的紅包能分享出去?
微信紅包技術結合電商平臺設計的秒殺系統之基礎,采用了以下技術解決方案:
-
SET集合化
-
串行化請求隊列
-
雙維度分拆數據庫表
通過以上方案設計,形成了自己的高并發、資金安全系統解決方案。
我們先回到使用場景中。
當大量的微信用戶在同一時間搖紅包,就會產生每秒千萬級請求。需要對請求疏導分流。
如果不進行負載均衡,分離流量,直接到達后端服務器,多大的服務器集群都會被如此大的流量負何過大而崩潰。
我們來看除夕當天后臺監控數據曲線便能說明一切。如下圖示:
各位可以看到,在前臺紅包重重的分流減壓下,后端服務器負載仍然瞬間飆升幾十倍甚至更高。
紅包產品特點
微信紅包,特別是群里的紅包,我們稱之為微信群紅包。這個東西的產品形態上像極了電商平臺上的商品“秒殺”活動。
舉個場景栗子,某位土豪在微信群里發一個紅包,這相當于商品“秒殺”商品上架。然后群里的其它人開始瘋狂搶之,這個場面相當于“秒殺”的庫存查詢——看看還有沒有貨。當用戶搶到紅包后,紅包在眼前晃呀晃時,食指輕點開拆紅包的操作,它對應了“秒殺”活動中點擊秒殺按鈕動作。
有的時候,點擊出紅包會提示網絡出問題,則是秒殺時你的庫存隊列沒有別人的快,微信給了一個友好的提示罷了。
這點上,和我們在12306網站搶火車票是同樣的道理。
且不急下定論,微信紅包在產品形態上和商品秒殺相比,也有著自己的一些特點和難點。來看都是哪兩點:
第一:微信紅包產品與商品“秒殺”,數量大&并發量更高。
為啥這么說?各位看,當土豪在群里發了一個紅包,相當在網站發布了一次秒殺活動對吧?有10萬個微信群里的人在同一時刻發起紅包請求,也就是說在瞬息之間,時時存在10萬個“秒殺”活動發布出來。
接下來,10萬個微信群里的用戶同時開搶紅包,便產生了海量的并發查詢請求。
第二:微信紅包產品需要極高的安全級別。
紅包的收發,本質上就是資金的交易。微信紅包本身是微信支付(底層支撐是財付通平臺在干活)的一個商戶,由微信紅包來提供資金流轉服務。
群里土豪發紅包時,相當使用微信紅包商戶名義向微信支付申請購買了一筆“錢”,而收貨地址是當前的微信群。
當土豪支付成功后,紅包就“發貨”到該微信群中,群里的人拆開紅包后,微信紅包商戶提供將“錢”轉入拆紅包成功用戶的微信零錢服務。
由于是和錢相關的交易業務,它比普通商品“秒殺”活動有更高的業務嚴密和安全級別要求,與銀行的在線交易有過之而無不及。
而電商平臺上“秒殺”商品由商家提供的,庫存是被事先預設好的,即使出現“超賣”(即實際被搶的商品數量比計劃的庫存多)、“少賣”(即實際被搶的商戶數量比計劃的庫存少)時也有辦法解決,比如和用戶商量、不發貨或者做虛假繁榮,BD小伙伴對外吹吹牛也就算了。
對于微信紅包產品就非常非常嚴謹,一塊錢也不能多,一分錢也不能少,絕不能有半點錯誤。比如群里土豪發249元的紅包絕對不可以被拆出250塊錢,用戶發了100塊錢未被領取,在24小時的退還期內要精確地退還給原路——發紅包的用戶。
第三:微信紅包與接口效率。
微信紅包和微信支付與支付寶的最大區別是,自己不做金融(余額寶業務),所有的支付操作均與用戶綁定的銀行卡銀行接口交互。因此,與銀行接口的安全,效率性能等需要有嚴密的設計。
微信紅包架構難點
上面幾次說,紅包架構與秒殺系統有著些許相似。我們先重溫下典型的秒殺系統架構設計,來看下圖所示。
這個系統可謂是經典。它由網關代理接入層、商業邏輯服務層、緩存與實體存儲層等構成。其中:
代理層,可使用Nginx或Varnish來處理請求接入,Web服務器使用Nginx承載主要的業務邏輯,Cache層如使用Memcached或Redis來緩存庫存數量、數據庫,使用MySQL/MariaDB集群中,做數據庫的持久化存儲。
業務邏輯層可以是多個Nginx的集群,Cache層可以是多臺機器組成的大的內存池,包括數據庫緩存,OpCode緩存等不同類型。
從數據庫側闡述,數據庫可以根據不同業務或日期進行分表分庫,讀寫分離等組成一個負載平衡的集群。
在秒殺業務中,表現就是一個秒殺活動對應Inodb中的一條庫存。當某個用戶開始點秒殺動作時,系統的主要邏輯在于數據庫中對庫存的操作上。
這樣,在數據庫的事務中包含以下3個步驟:
1、鎖定庫存LOCK
2、插入秒殺記錄 INSERT
3、更新庫存 UPDATE
可以肯定的是,所有的大小電商網站均是依此套路。詳解解釋如下:
首先鎖定庫存為避免并發請求時出現“超賣”的情形,同時下單的用戶需要等待此事務執行完后再執行下一個事務。
在數據庫的事務完整性要求,這三步需要在一個時間段一個系列中完成,當中間有一處錯誤發生即進行回滾,相當于放棄當前事務,若無錯誤發生,則整體事務的執行順利被完成。
商品庫存在數據庫中記為一行,大量的用戶同時點擊購買同一件SKU時,第一個到達數據庫的請求就鎖住了這行庫存記錄。
在第一個事務完成提交之前這個鎖一直被第一個請求占用,后面的所有請求就需要排隊等待。
同時參與“秒殺”的用戶越多,并發進數據庫的排隊請求就越多,如同旅行時去衛生間,隊形被排的很長。
所以并發請求搶鎖的事備,成為典型的“秒殺”或搶購類系統的設計難點。
在微信紅包系統的設計上,事務級操作量級更大。即便在普通的時間下,每一時刻都會有數以萬計的微信群在同一時間端發起紅包,就是引發幾萬并發請求搶鎖同時在排隊,這使得數據庫的壓力比普通單個商品“庫存”被鎖放大更多倍。
解決高并發的常用解決方案
常見商品秒殺活動,解決高并發問題,可以有如下幾種解決方案:
一,內存數據庫替代數據庫事務
如上圖所示,我們把實時扣庫存的行為上移到內存數據庫或者叫緩存層來干活,緩存操作完畢后再返回服務器成功,通過隊列異步返回到數據庫進行持久化。
使用內存操作替代磁盤操作,會明顯提升并發性能。但是需要注意引發的缺點,如果在內存操作完成,數據庫保存失敗,或內存出現Crash,數據庫的存儲進程不會進行。因此,這種解決方案不適合與錢相關的交易系統應用,特別是微信紅包。
二,使用樂觀鎖替代悲觀鎖
我們來回顧一下關系數據庫管理系統中的兩種鎖的概念。
悲觀鎖是DBMS里的一種并發控制的方法,它阻止一個事務以影響其他用戶的方式來修改數據。若一個事務執行的操作對某行數據加了鎖,只有這個事務將鎖釋放,其他事務才能夠執行與該鎖沖突的操作。此描述對應于上面所說的并發請求搶鎖行為。
而樂觀鎖,假設多用戶并發的事務在處理時不會彼此互相影響,各事務能夠在不產生鎖的情況下處理各自影響的那部分數據。在提交數據更新之前,每個事務會先檢查在該事務讀取數據后,有沒有其他事務又修改了該數據。如果其他事務有更新的話,正在提交的事務會進行回滾。
秒殺系統中,使用樂觀鎖會在庫存記錄中維護一個版本號。在更新庫存操作進行前,先取當前版本號,在更新庫存的事務提交時,檢查該版本號是否已被其他事務修改。若版本未被修改,則提交事務,版本號加1。如果版本號已被其他事務修改,則回滾事務,并給上層報錯。
樂觀鎖方案解決了“并發請求搶鎖”的問題,可以提高數據庫的并發處理能力。
似乎問題被解決,使用樂觀鎖對于一般的應用系統足夠,但將它應用于微信紅包系統中,會引發下面幾個問題。
如果拆紅包采用樂觀鎖,在并發搶到相同版本號的拆紅包請求中,只有一個人能拆紅包成功,其他的請求將事務回滾并返回失敗,給用戶報錯,用戶完全不可能接受這種體驗。
采用樂觀鎖將會導致第一時間同時拆紅包的用戶有一部分直接返回失敗,反而那些『網慢手慢』的,會有可能因為并發減小后拆紅包成功,這也會帶來用戶體驗上的負面影響。
如果采用樂觀鎖的方式,會帶來大數量的無效更新請求、事務回滾,給DB造成不必要的額外壓力。
有鑒于以上原因,微信紅包系統也不能用樂觀鎖的方式解決并發搶鎖問題。
微信紅包系統的高并發解決方案
我們綜合上面的一系列分析,微信紅包針對相應的技術難點,采用了下面幾個方案來解決高并發問題。
1 系統垂直集合化
集合(SET)化,即分組進行管理。
當微信紅包用戶發一個紅包時,微信紅包系統生成一個ID當它的唯一標識,接下來針對于這個紅包的所有發、搶、拆、查詢詳情等操作都根據這個ID關聯。
紅包系統根據這個紅包ID,按一定的規則(如按ID尾號取模等),垂直上下切分。切分后,一個垂直鏈條上的邏輯服務器、服務器統稱為一個SET(集合)。
這樣,每個集合間相互獨立,互相解耦,不存在任何關聯。
同一個紅包ID的所有請求,包括發、搶、拆、查詳情詳情等,合并在一個集合內處理,形成高內聚。
通過此法,系統將所有紅包請求這個巨大的洪流分散為多股小流,猶似諸侯各國,互不影響,各自治理。請看下圖所示:
綜上所述內容,這個方案對同時存在海量事務級操作的問題,將海量化為微量,問題得以解決。
2 邏輯服務層將HTTP請求隊化列化,解決數據庫并發
前面提到過,微信紅包系統是個交易系統,而數據庫操作的事務性(悲觀/樂觀鎖,回滾等特性)是不可能不用的,因此勢必會存在“并發搶鎖”的現象。
我們把到達數據的事務操作(拆紅包行為)的并發改為串行,由統一一個通道出口,就不會存在“并發搶鎖”的問題了。
這個其實和很多電商平臺,以及PUSH系統等原理相似。
這樣我們的策略就清晰明白了,接著來把拆紅包的事務操作串行地進入數據庫,來將請求在服務器層以FIFO(先進先出)的方式排隊,就可以達成串行的效果。
關于服務器的FIFO隊列系統,在前面提到過阿里的RoketMQ、ActiveMQ還有RabbitMQ等消息中間件產品。當然騰訊的技術團隊自己設計了一個分布式的、輕巧的、靈活的FIFO隊列產品。
具體解決方案實現如下:
首先,將同一個紅包ID的所有請求歸聚到同一臺服務器。使用集合化,將同一個紅包ID的全部請求,提到到同一個集合中。同個SET中會存在多臺服務器同時連接同一臺數據庫服務器。這是基于容災、性能等考慮,多臺服務器互備冗余,并且將流量進行均衡負載。
怎樣將同一個紅包ID所有請求,提到同一臺服務器上?在集合化的設計之外,微信紅包系統添加了一層基于紅包ID 哈希值的分流,如下圖所示:
這和很多分布式系統很像,如圖片的分布式存儲,數據庫的哈希分布等,可謂大道相通。
我們接下來再設計單機請求排隊之方案。當同一臺服務器上的所有請求被接管后,然后按紅包ID進行排隊,串行地進入工作進程處理,達到排隊的效果。看下圖所示:
接下來我們使用memcached來控制并發數量,具體實施為:
為了防止服務器中的請求隊列過載,導致隊列被降級,所有請求又沖進了數據庫,造成數據庫鎖與響應過慢,紅包系統又增加了與服務器同機部署的memcached內存數據庫,把它用來控制拆同一個紅包的請求并發數。我們實際是利用memcached的CAS原子性累增操作,來控制同時進入數據庫中執行拆紅包事務的請求數,苦超過預先設定數值則直接拒絕服務,用于處理數據庫負載升高時的降級體驗。
通過以上三個措施,我們就控制了數據庫的“并發搶鎖”問題。
3 雙維度庫表設計,保障系統性能穩定
任何系統的進化,在持久層都開始分庫分表,微信紅包系統也不例外。
微信紅包的分庫表規則,最開始是根據紅包ID的哈希值分為多庫多表。
隨著紅包數據量逐漸增大,單表數據量也逐漸增加,數據庫的性能與單表數據量有一定相關性,例如InndoDB單表數據量達到幾T的時水平時,性能會有不同程序的下降,這樣就影響系統性能穩定性。
我們可以采用冷(不經常被查詢到)熱(頻率存取的)數據的分離,將歷史冷數據與當前熱數據分開存儲,來解決這個問題。
在處理冷熱數據的分離時,在紅包ID維度分庫表的基礎上,增加了以循環天分表的維度,形成了雙維度分庫表的特色。
具體如下,比如分庫表規則使用哈希+月份的開工,類似db_xx.t_y_dd設計。其中:xx/y是紅包ID的哈希值的后3位,dd是月份,取值范圍在01~31,代表一個月天數最多到31天。
通過兩種維度的分庫表,我們解決了數據單表的大量膨脹,導致性能下降的問題,從而保障了系統性能的穩定性。同時在熱冷數據分離的問題上,使得數據遷移變得簡單優雅。
以上是微信紅包系統在解決高并發問題上的設計方案。總結起就是:采用集合化分治、隊列系統、多維度分庫分表方案,使得單集群數據庫的并發性能提升了多倍,取得了良好的用戶體驗。
在平時節假日、2015和2016春節實踐中充分證明了可行性,取得了顯著的效果。在剛剛過去的2017雞年除夕夜,微信紅包收發峰值達到76萬每秒,收發微信紅包142億個。微信紅包系統的表現穩定,實現了除夕夜紅包收發順暢零故障。
小結
本文從實戰出發,講解了電商平臺以及交易系統的典型紅包系統的構建,包括分布式集群系統的靈活應用,實現Web服務器、內存、緩存以及數據庫的有效利用。通過秒殺系統觸類而旁通到紅包系統,用簡單有效的思維來解決復雜問題。
作者:21CTO社區
說明:本文參考了騰訊大講堂關于微信紅包架構的文章,原文一部分生澀部分做了優化。阿里架構一部分內容參考了阿里云社區關于雙十一的部分內容。
來源:http://www.sohu.com/a/126891351_505802
總結
以上是生活随笔為你收集整理的高并发资金交易系统设计方案—百亿双十一、微信红包背后的技术架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 端午节送香包有什么意义?
- 下一篇: 面包机做面包为什么硬?