大促系统全流量压测及稳定性保证——京东交易架构
https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=2653547431&idx=1&sn=744a42639e7c362a05aacbfbed6a988c&scene=0#wechat_redirect
大家好!我是來自京東商城交易平臺的楊超,今天特別高興能夠來給大家分享每年 618 及雙十一所做過的工作,我是 2011 年加入京東,在這 5 年中我經歷了不少技術演進,也看到了不少變化,在這里給大家做一個分享。
?
先介紹一下交易系統基本情況。
?
交易系統的三階段
?
(點擊圖片全屏縮放)
?
這張圖是整個京東商城數據流向結構。這個圖主要分為三個部分。
?
訂單生成前,包括單品頁,購物車,架構,促銷等功能,我們每個用戶進來需要訪問。它的特點是大促期間訪問量非常大,后面會詳細介紹如何應對。
訂單預處理,訂單生成之后,這是一個原始生成單,之后需要對訂單進行預處理,進行拆包,包裹的拆分、大家電小家電拆開包裹運送等。因為是統一下單,這一塊是訂單預處理。挑戰是訪問量大,各個模塊如拆單、訂單轉移,支付臺帳等可能會承受非常大的壓力,我們會采取擴容存儲,限流,數據結構優化等方法去應對。
訂單履約階段,真正到后面是整個處理過程,配送黏合起來做的系統。這是京東商城的服務結構。
?
交易系統的三層結構
?
下面是交易結構圖,從左到右,單品頁是網站平臺做的,今天來到現場的也有一些參與過的同事。移動端、微信、手Q,等入口都會調到購物車服務。
?
從購物車開始,我們從上到下是一個典型的分層結構,上面是調用來源,中間是我們的服務,下面是依賴的底層服務。其中強依賴服務是關鍵路徑所需要調用的服務,是主流程中不可缺少的一部分。
?
(點擊圖片全屏縮放)
?
強依賴服務在大促期間不能被降級,我們需要提前擴容,以及進行代碼重構、拆分、按來源單獨部署等方法提前進行優化。
?
交易系統的訪問特征
?
為了更好應對,我們需要對用戶訪問的特點進行分析。參看下面圖,2011 年到 2015 年整個的單量,2011 年,618 是幾十萬的單量,去年單量一天是幾千萬。看著單量往上增長的這張圖,就能感受到系統壓力有多大。
?
為了應對大促的壓力,我們必須清楚知道用戶訪問系統功能的流量及分布。經過數據統計,接單前面這波系統,正常每一單,有一個前幾年的大概的統計。購物車:結算頁:產生訂單頁面訪問的比例是 16 :4 :1,也就是說購物車訪問 16 次,結算頁訪問 4 次,提交訂單頁面訪問 1 次。到 618 及雙十一,每天 PV 就是幾十億,幾百億、上千億,因此我看到最大的量 1 分鐘是幾千萬。我需要清楚知道這幾千訪問落到那幾個頁面。
?
根據京東傳統,每年定一個目標,618 當天或者三天需要達到多少億的指標,比如說一百億或者幾百億,后面我們會把錢換算成我們的單量,我們客單價是多少?如果客單價是 300,目標要 100 億,則我們單量需要達到百萬或者三千萬,這樣通過預估出來當天的單量會有多少,這是提前的準備的整體規劃過程。
?
為了每年的 618、雙十一系統的穩定,京東研發如何應對?
?
應對大促的第一步
全鏈路全流量線上壓測
?
系統底層的調用量是知道的,往年的 618 或者往年的雙十一也可以找到。經過半年的業務跟進,我們系統會有很多的變更,數據變更或者是代碼變更結構變更都會產生,我們知道這個系統能夠承受多大量,上來對它進行壓測。
?
壓測分為線上壓測、線下壓測,主力做線上壓測。
?
為什么我們會采用線上壓測?早年我們只做線下壓測,環境跟線上不一樣,路由器和機器 CPU,物理機,每一個不相同或者架設的路由超過 3 層,丟包,各種數據不一樣,壓測出來的數據經常會差異。
?
線上壓測分開是怎么樣做的?需要將讀業務跟寫業務區分開。讀業務,我們正常可以看到讀價格讀庫存、讀購物車場景的分開,讀跟寫,看到購物車上的分布,就能知道是讀還是寫。
?
演練縮減服務器
?
從壓測上,在集群中將服務器縮減,因為我們支撐的量,最高量達到 1 分鐘達到 1 億左右,平常最少有幾十萬、幾百萬的量。集群肯定是比較大的,最少也是幾十臺的機器,我們會把集群機器逐臺往下縮減,真正看到線上量能扛到什么情況。
?
做到這兒,大家會有疑問?風險挺大。對,風險的確挺大,比如一個集群的 30 臺機器一個一個往下縮,比如縮到 5 臺,如果扛不住,所有的機器就崩潰,就會面臨很大風險。所以梳理完每個架構之后,每年我們冒著風險,找到這個點,往上一點的量進行縮減,縮到一定程度再強行縮。
?
復制流量
?
主要通過 TCPCopy 復制端口流量,多層翻倍放大流量。如下圖就直接將每層流量翻倍整體就是 1,000 倍,工具實現簡單,可以實現多條線組合進行流量復制。通過這種方式發起超負荷的請求,檢驗服務能夠承載的容量。
?
?
模擬流量
?
我們做了一個成立了一個壓力小組,線上壓力測試小組,我們做線上壓測。用非常簡單的底層工具去做壓測。底層發起的量特別快而且特別多,集群,我們只做了壓測平臺,把這些工具集成起來做模擬流量壓測。
?
在數據模擬上,我們是自己事先會準備一批數據。比如說幾萬個用戶,幾萬個 SKU。商家各種庫存模式,促銷模式,在模擬平臺我們會準備好。
?
流量泄洪
?
我們把訂單在這個結構,接住堵在這個地方不往下放,往后拽都是密集的一些服務。從這一塊把量堵住,堵幾十萬,突然有一天打開,看到一個峰值,看每一分鐘處理量,往后能承受多大量,是不是能夠承受發起的量,
?
實施方法
?
大家可能在朋友圈看到照片,各個服務的核心人員,集中在一個會議室,進行壓測。一步一步往上加量,嚴密監控線上響應情況、訂單量情況、各個服務器,以及各個緩存、數據庫等機器的實際負載情況。出現任何風吹草動就停止發起壓力,并進行記錄和排查問題。
?
?
然后壓測訂單提交,往主集群寫數據。跟購物車不同,這種壓測會直接在生成集群上進行壓測,并會寫入數據。因此需要將寫入數據進行隔離操作,并將垃圾數據進行數據刪除,不能進入生產環境。
?
根據業務和技術維度篩選一批商品、一批用戶,主要覆蓋存儲分布、用戶每個等級以及業務分支。促銷組幫忙建立能覆蓋所有環節的促銷數據。將這些用戶的提交訂單后清空購物車的功能禁用,保證能不停的重復下單。另外這些用戶的訂單提交流程中的郵件、短信提醒等相關功能禁用,產生的訂單進行隔離,不往生產系統下發,并在測試完成后進行刪除。
?
線上壓測時,組織各個相關組核心人員嚴密監控各項數據。出現問題立即停止壓測。先進行恢復,同時進行數據記錄和問題排查,如分鐘級無法恢復則直接切亦莊備用集群。
?
每個服務分別進行一輪壓測,記錄每個服務和購物車、訂單提交壓測得出的數據。根據線上實際用戶調用比例進行換算,得出一個相對精準的整體集群承載數據。
?
訂單生產后系統,主要用憋單,快速釋放流量進行壓測。形成對整個后續系統的,持續性高流量沖擊,得出整體系統的處理訂單能力。
?
下面是壓測的 DPMP 系統結構圖。
?
?
通過壓測,就知道目前京東系統,壓測完能承受多大量,面臨我們目標差距有多少?壓測完之后,我們就要運維優化。
?
?
在打壓時候,我們按照交易系統的流量分布來模擬流量,比如正常訪問購物車與結算頁是 16 :4 的流量,下圖的在打壓時候我們也嚴格按照這個流量來執行,確保壓力接近大促時候的真實訪問場景。
?
?
?
應對大促的第二步
根據壓力表現進行調優
?
調優一:多級緩存
?
緩存從前面比較多,CDN、Nginx、Java 都會有緩存。
?
緩存是逐級往下做,是一個漏斗狀,最開始做緩存,到緩存的持續性在很短的時間內,一分鐘或者一秒鐘或者毫秒,這樣給用戶的感知是看不到緩存的,如果你要承載這么大量,必須逐級做緩存,前面做一些靜態緩存掉,后面會做一些基礎數據緩存,最后大數據,一層一層往上能擋住整個這一塊,
?
?
?
調優二:善用異步
?
這是購物車大概的結構。這里有一個異步雙寫,我們會寫丟這個數據,寫丟沒關系,我們購物車是整體的,加一個商品,寫不過來,下次過來又會全覆蓋。這樣購物車就有一個多機房多活的可用性。
?
?
調優三:超熱數據的緩存
?
購物車里面做熱數據緩存,這種數據的緩存,比如促銷服務直接影響到價格,緩存效率必須是在秒級毫秒級,在一秒鐘怎么篩選十億商品里面最熱的商品?
?
我們利用 Queue 的原理,不斷往里塞 SKU,隊列的長只有 50。傳進來之后,這里有的位置往前移,我們很快知道在一秒鐘知道,排在前面肯定是訪問次數最多的,每一個階段應用存儲訪問最多的數據,如果是秒殺商品,500 萬的請求有十萬到二十萬,它肯定大部分的請求在這塊就出去了,不會穿透進來,這是我們自己做的熱數據緩存。
?
?
?
調優四:數據壓縮
?
對 Redis 存儲的數據進行壓縮,這樣空間又縮小四分之一或是三分之一,我們數據到后面就會很小。當量小之后,訪問效率就會升高,你數據量彈出很小,丟單率很小,可以提高我們的可用性。
?
異步和異構
?
什么是異步?購物車會調三個服務,如果是串行,一個 2 毫秒,累計起來是 6 毫秒。同時去處理,同時往后并行,這三個服務同時去調,根據業務規則要先調商品,再調促銷,調兩次,肯定在三毫秒之內。
?
異步數據落地,中間存儲來解決訪問流量過大,沖擊原始存儲的問題。包括庫存狀態庫存數據的剝離,庫存狀態調用量太大,穿透直接到庫存數據。
?
接單系統的異構
?
異步異構用得最多在這個系統里面。這一步接單系統的異構。接單系統在這一塊的異構。我們整個接單,一次性提交訂單、購物車是提交成一份數據,這樣提高效率。
?
如果說按照原來的做法,直接寫到表里面,有很多訂單明細、促銷明細、優惠券很多要寫,這樣訪問效率會存在瓶頸。因此后面寫到接單服務,再異步,調動某一個狀態機,通過管道服務再衍生出來拆分成訂單中心數據,支付臺賬,異構之后,單個系統的應對峰值的能力都得到了提升。
?
?
訂單中心的異構
?
提交訂單、接單做了異步處理。
?
再往下訂單中心又會有很大異構,分成了 4 個子系統去分別調用。訂單中心會產生列表服務數據,列表服務數據根據PIN的維度用戶維度看到數據存儲,第一步直接寫,寫不成功就是狀態機,異步寫到這一塊存儲。
?
訂單中心有一個列表服務的存儲,再有訂單詳情的存儲,訂單詳情的存儲是根據訂單維度去存,這一塊是根據 PIN 存的。
?
第三、四部分是單拎出來的狀態服務及跟蹤服務,后續生產跟它直接掛鉤。通過異構之后,提高了訂單中心應對峰值的能力。
?
商品頁的異構
?
后面看一下看不到商品服務的一切異構。ERP 過來,是采銷或者 POP 用戶,進入我們的 MySQL,通過商品發布系統,接到商品消息在這一塊之前是不能售賣,這一塊直接發出去,這個消息會寫自身的存儲,我們會裝 A 包、B 包、C包。
?
-
A 包就是基礎數據,比如商品名稱;
-
B 包擴充數據;
-
C 包比如特殊標識,生鮮、易碎。
?
這樣可以把數據分開,因為數據量太大了,十個億的數據就有幾百個 G,分開幾個包。這樣性能和可擴展性都得到了提升。
?
商品服務調用方,我只要調,訂單系統查你,我知道是生鮮、易碎。但是前面需要基礎數據,商品的名字,特殊屬性,只有訂單結算頁需要,所以分這么多的包,我可以分開部署商品服務。為什么異構這些包。
?
發一個通知給別的系統,大部分系統依賴基礎服務,發一個消息給他,商品變更了,它會緩存自己需要的數據,實時計算通過這個地方過來,異構出來存儲,內部異構出來這么多存儲,這是后臺用戶存儲。
?
一個商品服務,真正做大了可以參考對一個胖的大系統進行拆分的異構方法,如果達不到這種規模之前也不建議過細去分。
?
?
應對大促的第三步
分流與限流
?
我們假設系統當超過一定流量后,超過的流量做直接拒絕處理,以便保護后端的服務,這就是限流。
?
Web 的限流根據 PIN 來限流,這是根據 IP 加 PIN 風控數據限流,這一塊根據業務邏輯,一個單一天能下多少單,根據這個邏輯去限流。渠道可以按 App、PC、微信等分開,分流和限流這么做。
?
?
下面講秒殺系統是怎么來的。秒殺系統是限流和分流的典型。
?
秒殺,假設預約是 1500 萬,在那一分鐘之內,這么多用戶過來搶手機,也就是單個商品,就把流量直接導到秒殺系統。
?
秒殺系統從 Ngnix 進來就有各種的限制,到我們會識別用戶供應商或者商販去刷的數據,這塊調用是從正常訪問的單品頁分出來,不影響主流程。
?
通過 IP、PIN、每一步怎么來、用戶以提交記錄,一秒鐘提交多少次,一分鐘提交多少次等一堆的規則做判斷來限流。到最后再驗證有沒有預約、常用地址服務等,都通過后再調到接單系統。
?
整個秒殺系統就是一個典型的沙漏的系統,當流量跑到后面,實際上只剩很小的一部分,只有真實的寫流量到接單。
?
接單提交服務單獨出來兩臺機器給它用,后面的存儲得到保護,兩臺機器最多也就幾十萬,也能承載住,這就是分流跟限流。
?
促銷與價格
?
促銷里面也有一個限購,比如前 30 個用戶享受促銷,發一個碼出去,需要對這個碼進行處理,這是一種限流。
?
促銷分流中需要把價格服務單拎出來,分出去,單品頁搜索,手機微信,購物車的架構從這里出來,最實時的價格。這樣產生分流,這一塊有一個存儲分流,還有更多其它的就沒有一一列舉,這只是一個示意圖。
?
這就是我們整個的分流跟限流。根據前面的渠道,調用量、做多少程度,相對于影響力,做分流和限流。
?
?
應對大促的第四步
容災降級
?
如果分流、限流還沒抗住,系統進一步出現壓力問題,再要做準備做容災降級。
?
容災降級有機房容災,我們做多中心機房,網絡容災、內網外網的容災,應用的容災,分組、托底容器,最后保證基礎的服務是正常的。
?
網絡及 IDC 降級
?
這是容災降級,這是網絡大概示意圖。我們的 ISP 進入機房,核心交換機、柜頂交換機、這是交換級的容災,網絡共享容災。
?
?
業務降級
?
購物車結算頁的降級,當訂單出現過大,延保服務、預約服務如果不行,直接保主流層,就屬于業務層面的降級。
?
(點擊圖片全屏縮放)
?
整個 618、雙十一準備下來了,后面準備降級方案、容災方案列出很多,每個業務需要根據自己的情況去考慮,上面只是簡單列舉了幾個供大家參考。
?
?
應對大促的最后一步
完善監控
?
最后到臨近雙十一、618,需要網絡監控、機器監控、以及了解訂單量、登錄量、注冊量等應用級的監控。
?
這是 IDC 機房的監控,運維部做的。這是單個機器,物理機、Docker 的監控。以及對交換機、IP 進行監控,這是網絡監控。
?
下面是方法監控,每個方法監控到 TP99,99 是最近幾次的峰值是達到多少毫秒?成功率、失誤率、調用次數等。
?
?
訂單量的監控,一旦出問題都會報警,這是大概的監控系統,這是依賴的一些監控系統,我們還會衍生出來自己應用的監控。比如說庫存,預算是最重要,提交訂單,保證提交訂單成功是最重要,從那一堆,庫存自己的一套寫一個頁面,寫一套監控系統出來,優惠券、購物車寫一個小監控系統去監控。監控是到大促的眼睛。
?
?
一次大促,總結下來就這么多,謝謝大家!
?
Q&A
?
Q:您提到做線上的壓測,會產生很多臟數據,這個數據是最終怎么處理。還有一個,您做了好多異構的數據,這個數據怎么保持它的一致性。
楊超:先回答你臟數據,所謂的臟數據,寫數據是為了隔離出來,有的是打標,有的是另外起表,在數據庫里面把這些數據隔閡開來打標,一邊寫一邊刪,壓測,30分鐘到一個小時,我們是在凌晨做這些事情,壓測完寫的數據是非常危險,寫的數據會爆,引起癱瘓。我們實時監控它,打標清理,首先切到小集群承載。真實的集群,真正的量不會達到618那個量,我們的峰值可能會很高,正常到晚上凌晨那個量很小,我們就把它切到另外一個小集群承載,后面再把它轉回來。
?
異構出來的數據怎么保證它完整性一致性?異構都是小維度,不成功會補全,補全不成功會穿透,寫 Ngnix,會一層一層穿透到 MySQL 數據庫。
?
Q:一個庫存性能與一致性的問題,客戶下單肯定會判斷一下有沒有庫存,并且他下單的時候還要實時扣減庫存,這方面怎么解決性能問題?如果把庫存的量放在 MySQL,一拿會慢也會影響你的下單,并且渠道會比較多。
楊超:庫存大部分用前端 Redis 防重。用業務維度做防重,第一次查出來的業務屬性、商品屬性、庫存數量數據,我們的一些業務數據、一致性查出來,進行一次校驗,校驗成功就通過,校驗不成功就告訴它庫存不足。目前看到這個單量一天幾千萬單,幾乎沒有超賣的部分。
?
Q:SKU 庫存量是放在 Redis,通過 Redis 實時判斷?
楊超:對,基本上卡的第一道都在前面,查的第一項,如果查到數據就會寫到 Redis,最后 MySQL 是落地存儲,內部存儲。MySQL 寫入量最大達到 60、70 萬。
?
Q:還有一個問題關于線上壓測,還有線下壓測。線下壓測指的是你們把流量鏡像到相同環境里面實時做壓測還是走的同一個環境?
楊超:線下一個測試機房,拿一堆機器按照你線上結構部署,導一點數據下來進行壓測。線上是我們真實布局的線上的環境,配置差不多一樣。
?
Q:數據庫對應的客戶能否看到你的壓測數據?
楊超:壓測的訂單,從接單到后面就會把它屏蔽,直接截住,相關數據要打一個標,正常數據打一個標識,不能往下傳,不能讓客戶看到。
轉載于:https://www.cnblogs.com/davidwang456/articles/8360456.html
總結
以上是生活随笔為你收集整理的大促系统全流量压测及稳定性保证——京东交易架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于用户画像大数据的电商防刷架构
- 下一篇: Lambda架构与推荐在电商网站实践