《大促訂單、PV雙線破億,解密京東商城交易系統的演進之路》要點:
本文介紹了大促訂單、PV雙線破億,解密京東商城交易系統的演進之路,希望對您有用。如果有疑問,可以聯系我們。
本文根據京東商城交易平臺的楊超在“第一期蝴蝶沙龍:揭秘618電商大促背后的高并發架構”會議上的演講整理而成.
大家好!我是來自京東商城交易平臺的楊超,今天特別高興能夠來給大家做這個分享.我是 2011 年加入京東,5 年中我經歷了不少技術架構的演進,也看到了不少變化.這次分享首先介紹京東商城的服務、京東交易結構,然后介紹針對618備戰,我們做的一些事情,以及從2011年到現在,京東交易平臺經歷的變化.
如圖所示是京東交易平臺的一張大的漁網圖.從主頁面網站開始,到后面提交訂單、購物車、結算頁、訂單中心等的整個生產過程,大體可分為三個部分.第一部分是訂單提交前,就是俗稱的購物車,結算頁.第二部分是訂單預處理部分,生成訂單之后、到物流之前,還會有一些預處理過程,比如生鮮、大家電、奢侈品、易碎品等商品.第三部分是訂單履約部分.今天我講的主要內容是,交易平臺的提交以前和預處理部分.
京東交易平臺,包括單品頁的價格、庫存,購物車、促銷,結算頁的下單,再到訂單中心線.
如下圖所示,2011年京東的訂單量是30萬,2015年訂單量就已經到了3000多萬,京東的流量每年不斷地翻倍.訂單從30萬到100萬是三倍增長,實際上訪問流量的翻番,可能是10倍、50倍,甚至上百倍.
比如,用戶購買東西從單品頁進入,然后查詢很多信息,包括價格、評價.商品加入購物車后,用戶會不停地比對各類商品.刷新購物車,從前端到后端所有的服務基本上都會刷新.那么,當你刷新一次,調動服務就會承受一次動態的調用.當訂單量翻三倍的時候,實際服務訪問量最少是要翻20倍.
我見過的京東目前最大的前端流量是,一分鐘幾千萬,一個正常前端服務訪問量是在幾千萬,幾億、幾十億,一天的PV.
那為了應對如此大的調動量,每年的618、雙11,京東都做了什么?
下面我會詳細講618、雙11備戰后面,每一年所做的不同改變.這是一個整體的大概分析,我們從哪些方面做優化,去提高系統的容災性,提高系統應對峰值流量的能力.
實際上每年京東內部的正常情況是,領導層會給出一個大概的預期值,就是希望當年的大促中,需要達到幾百億,或者幾十億的預期銷售額.那么,根據這個銷售額,根據客單價(電商的訂單的平均價格,稱為客單價)換算成訂單量.
另外在以往的618、雙11中,我們都會統計出訂單量和調用量,即前端價格需要訪問多少次,購物車需要訪問多少次,促銷引擎需要訪問多少次,整個流程需要多大的量.有了大概的方向之后,就會把具體系統的量換算出來.第一輪會做壓測,壓測分為線上壓測和線下壓測兩部分.這些都是準備工作,根據一些指標往年的增長量估算出一個預期值.
壓測
這是真正進入第一波.首先,每年的大促前,都會經歷半年業務迭代期,整個系統會有很多變更.我們會進行第一輪的壓測系統,壓測之后會知道當前線上真正能夠承載的訪問量有多大,距離預期有多遠.壓測分為線上壓測跟線下壓測.壓測場景分為讀業務和寫業務,壓測方案有集群縮減服務、模擬流量、流量泄洪.
講到壓測,先說說壓測的來歷吧.2011年時候沒有線上壓測,線下壓測也不是很全.真正引入線上壓測是在2014年,訂單量已經接近2000萬.之前的大促備戰,是通過組織架構師、優秀的管理人員,優秀的技術人員,一起去評估優化系統,因為在迭代代碼的同時,我們會知道系統哪里容易出現問題,然后對數據庫、Web或者業務服務做一堆優化.
在2014年,訂單量到了上千萬,換算成為訪問量,每天的PV大漲,集群也更大偏大,如果還是只依靠技術人員去優化,可能會不足.于是就衍生出壓測,我們想知道系統的極限值.這樣,當系統承受不住訪問請求的時候,我們就會知道哪里出現瓶頸,比如,服務器的CPU、內存、連接速度等.我們通過第一輪壓測找到第一波的優化點,開始了線上的壓測.
當時第一波做線上壓測是在凌晨一兩點,把整個線上的流量剝離小部分機器上.把集群剝離出來,然后再做壓測.所有的服務器、所有的配置就是用線上完全真實的場景去做壓測,就能夠得到線上服務器在真實情況,再優化.
曾經做redis壓測,把進程綁定到單核CPU,redis是單進程程序,當時集群的性能就提升了5%.因為機器的每次CPU切換,都需要損耗資源,當時把進程直接綁定到固定的CPU上,讓它高壓下不頻繁地切換CPU進程.就這樣一個改變,性能提升了5%.當量很大的時候,真正底層細節的小改變,整個性能就會有很大的改進.這是我們從2014年引進線上壓測和線下壓測之后的一個真實感受.
壓測完之后得到容量,得到交易系統的購物車、結算頁大概承受值,之后會進行一輪優化,包括對NoSQL緩存的優化.京東在2012年的時候自建CDN網絡,Nginx層做了很多模塊加Nginx+lua的改造.應用程序層也會做很多緩存,把數據存在Java虛擬器里面.數據層的緩存,主要有redis、?NoSQL的使用,另外會剝離出一些獨立的數據存儲.
緩存壓縮
CDN域名切換的問題,原來外部CDN切換IP,需要15-20分鐘,整個CDN才能生效.我們的運維做了很多的改進,自建了CDN,內網VIP等等進行緩存壓縮.Nginx本身就有介質層的緩存和GZIP壓縮功能,把靜態js、CSS文件在Nginx層直接攔掉返回,這樣就節省了后面服務的服務器資源.
GZIP壓縮能壓縮傳輸的文件以及數據,節省了網絡資源的開銷(GZIP壓縮主力損耗CPU,機器內部資源的平衡).前面就直接壓縮返回圖片、文件系統等靜態資源.流量到部署集群系統時,只需要處理動態資源的計算,這樣就將動態靜態分離集中處理這些專向優化.
真正的計算邏輯,服務自身的組裝、如購物車的促銷商品、服務用戶,基本上所有資源都耗費在此.比如,連接數都會耗費在跟促銷,商品,用戶服務之間調用,這是真實的數據服務.如果不分離,你用DOS攻擊直接訪問JS,然后傳一個大的包,就會完全占用帶寬,連接和訪問速度就會非常慢.這也是一種防護措施,在大促中會做很多緩存、壓縮這些防護.
購物車從2010年就開始Java改造,整體結構的劃分主體有,促銷引擎、商品、用戶.系統結構在2012年已經成型.到13年,加入了購物車服務的存儲.原來購物車存儲的商品是在瀏覽器端的Cookie里的,用戶更換一臺設備,之前加入的商品就會丟失掉.為了解決這個需求,我們做了購物車服務端存儲,只要登錄,購物車存儲就會從服務端拿取.然后通過購車服務端存儲打通了手機端與PC端等的存儲結構,讓用戶在A設備加入商品,在另外一個設備也能結算,提高用戶體驗.
異步異構
2013年之后,接入了很多其他業務,如跟騰訊合作,有微信渠道,我們會把存儲分為幾份,容量就會逐步地放大.這是異步的存儲,手機端會部署一套服務,PC端會部署一套服務,微信端會部署一套服務.就會隔離開來,互不影響.
購物車就是這么做的.購物車整個數據異步寫的時候都是全量寫的.上一次操作可能異步沒寫成功,下一次操作就會傳導都寫成功了.不會寫丟,但是可能會有一下延時,這些數據還是會同步過來.比如,從PC端加入商品之后沒有立即同步到移動端,再勾選下購物車,購物車的存儲又會發生變更,就會直接把全部數據同步到移動端.這樣,我們的數據很少會出現丟失的情況.
異步寫的數據是進行了很多的壓縮的.第一層壓縮從前端開始,整個前端是一個接口串,到后面購物車服務,先把它壓縮為單個字母的接口串,后面又會壓縮成字節碼,使字節流真正存儲到redis層里面.當存儲壓縮得很小的時候,性能也會提高.
緩存壓縮只是為提升縱向性能做的改進.后面還會進行橫向異步異構的改進,購物車把移動端存儲剝離出去,移動端的存儲在一組redis上,PC端的存儲在另外一組上.PC端和移動端是異步去寫,這樣相互不影響,雖然它們的數據是同步的.這是針對多中心用戶所做的一些改進.
外層的異步,是做一些不重要的服務的異步,就從購物車前端看到的地址服務、庫存狀態服務.庫存狀態服務在購物車只是一些展示,它不會影響主流層、用戶下單.真正到用戶提交的時候,庫存數據才是最準確的.這樣,我們會優先保證下單流程.
接下來講講接單的異步.提交訂單,提交一次訂單原來需要寫10多張表.當訂單量提高到一分鐘10萬的時候,系統就無法承受.我們就把整個提交訂單轉成XML,這樣只寫一張表,后面再去做異步.接單的第一步,先是把整個訂單所有信息存儲下來,然后再通過狀態機異步寫原來的10多張表數據.
關于訂單中心的異步異構,訂單中心原來都是從訂單表直接調出的.隨著體量增大,系統無法承載訪問,我們異構出訂單中心的存儲,支付臺帳存儲等. 異構出來數據都具有業務針對性存儲.數據體量會變小,這樣對整體的優化提升提供很好的基礎.
這樣的存儲隔離,對訂單狀態更新壓力也會減小,對支付的臺帳、對外部展示的性能也會提升.大家會疑問,這些數據可能會寫丟.我們從第一項提交開始,直接異步寫到訂單中心存儲,到后面訂單狀態機會補全.如果拆分不出來,后面就生產不了.也就是說,到不了訂單中心,數據生產不了,一些異步沒成功的數據就會在這個環節補全.
然后是商品的異步異構.2013年,商品團隊面臨的訪問量,已經是幾十億.如何去應對這個情況呢?很多商品數據貫穿了整個交易,包括交易的分析、各個訂單的系統都會調商品系統.我們會針對系統優化.
比如,針對促銷系統調用,促銷系統主要調用特殊屬性,我們把這些屬性存到促銷系統的特有存儲.庫存系統也類推.調用的特殊屬性的方法也不一樣.譬如大家電的長寬高這些特有屬性,不像前端商品頁里只是基本屬性.這樣就把所有的屬性異構處理,針對商品緯度、商品ID等所有數據會異構一份到庫存、促銷、單品頁,后面進行改造的時候,又將數據分A包、B包、C包.
京東的業務很復雜,有自營,又有平臺數據,A包可能是基礎數據,B包可能是擴展數據,C包可能是更加偏的擴展數據.這樣,促銷系統可能調用的是B包的擴展屬性,也有可能調用的是A包的基礎屬性.單品頁訪問A包、B包,調的集群是不一樣的.這樣存儲的容量就可以提高兩倍,系統的容災承載力也會提高.
商品原來是一個單表,后來慢慢發展成為了一個全量的商品系統,包括前端、后端整個一套的流程.異步異構完了之后,系統可進行各方面的優化,這樣系統的容量也會慢慢接近預期值.然后找到系統容量的最大值,如果超過這個值,整個系統就會宕機.那么,我們會做分流和限流,來保證系統的可用性.否則,這種大流量系統一旦倒下去,需要很長的時間才能恢復正常,會帶來很大的損失.
分流限流
從Nginx,到Web層、業務邏輯層、數據邏輯層,就會分流限流,真正落到實際上的流量是很小的,這樣就會起到保護作用,不會讓后端的存儲出現崩潰.從前面開始,可能訪問價格或者購物車的時間是10毫秒,保證20臺的機器一分鐘的流量是一百萬、兩百萬.
如果是40臺機器的話,承載能力會很強,會透過Java的服務,壓倒存儲,這樣會引發更大的問題,龐大存儲一旦出現問題很難一下恢復.如果從前面開始一層一層往下限,就可以起到保護底層的作用.中間層出問題比較容易處理,如Web層,限流會消耗很多CPU,會一步步加入更多機器,這樣就能夠解決這個問題.
我們需要降級分流限流.
下面結合秒殺系統來講講如何限流分流.2014年才產生秒殺系統.當時,在同一時刻可能有1500萬人預約搶一件商品,搶到系統不能訪問.后端服務都沒有出現這些問題,有的服務費不能正常展現.后來就專為搶購設計了一個秒殺系統.正常情況下,有大批量用戶需要在同一時間訪問系統,那么就從系統結構上分出去這些流量.秒殺系統盡量不影響主流層的入口,這樣就分離出來一部分數據.
接下來講講促銷和價格.主力調用價格的服務主要在促銷引擎,限流主要是通過購物車服務,購物車到促銷引擎又會限流,促銷引擎里面會有令牌.比如,有5000個庫存,發50萬個令牌到前端去,肯定這5000個庫存會被搶完,不可能再把其他服務的量打到后面,這樣會保護促銷引擎,這是一種總令牌模式的保護.后面的分流性能,會分集群式、重要程度去做.
另外,一些廣告的價格服務,我們會優先降級,如果出問題的話會限制.另外,有一部分刷引擎刷價格服務的數據,正常情況下是保證它正常使用,但是一旦出現問題,我們會直接把它降級,這樣就保護了真實用戶的最好體驗,而不是直接清除程序的應用.
容災降級
每次雙11活動,我們會做很多的容災和降級,有多中心交易、機房容災、業務容災等各種緯度的容災.大概統計了一下做過的一些容災方案.
首先是網絡容災.前面說到SB中間件、域名解析,我們運維自己會做了核心交換機兩層專線.這是我們運維部做的一些網絡架構圖,兩邊相互容災的一個結構.有LVS、HA、域名及解析,只是單服務掛了,通過交換機,我們可以從一個機房切換到另一個機房,因為會做一些域名的解析和切換.
應用系統相互調用容災和降級:結算的容災和降級.應用系統大部分能夠降,比如庫存狀態.如果像優惠券這些不重要的服務,備注信息,可直接降級服務,不用去訪問它,直接提交就行.在提交訂單時候,首先我們會保證必要服務,這些服務都會有很多的保護措施.每個應用里面,應用級別、服務級別的容災,比如地址服務、庫存狀態容災可以直接先降級.到提交的時候,我們直接對庫存做限制.
應用內部的容災.庫存就是結算前面的系統應用的服務,再到細一層的我們的庫存服務,這是每一個服務的容災降級.從庫存狀態這邊的話,從網絡設備內層,有網絡容災降級.應用內部有對于預算服務的降級,預算服務會有預算庫存,原來是寫MySQL數據庫.
正常情況下,預算庫存是寫MASIC預算庫,當出現問題的時候,我們會異步堆列到本地機器,裝一個程序去承載這個異步MySQL數據的落地,然后再通過Work把它寫到MySQL服務里面.正常情況下,是雙寫MySQL、redis,當MySQL承載不住的時候,我們會把MySQL異步寫到里面.
這里面都會有開關系統去控制.當提交訂單產生變更的時候,才會把庫存狀態從這邊推到這個庫存狀態這邊,因為庫存狀態的調用量跟價格一樣很大.今年我們看到的最大調用量是一分鐘2600萬.
這樣不可能讓它直接回原到MySQL,跟直接庫存的現實存儲里面.通過預算系統把這個狀態從左邊算好,直接在推送過到真正的存儲,這樣就把這個存儲剝離出來,這也算一種異步異構,這樣我們會提升它的容量.
這是原來的結構,就是redis直接同步,然后直接訪問.現在把它改成是,直接讓左邊的預算服務去推送到狀態服務里面.
監控
最后主要就是監控系統,我們運維提供了網絡監控、機器監控.
網絡監控包括我們看到的SBR,以及一些專線網絡監控,如交換機、柜頂交換機、核心交換機的監控.
接下來是應用的系統監控.機器監控有CPU、磁盤、網絡、IO等各方面系統的監控.業務緯度的監控,有訂單量、登陸量、注冊量等的監控.京東機房微屏專線的一個網絡平臺的監控,里面有很多專線,它們相互之間的流量是怎么樣?圖中是我們監控系統,是機器之間的監控,包括機器直接對應的交換機、前面的柜機交換機等的網絡監控等.
這是應用系統里面的方法監控,后面是業務級別的監控.訂單級別的包括注冊量、庫存、域站,或者區域的訂單、金額、調用量的監控都會在這里體現.真正到大促的時候,不可能經常去操作我們的系統,去修改它的配置.正常情況下都是去查看這些監控系統.
2012年之后,監控系統一點一點積累起來.當量越來越大,機器資源越來越多之后,這些監控都會直接影響正常服務,服務用戶的質量會下降,可能20臺機器宕了一臺機器,不會影響全部效果.所以,監控的精準性是一步步慢慢提高的.
文:楊超
文章出處:InfoQ
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4460.html