挑戰(zhàn)空中加油——1號(hào)店B2C電商系統(tǒng)演進(jìn)之路作者
韓軍 發(fā)布于 2011年11月28日
領(lǐng)域
架構(gòu) & 設(shè)計(jì)主題
互聯(lián)網(wǎng)標(biāo)簽
電子商務(wù) ,
《架構(gòu)師》月刊分享 |
一、 面臨的挑戰(zhàn)
發(fā)展速度快:每年近十倍的業(yè)務(wù)增長(zhǎng)。既要及時(shí)響應(yīng)業(yè)務(wù)發(fā)展的新需求,又要對(duì)系統(tǒng)平滑地進(jìn)行技術(shù)升級(jí)重構(gòu),其難度堪比飛機(jī)空中加油。
系統(tǒng)越來(lái)越復(fù)雜:多渠道: 1號(hào)店、掌上商城、第三方商城、多個(gè)分站
產(chǎn)品多樣: 既有各類百貨,也有各種虛擬票劵,還有機(jī)票充值等
多種經(jīng)營(yíng)模式: 有自營(yíng)也有代售,有自配送也有第三方配送
多部門協(xié)同:采購(gòu)、市場(chǎng)、銷售、倉(cāng)儲(chǔ)、配送、客服等多部門需高效協(xié)同。
更智能化:隨著業(yè)務(wù)和系統(tǒng)的復(fù)雜,各部門完全人工的運(yùn)營(yíng)決策變得十分低效,需要系統(tǒng)更加智能化。
流量越來(lái)越大:流量每年增長(zhǎng)10倍。
二、演進(jìn)的策略
新舊兼容,平滑升級(jí):我們?cè)趯?shí)施任何技術(shù)升級(jí)時(shí),首要強(qiáng)調(diào)的就是新系統(tǒng)要盡量兼容舊系統(tǒng),以支持平滑升級(jí)。完全新的架構(gòu)看似很吸引人,比較容易開發(fā),但是不兼容原來(lái)的系統(tǒng)可能使得新系統(tǒng)風(fēng)險(xiǎn)非常大。所以1號(hào)店采用兼容的方式,滾動(dòng)開發(fā),把架構(gòu)從原來(lái)的合成一團(tuán)的小系統(tǒng)方式逐步改變?yōu)樽酉到y(tǒng)獨(dú)立,多數(shù)據(jù)庫(kù)的模式。這好比一邊高速飛行,一邊加油。
系統(tǒng)拆分:解決系統(tǒng)復(fù)雜性的唯一方法是分解。同時(shí)拆分后系統(tǒng)也使各自進(jìn)行新的技術(shù)改造變得相對(duì)平滑。我們從終端渠道、業(yè)務(wù)邏輯、使用部門等多個(gè)維度進(jìn)行了系統(tǒng)拆分。 例如:
相關(guān)廠商內(nèi)容
Sybase在線課堂:ASE15.7——SYBASE數(shù)據(jù)管理的革新送給光棍節(jié)的促銷,電子商務(wù)的背后—《架構(gòu)師》11月刊免費(fèi)下載!適當(dāng)放棄一致性:在一些實(shí)時(shí)性要求不高的場(chǎng)合,我們適當(dāng)放棄一致性要求。這樣就可以充分利用多種手段來(lái)提高系統(tǒng)吞吐量,例如頁(yè)面緩存、分布式數(shù)據(jù)緩存、數(shù)據(jù)庫(kù)讀寫分離、查詢數(shù)據(jù)搜索索引化。
系統(tǒng)共用組件Service化:隨著系統(tǒng)的分拆,各子系統(tǒng)間的重復(fù)代碼越來(lái)越多,增加了很多不必要的維護(hù)成本。為提高代碼的復(fù)用,降低維護(hù)成本,我們將多個(gè)子系統(tǒng)都需要用到的業(yè)務(wù)組件,進(jìn)行了Service化。例如:
中間件的研發(fā)使用:隨著子系統(tǒng)和Service的增多,面臨很多共同的技術(shù)性挑戰(zhàn)。為降低應(yīng)用系統(tǒng)人員的開發(fā)難度,我們?cè)谝恍╅_源系統(tǒng)的基礎(chǔ)上,研發(fā)了多個(gè)適應(yīng)我們的中間件系統(tǒng)。例如:ESB平臺(tái)(支持遠(yuǎn)程服務(wù)、異步消息)、分布式緩存、數(shù)據(jù)訪問層等。大大簡(jiǎn)化了應(yīng)用系統(tǒng)的開發(fā)。使用中間件后的總體示意圖如下:
系統(tǒng)自動(dòng)化:為進(jìn)一步提高運(yùn)營(yíng)效率,我們采用了很多自動(dòng)化的設(shè)計(jì)理念,盡量減少人工配置的需要。例如:根據(jù)比價(jià)系統(tǒng)和策略自動(dòng)調(diào)整商品價(jià)格,根據(jù)投放效果和策略自動(dòng)調(diào)整廣告投放,根據(jù)庫(kù)存和銷售預(yù)測(cè)自動(dòng)安排采購(gòu)等。
三、 經(jīng)典案例:數(shù)據(jù)訪問層YhdDAL 1.0設(shè)計(jì)與實(shí)施
1) 實(shí)施前舊系統(tǒng)狀態(tài)與結(jié)構(gòu):
整體已拆分有多個(gè)子系統(tǒng)和多個(gè)數(shù)據(jù)庫(kù)。
每個(gè)應(yīng)用系統(tǒng)與多個(gè)數(shù)據(jù)庫(kù)直連,使用iBatis進(jìn)行O/R Mapping。
各應(yīng)用系統(tǒng)代碼中,使用MemCached服務(wù)器進(jìn)行數(shù)據(jù)緩存。
2) 舊系統(tǒng)面臨的問題:
數(shù)據(jù)庫(kù)連接數(shù)大,數(shù)據(jù)庫(kù)服務(wù)器負(fù)擔(dān)重。
Cache代碼繁瑣: 本來(lái)一行代碼的事需要寫四五行。下面是典型的示例偽代碼:
result = getFromMemCached(key);if (result != null) return result;result = getFromDatabase(...);writeMemCached(key, timeout);return result;Cache 管理困難: 失效時(shí)間代碼分散,不便管理。不同系統(tǒng)還容易key沖突。
數(shù)據(jù)分庫(kù)和讀寫分離代碼繁瑣,某庫(kù)故障時(shí)無(wú)法自動(dòng)切換到可用庫(kù)上。
系統(tǒng)Service化改造困難: 原Web層與Dao層代碼耦合度高,不易實(shí)現(xiàn)Service化。拆分粒度太細(xì)連接數(shù)上升和故障概率增加,粒度太粗又效果不佳。
無(wú)法充分發(fā)揮Cache潛能:某個(gè)Cache項(xiàng)失效時(shí),因前端的并發(fā)性會(huì)導(dǎo)致多次數(shù)據(jù)庫(kù)請(qǐng)求。到期Cache無(wú)法延期使用,數(shù)據(jù)庫(kù)故障時(shí)應(yīng)用系統(tǒng)就立即故障。
3) 備選方案的優(yōu)缺點(diǎn):
基于iBatis本地?cái)U(kuò)展: 優(yōu)點(diǎn)是工作量小。缺點(diǎn)是連接數(shù)和Service化等問題無(wú)法很好解決。
基于jdbc驅(qū)動(dòng)的DAL:優(yōu)點(diǎn)是客戶端代碼兼容性好,原代碼改動(dòng)工作量小。缺點(diǎn)是實(shí)現(xiàn)一個(gè)完整的jdbc驅(qū)動(dòng)本身代價(jià)很高。
DAL服務(wù)化,接口自定義: 優(yōu)點(diǎn)是代碼可控性高,各項(xiàng)需求特性易實(shí)現(xiàn)。缺點(diǎn)是有一定的遷移成本。
4) YhdDAL 1.0設(shè)計(jì)方案:
引入DAL服務(wù)器。應(yīng)用系統(tǒng)僅訪問DAL服務(wù)器,DAL才連接數(shù)據(jù)庫(kù)。
客戶端與DAL采用成熟的遠(yuǎn)程調(diào)用協(xié)議,接口簡(jiǎn)化為一個(gè):
Object execute(functionName, parameters...)
參數(shù)和返回值一律采用Map或基本類型,必要時(shí)可在客戶端轉(zhuǎn)換為Java Bean
支持iBatis格式的sql腳本定義和字段映射,以降低iBatis代碼遷移成本。
DAL層支持JavaScript腳本語(yǔ)言編寫的類似存儲(chǔ)過程的計(jì)算代碼,簡(jiǎn)化業(yè)務(wù)層數(shù)據(jù)處理代碼實(shí)現(xiàn)。
因DAL服務(wù)器數(shù)量明顯小于應(yīng)用服務(wù)器數(shù)量,可有效減少數(shù)據(jù)庫(kù)連接總數(shù)。
DAL層封裝Cache處理機(jī)制,一方面簡(jiǎn)化應(yīng)用層代碼。另一方面可采取緩存主動(dòng)更新,失效延期等機(jī)制,充分發(fā)揮Cache潛能。
DAL層封裝分庫(kù)和讀寫分離處理機(jī)制,簡(jiǎn)化應(yīng)用層代碼。
參考數(shù)據(jù)庫(kù)存儲(chǔ)過程的設(shè)計(jì)思想,客戶端僅傳入過程名稱和參數(shù),DAL層計(jì)算完成后返回結(jié)果。有利于實(shí)現(xiàn)Service化。
大量簡(jiǎn)化應(yīng)用層代碼,很多簡(jiǎn)單的Sevice/Dao類可以完全省略。
1.0的緩存和負(fù)載均衡采用相對(duì)成熟簡(jiǎn)單方案,以降低風(fēng)險(xiǎn)。結(jié)構(gòu)圖如下:
5) 實(shí)施與升級(jí)過渡步驟:
實(shí)現(xiàn)DAL核心功能。進(jìn)行壓力測(cè)試,評(píng)估系統(tǒng)性能。
先對(duì)一個(gè)風(fēng)險(xiǎn)相對(duì)較小的應(yīng)用系統(tǒng)進(jìn)行改造,評(píng)估系統(tǒng)穩(wěn)定性和改造成本。
采用iBatis兼容模式,直接轉(zhuǎn)換遷移舊代碼。以快速將原有系統(tǒng)升級(jí)至新平臺(tái)。
采用新平臺(tái)的設(shè)計(jì)理念,如讀寫分離、Service化,進(jìn)行舊代碼改造。
擴(kuò)展DAL附加功能,如日志記錄、權(quán)限控制、緩存優(yōu)化、連接分組等。
通過一系列的方法與手段,1號(hào)店基本實(shí)現(xiàn)了從小系統(tǒng)向大系統(tǒng)演變,使得1號(hào)店的系統(tǒng)能夠支撐大量高并發(fā)的訪問,同時(shí)滿足了業(yè)務(wù)的需要。
關(guān)于作者
韓軍,1967年出生。1989年畢業(yè)于上海交通大學(xué)計(jì)算機(jī)系, Monash MBA
1號(hào)店的第一個(gè)員工,CTO, 設(shè)計(jì)并開發(fā)了1號(hào)店所有的系統(tǒng)
2004年,設(shè)計(jì)了 美國(guó)著名的比較購(gòu)物系統(tǒng) smarter.com
1999年加入51job,設(shè)計(jì)并開發(fā)了中國(guó)最為成功的工作網(wǎng)站與系統(tǒng)