當當11.11:促銷系統與交易系統的重構實踐
電商行業近年來發展勢頭迅猛,諸多巨頭成功上市,業務模式不斷升級,促銷手段花樣百出。雙十一成為各路電商運營能力的年度大考,同時也是對電商技術平臺能力的極限測試,每年進行了重大改版升級的系統只有經過雙十一的槍林彈雨才能浴火重生。
在當當,2015年的雙11,面臨考驗的是促銷系統和交易系統,兩者都是電商體系的核心組成部分。此次雙11專題,InfoQ特別邀請 EGO會員 、當當架構部總監史海峰先生,為大家講述當當雙11背后的技術故事。
另,ArchSummit全球架構師峰會北京站將于2015年12月18日~19日在北京國際會議中心召開,大會設置了《 揭秘雙十一背后的技術較量 》專題來深入解讀雙十一背后的技術故事,歡迎關注。
促銷系統重構
如今大規模促銷已經成為大大小小的電商平臺及入駐商家運營的常態。隨著業務的復雜化、運營的精細化,以及品類、平臺、渠道的不斷豐富,各種新的促銷形式也層出不窮,貫穿從商品展示、搜索、購買、支付等整個流程,電商對于精細化、精準化促銷運營的需求也越來越強烈。
一次促銷活動幾十萬商品,一天之內幾十個、上百個促銷活動已是家常便飯,至于入駐商家的常態促銷更是不勝枚舉。雙十一期間,電商平臺和商家更是會使出渾身解數,火力全開,無品不促銷。
促銷規則支持分時段設置,多個活動能夠疊加,促銷系統中的數據量甚至會超過商品信息系統,而且促銷內容會根據執行效果快速調整,這些都對促銷系統提出了更高的要求,促銷系統越強大,促銷活動才能玩得越瘋狂。
我們在重構前面臨的狀況,是促銷模型比較陳舊、擴展性差,促銷系統成熟度低、與其他系統耦合嚴重,新增一個促銷類型可能牽動從單品展示、搜索、推 薦、購物車、交易、訂單、退換貨、庫存、價格、促銷自身等一系列產品線的變更。因此,促銷系統的重構勢在必行,數據模型與運營的貼合度決定的擴展性、靈活 性,系統解耦和更強大的數據處理能力,是核心改進點。
最基本的促銷模型很簡單,如下圖:
在當當,有一些“類促銷”業務,從廣義上可以歸入促銷范疇,但業務與數據均不屬于促銷系統,在設計中,我們考慮將這類業務逐漸回收;另外,促銷系統能不能承擔一些營銷的功能?帶著這兩點考慮,在促銷基礎上進一步抽象出活動模型。
什么是活動?我們認為任何一個有時間范圍的事件/動作均可稱為活動,活動則抽象為三要素組成:基礎信息、維度(條件)、工具(動作)
例如,在11月1日10:00-12:00在第一會議室開雙十一準備會,討論雙十一各系統需要準備的事項,需要各系統負責人參加;那么這個活動的 基礎信息包括時間(11月1日10:00-12:00)、主題(雙十一準備會),維度包括地點(第一會議室)、與會人員(各系統負責人),工具(動作)包 括議題以及討論本身。
那么推而廣之,理論上,只要有相應的工具對接,可以用這個極簡的活動模型,去管理任何一類活動,這樣模型就變為了兩層:
實際業務中我們遇到過的一些關于促銷計算單元的頭疼問題。買了一堆商品,到底哪幾個應該作為一組計算條件和優惠,在促銷疊加的場景這一點顯得更為 復雜。所以我們引入作用域來定義這個計算單元的范圍。例如常規的限時搶促銷,每個SKU有自己的價格,那么SKU就是這個促銷的計算單元,也就是促銷的作 用域;例如第二件5折,可能會按SPU來做,你買一個紅的一個藍的,還是能享受促銷,那么SPU成為了這個促銷的計算單元;諸如此類,現有及未來可擴展的 還有店鋪、品類、品牌等等。簡言之,這個作用域成為促銷計算引擎進行計算單元分組的依據。于是模型又變成了這樣:
舉個例子,我們要在11月11日11:00-12:00針對IT技術類圖書進行滿200元減100元促銷,購買過此類圖書的客戶每本書每人限購一 冊。那么這個活動的基礎信息包括時間(11月11日11:00-12:00)、主題(程序猿光棍節福利);維度包括商品品類(IT技術)、用戶范圍(購買 過此類圖書的客戶);工具是滿額減促銷、以金額滿200元為條件、減100元為優惠,此外還有限購策略為限購1本,作用域為參與活動的所有商品;
可能這里會引發困擾,基礎信息的時間為何不能算做時間維度?維度也定義了一些限制條件,那和促銷工具模型里的條件有什么區別?時間之所以不歸入維 度,是基于前面對活動的定義,時間范圍是必須的,而維度是可選的;促銷模型中的條件只對于促銷工具有效和有意義,而維度則有更廣泛的普適性,例如平臺、渠 道、地區、用戶、商品等,與工具是什么并無關系。
基礎模型定型之后,我們開始著手解耦方面的設計:
首先是系統交互解耦,將直讀DB和存儲冗余促銷數據的系統修改為調用服務及監聽MQ;然后是邏輯回收,包括將促銷校驗與促銷計算提取為交易服務, 將原先由購物車、交易系統自行處理的促銷邏輯回收;從業務上,將促銷工具的屬性進行提取,諸如類型枚舉、促銷標簽、限購策略、庫存策略等,以期外圍系統盡 量少的關注促銷類型,通過促銷ID拿到所需信息直接使用;未來則關注于業務層面的梳理與整合,逐步回收適用于活動模型的其他“類促銷”業務。
系統解耦后,促銷系統需要提供各系統所需要的服務,必須具備更強大的數據處理能力和更好的性能表現。應用架構實現上,從前端頁面到后端邏輯,盡量 避免有邏輯與促銷類型直接綁定,全部以插件化方式與促銷模型對接,完全根據促銷類型的配置進行組裝。針對不同維度、條件、優惠、促銷屬性,定制頁面模板及 業務邏輯,使得新增一種促銷類型(在已有維度、條件、優惠下)僅需配置即可完成。
促銷系統的查詢服務需要同時為多個系統提供數據,對TPS要求很高,同時促銷的時效性又要求很高的實時性。我們采用的方式是在數據庫前加Redis緩存,提高響應速度,同時監聽MQ,根據事件清理相應的緩存數據。
這種設計方案也有一些可能的坑,例如Redis緩存雖然減輕了DB壓力,但對于計算密集型應用并未減輕應用服務器壓力,IO沒有節省還增加了序列化的開銷;事件驅動清理緩存在讀寫分離場景下,有可能比主從同步更快,造成緩存數據錯誤。這也是具體應用中需要注意的地方。
促銷系統重構上線后,使多渠道(終端)、多區域化營銷成為簡單易行的配置操作,顯著提高了當當運營能力,當當雙十一呈現出更多的想象空間。
交易系統重構
交易系統是客戶購物流程中最重要的環節,主要任務是完成購物車中商品信息獲取、拆單、促銷計算、配貨計算、運費計算、非現金支付的使用以及生成訂 單等操作,聚合各方面業務邏輯,計算非常復雜,而且響應速度影響購買轉化率,一旦出現故障,直接影響營業收入,可謂電商最為敏感的核心系統,決定對其進行 重構需要極大的魄力。
當當原有交易系統采用.NET技術框架,運行多年,很好的支撐了購買流程,但是弊端逐漸顯露。首先是技術體系屬于微軟系,每年要花費大量成本購買服務;其次是隨著業務需求的不斷疊加,其結構及可維護性逐年下降,尤其是眾多小版本結算的存在,使得功能擴展異常艱難。
基于以上因素,交易系統團隊在2014年底啟動重構項目,2015年10月底新老版本完成切換。此次重構耗費約1500人天,重構代碼17萬行,全部切換至Java開源技術架構,為公司節約大量成本,并進行了架構優化,整體性能平均提升25%。
交易系統業務主流程圖如下:
交易系統重構引入了許多業界成熟的技術實現方案,主要有以下幾點:
1. 集中化配置
集中化配置方式,一點配置,所有實例可見,更易于管理,而且配置修改后,通過熱加載方式,立刻生效,快速便捷。而原有交易系統修改配置后,必須重啟系統才能生效。
2. 頁面緩存技術
用戶請求一次交易結算頁面,會調用各種后端服務,而由于邏輯的復雜性,每次服務調用都會調用訂單計算大流程,導致頁面刷新緩慢。新交易系統將大流程計算結果進行緩存,在一次頁面請求范圍內,后續調用直接用緩存結果,極大提高了頁面的刷新速度。
3. 小版本合并
由于歷史原因,交易系統存在很多版本的結算邏輯。最常用的是統一結算,還有一些特殊類型的結算,如秒殺、一鍵下單、補發貨等等,邏輯與統一結算稍 有不同,統稱為小版本結算。因小版本結算與統一結算大部分邏輯相同,因此新交易系統將二者合到了一起,共享基礎邏輯,而不同的邏輯則單獨處理,極大提高了 可維護性。
4. 灰度發布、無縫切換
借助了Nginx在運行狀態下可以reload配置,而基本不影響對外提供服務的能力。每個Nginx負載兩臺應用服務器,灰度發布時,將Nginx配置更改為只負載一臺應用服務器,即可對另一臺進行部署。用戶請求不會導向正在部署中的服務器,從而不影響用戶下單。
(點擊放大圖像)
5. 并行比對
交易系統重構后,盡管進行了大量的測試,仍不能放心部署上線。因為交易系統的計算都和金錢有關,必須慎之又慎,我們提出了線上并行比對方案,根據老交易系統比對新交易,保證其邏輯正確。原理如下:
1) 用戶請求到達老交易系統
2) 根據條件將部分請求數據復制,發送至調用mock服務的新交易系統
3) 新老交易同時計算,結果存入各自的數據庫,但只有老交易結果對用戶公開
4) 對新老計算結果進行比對
這樣,既實現了比對目的,又不會影響線上環境。
6. 分流
比對之后,新交易系統也不能立即全面上線,那樣可能有巨大風險。我們開發了分流功能,按照用戶id來分流,正式分流前,先使用測試白名單中的用戶進行預驗證。預驗證通過后,再按比例由低至高逐步切換。
7. Web服務器按需伸縮
基于前面所講的灰度發布技術,新交易系統很容易做到按需伸縮。正常情況下,每個Nginx負載兩臺應用服務器。雙十一需要擴容時,將待擴服務器ip地址加入Nginx配置,重新reload,該Nginx就可負載更多臺應用服務器了。
交易系統上線后為備戰雙十一,確保萬無一失,利用老交易系統還未下線的條件進行了線上壓測。為達到最準確的測試效果,且不影響正常系統運行,進行了以下的準備:
1. 測試環境、數據與生產環境一致
在準備測試環境方面,為了保證測試結果更接近真實結果,本次測試使用線上環境,通過大量測試賬號對線上的真實促銷商品進行測試,這樣也對新交易系統所依賴的各系統服務做了檢驗。
2. 線上業務運行保障
測試階段線上的請求切到老交易系統,壓測請求發送到新交易系統,使測試和生產業務進行分離,保證了各自服務器資源的獨立性。在應用服務器層面使測試過程不會影響到線上正常交易。
3. 攔截訂單回收庫存
由于使用線上環境測試,需要對測試訂單進行攔截,避免進入生產流程,并回收占用的庫存,使商品不會耗盡庫存,采用的方法是在自動審單系統中將測試 賬戶加入黑名單,測試訂單提交后會被攔截,然后取消訂單釋放庫存。為防止測試過程占用了商品的全部庫存而影響線上銷售,測試商品池基數很大,并且過濾掉了 庫存數量較少的商品,在執行測試過程中控制每個商品的使用次數,保證可銷售庫存占用在安全范圍內。
4. 惡意用戶策略控制
因為在交易下單過程中包含惡意用戶判定的策略,會對用戶進行隔離,禁止連續大量下單,線上壓測時根據實際情況短時間內調整了安全級別,保證訂單成功率。
經過多輪線上壓測,新交易系統的高可用性得到驗證,得到了實際性能指標,并根據雙十一流量估算進行了擴容部署,將以嶄新的面貌為廣大客戶提供穩定可靠便捷的網購服務。