1. 程式人生 > >高併發資金交易系統設計方案—百億雙十一、微信紅包背後的技術架構

高併發資金交易系統設計方案—百億雙十一、微信紅包背後的技術架構

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分發

阿里通過上面一系列產品,將推流、轉碼、分發、播放等問題全部解決。

關於流量的負載均衡,阿里雙十一採用了雙專線的CDN20T以上的頻寬,這樣可支撐1000萬人同時線上下單和觀看視訊直播

在視訊的傳播壓縮,阿里率先使用H.265編碼壓縮。H265在壓縮比以及清晰度上要超過目前主流採用的H.264標準。

資料儲存

手機淘寶中的使用者關注資訊儲存在雲伺服器的Redis中,訂單等持久化資料儲存在RDS(阿里雲的MySQL叢集)中。

在阿里的電商平臺,從雙11節開始後,每筆交易佇列都是通過訊息中介軟體系統來做流轉,包括訊息釋出訂閱,狀態,定時,監控報警等訊息服務——這個訊息系統是阿里自研的產品稱為AliwareMQ(核心為RocketMQ),當然我們也可以使用ActiveMQ,RabbitMQ等開源軟體

商品支付成功後的訂單完成後,發給各個物流公司的訂單資料採用了PetaData的產品,支援OLTP和OLAP注。(注:PetaData分散式資料庫之一,OLTP:On-Line Transaction Processing聯機事務處理系統(OLTP) 也稱為面向交易的處理系統,其基本特徵是顧客的原始資料可以立即傳送到計算中心進行處理,並在很短的時間內給出處理結果;聯機分析處理 (OLAP) 的概念最早是由關係資料庫之父E.F.Codd於1993年提出的聯機分析處理OLAP(On-Line Analytical Processing),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來處理請求接

(注:Varnish 是記憶體快取,速度一流,但是記憶體快取也限制了其容量,快取頁面和圖片一般是挺好的

Web伺服器使用Nginx承載主要的業務邏輯,Cache層如使用Memcached或Redis來快取庫存數量、資料庫

(注:Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric為首開發的高效能分散式記憶體快取伺服器。其本質上就是一個記憶體key-value資料庫,但是不支援資料的持久化,伺服器關閉之後資料全部丟失;Redis是一個開源、支援網路、基於記憶體、鍵值對儲存資料庫,使用ANSI C編寫。

使用MySQL/MariaDB叢集中,做資料庫的持久化儲存。

(注:MariaDB資料庫管理系統是MySQL的一個分支,主要由開源社群在維護,採用GPL授權許可 MariaDB的目的是完全相容MySQL,包括API和命令列,使之能輕鬆成為MySQL的代替品。

業務邏輯層可以是多個Nginx的叢集,Cache層可以是多臺機器組成的大的記憶體池,包括資料庫快取,OpCode快取等不同型別

(注:當直譯器完成對指令碼程式碼的分析後,便將它們生成可以直接執行的中間程式碼,也稱為操作碼(Operate Code,opcode)。Opcode cache的目地是避免重複編譯,減少CPU和記憶體開銷。)。

從資料庫側闡述,資料庫可以據不同業務或日期進行分表分庫,讀寫分離等組成一個負載平衡的叢集

在秒殺業務中,表現就是一個秒殺活動對應Inodb中的一條庫存。

(注:InnoDB,是MySQL的資料庫引擎之一,為MySQL AB釋出binary的標準之一。InnoDB由Innobase Oy公司所開發,2006年五月時由甲骨文公司併購。與傳統的ISAMMyISAM相比,InnoDB的最大特色就是支援了ACID相容的事務(Transaction)功能,類似於PostgreSQL

當某個使用者開始點秒殺動作時,系統的主要邏輯在於資料庫中對庫存的操作上。

這樣,在資料庫的事務中包含以下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原子性累增操作

CAS是單詞compare and set的縮寫,意思是指在set之前先比較該值有沒有變化,只有在沒變的情況下才對其賦值。

來控制同時進入資料庫中執行拆紅包事務的請求數,苦超過預先設定數值則直接拒絕服務,用於處理資料庫負載升高時的降級體驗。

通過以上三個措施,我們就控制了資料庫的“併發搶鎖”問題。

3 雙維度庫表設計,保障系統性能穩定

任何系統的進化,在持久層都開始分庫分表,微信紅包系統也不例外。

微信紅包的分庫表規則,最開始是根據紅包ID的雜湊值分為多庫多表

隨著紅包資料量逐漸增大,單表資料量也逐漸增加,資料庫的效能與單表資料量有一定相關性,例如InndoDB單表資料量達到幾T的時水平時,效能會有不同程式的下降,這樣就影響系統性能穩定性。

我們可以採用冷(不經常被查詢到)熱(頻率存取的)資料的分離,將歷史冷資料與當前熱資料分開儲存,來解決這個問題。

在處理冷熱資料的分離時,在紅包ID維度分庫表的基礎上,增加了以迴圈天分表的維度,形成了雙維度分庫表的特色。

具體如下,比如分庫表規則使用雜湊+月份的開工,類似db_xx.t_y_dd設計。其中:xx/y是紅包ID的雜湊值的後3位,dd是月份,取值範圍在01~31,代表一個月天數最多到31天。

通過兩種維度的分庫表,我們解決了資料單表的大量膨脹,導致效能下降的問題,從而保障了系統性能的穩定性。同時在熱冷資料分離的問題上,使得資料遷移變得簡單優雅。

以上是微信紅包系統在解決高併發問題上的設計方案。總結起就是:採用集合化分治、佇列系統、多維度分庫分表方案,使得單叢集資料庫的併發效能提升了多倍,取得了良好的使用者體驗。

在平時節假日、2015和2016春節實踐中充分證明了可行性,取得了顯著的效果。在剛剛過去的2017雞年除夕夜,微信紅包收發峰值達到76萬每秒,收發微信紅包142億個。微信紅包系統的表現穩定,實現了