海淘平臺架構實踐
來自: http://toutiao.com/news/6247787727907979778/
1引言
隨著互聯網的發展,電子商務在全社會的深入普及,中國網購用戶強大的消費能力已經不止滿足于天貓、京東、淘寶等購物平臺。據相關報道,目前國內中產階級人數已過億。其中一批懂英文或日文的先行者,通過雙幣或多幣種信用卡,直接在國外電商站點上購物,直郵或者通過海外轉運公司將商品運輸回來,也就是所謂的“海淘”。海淘族最初的發展壯大,還得力于一批海外代購客的大力宣傳,通過收取服務費以及國內國外商品的價格差賺的盆滿缽滿。
從2012年開始,涌現出一大批海淘平臺(也屬于跨境電商)創業潮,專門搶奪這3千萬海淘用戶群體,例如:洋碼頭,蜜淘、麥芽寶貝、辣媽幫、小紅書等。2015年天貓、京東、唯品會等各大電商巨頭更是紛紛加入海外購頻道,一時綠海變紅海,好不熱鬧。
本文旨在從技術的角度,來探討海淘平臺建設中的一些問題和經驗。
2業務背景
雖說個人可以直接到國外網站購物,但畢竟有些門檻。一是二三線城市,多幣種信用卡申請有限制;二是語言障礙,即使英文略懂,也不敢貿然下單,還有日文、德文、法文等站點;三是大部分海外購物站點并不支持直郵中國,需要借助于轉運公司,到轉運公司的服務站點申請帳號,進行商品預報及付費等一系列處理。整個流程下來,周期短則半月多則數月,一般人都望而卻步了。
海淘平臺的出現,正是為了解決上面的痛點。用戶可以直接在平臺上瀏覽中文商品介紹,像在國內京東、天貓上一樣的購物流程,使用支付寶或銀聯卡進行付款,無須關注后續轉運細節操作。由海淘平臺來提供一站式翻譯、外幣支付、物流轉運和售后服務。

3整體架構


1) 接入層用于為PC瀏覽器,手機瀏覽器,原生APP應用提供后端Web服務。
2) 業務服務層用于為用戶提供注冊、登錄認證、商品瀏覽、加入購物車、提交訂單、支付、自動下單、商品優惠爆料爬取等業務相關的服務。
3) 基礎服務層用于提供短信發送、郵件收發、全文檢索、圖片存儲與讀取、消息通訊、日志集中存儲與讀取、分布式緩存等業務相關度低的服務。
4) 數據存儲層用于對結構化數據與文件數據的存儲。
4網絡部署



1) CDN網絡用來發布商品圖片、JS、CSS、HTML等靜態資源。
2) Nginx一主一從,保障高可用,提供靜態資源緩存和反向代理服務。
3) Web應用中的會話信息集中存放到Memcached中,支持Non-sticky會話。
4) 商品信息、評論信息、用戶屬性等業務信息緩存到Redis中。
5) 消息服務用于內部子系統間事件通知,業務消息通訊。
6) 數據庫主從復制,基于LVS實現高可用。
5存在問題點
由于項目周期短,產品不停迭代新功能,以及技術人員水平有限,系統依然存在不少弊端,主要體現在以下幾點:
5.1數據集中在單個數據庫,難以擴展
商品數據、用戶數據、訂單數據以及基礎數據全部表在一個數據庫實例中,核心數據與其它數據沒有分開來,無法根據業務系統負載量來將訪問壓力分攤。運營支撐系統與網站應用共用數據庫表,一旦后臺子系統程序出現bug,數據庫負載加重或鎖表,直接影響前端用戶的訪問。
5.2核心業務代碼未封裝,難以管理
商品信息的編輯入口太多,沒有統一的商品管理接口,各個業務模塊直接訪問數據庫,難以維護商品緩存的一致性。一旦開發新功能,容易顧此失彼,維護成本加大。生成訂單的邏輯,分散在網站、H5、APP,計算訂單金額的邏輯,由于開發人員各搞各的一套,容易出現漏洞以及不一致的情況。
5.3開發人員過度設計,垃圾代碼多
過度設計,人為地制造問題。為了支持多視圖模版,蹩腳的插件式Web集成,非標準化的Maven工程結構,DAO層重復造輪子等等。同樣功能的代碼存在好幾份,難以維護。
5.4濫用表關聯查詢,濫設計數據庫表
數據庫表數量膨脹過快,兩百張表里面核心庫表不足20個。應用程序代碼中功能實現過度依賴多表關聯查詢,有些基礎數據完全可以在緩存中讀取。數據庫表命名不規范,復用性差。有些業務場景,數據完全不需要持久化到數據庫中,可以采用Redis、MongoDB等來替代。
6架構演進
為了解決上述問題,同時隨著業務的運營發展,日PV量很可能達到千萬級,不得不對架構進行重構優化。考慮從以下幾個方面著手:
6.1核心業務服務化
引入分布式服務注冊與發現框架,遠程調用服務,請求應答參數需要序列化與反序列化,都會增加開發與維護成本。因此先將核心業務服務化,設計成無狀態的應用,便于負載加大時動態擴容。
1) 用戶注冊、登錄、用戶信息查詢封裝成用戶服務。
2) 商品信息的新增、編輯、上下架、價格更新、重量更新、SKU屬性更新封裝成商品服務。對商品及SKU信息的緩存維護在該服務內部集中管理起來。
3) 加入購物車、刪除購物車、購買數量更新、收貨人地址更新、提交訂單、計算訂單價格、更新訂單狀態封裝成購物車服務和訂單服務。
6.2按照業務垂直分庫
將單個數據庫切分成多個數據庫:用戶庫、商品庫、訂單庫、基礎數據庫、營銷活動庫、物流庫、文章資訊庫、綜合數據庫、日志庫。其中用戶庫、商品庫和訂單庫對高可用要求最高,商品庫和日志庫的存儲容量要求最高。
6.3按業務拆分服務組件
目前的代碼中按照分層理論一刀切的痕跡過重,切分粒度太大,體現不出按照業務來劃分組件的設計思想。這樣的后果就是封裝性差,業務上無法復用代碼。同時新增功能時誰都可以改動已有的代碼,容易引入新bug造成原有功能的不穩定。接下來需要對代碼進行重構,拆分成不同的業務組件,各個組件對外提供訪問服務接口,對內管理數據持久化狀態和緩存更新。
6.4數據庫一主多從
目前一主一從的方式,雖然保證了高可用性,但是當發生故障時(例如從庫宕機時)無法保證讀寫分離的可用性。實際應用中,讀數據的場景遠遠大于寫數據的場景。因此后面考慮數據庫一主多從(3個以上)的配置,同時保障高可用和讀寫分離持續可用性。
7那些趟過的坑
7.1商品信息從哪里來?
數以萬計的商品量,數十上百萬的SKU,作為一個創業公司錢少人少,是不可能有那么大的運營團隊去人工編輯錄入的。
沒錯,我們就是用爬蟲去國外網站上下載。技術宅嗖嗖嗖一天功夫爬蟲程序寫好了,一個站點的商品信息開始下載了。第二天早上過來一看,怎么只有幾千件商品這么少?趕快查看日志,診斷定位,原來被對方站點屏蔽了。不能請求太頻繁,同一個IP不能訪問太長時間,圖片下載過慢,國內IP無法訪問到墻外的世界,隔三差五原站點改版換樣式。什么,圖形驗證碼?OMG,美亞服務端能分析出來你不是真人在訪問!你屏蔽,我就換IP,封封封,換換換。
費了九牛二虎之力,商品信息爬下來了;運營說,全都是英文的,日文的,他們現在的人力配置,翻譯完需要到猴年馬月。翻譯慢,找百度翻譯,谷歌翻譯啊,So easy!結果程序一運行,發現翻譯結果真垃圾啊,根本就不是在說人話,比沒翻譯時的效果還差。終于有一天,放下了自尊,抄同行的啊,直接爬取別人編輯好的中文商品信息。終于,如此這般,總算有了第一批冷啟動的一兩萬件商品。
那么問題來了,原站點商品價格一直在變化啊,SKU一時有一時沒有,怎么辦?用戶下了單,結果原站點漲價50%,要不要給用戶下單,還是退錢?呃,我們還需要開發一套商品信息同步系統,每隔5分鐘獲取最新的價格和SKU信息。即便你5秒更新一次,就是那么巧,用戶下單后,商品漲!價!了!運營同學跑過來,怎么辦,有沒辦法解決?思量好久,最后和老板說,用戶提交訂單的時候我們去原站點再檢查比對一次,但是這之后的價格波動,只能由我們平臺認栽了(沒錯,賠錢也要給用戶下單。電商行業,用戶就是上帝)。
至于每5分鐘同步一個商品的價格和SKU信息的成本,呃,這是個秘密。只能說公司預算少,根本做不到!!!后來,我們只將熱門推薦商品每半小時更新一次價格和SKU信息,其它大量商品,在用戶瀏覽商品頁點擊SKU時去觸發后臺異步更新單個SKU的信息和價格,在預算成本和用戶體驗之間做了個折衷。當然,這個方案并不高明,但是很有效。
7.2用戶的訂單怎么下?
用戶不下單,我們愁啊。是不是產品視覺沒有沖擊力,還是商品不是用戶喜歡的,價格不吸引人,還是推廣投入不足流量沒有做上去?用戶下了單,我們也愁啊,是喜極而泣的煩惱。信用卡額度不夠了怎么辦?什么,美亞又砍單啦?帳號怎么又登錄不上去啦?如此這般,愁啊,沒有一天安生過。運營說,我們可以找黃牛來解決,沒錯,就是專業代購。他們有信用卡,有帳號,有固定IP,他們有強大的協同作戰扣扣群組織。每天幾十上百的訂單,他們輕松就能處理完,前提是平臺給傭金!到最后等于平臺成了個只虧本不盈利,賠錢賺吆喝的主。老板說,這樣下去不行,我們得有自己的下單團隊。
沒錯,技術宅又頂上了。噌噌噌兩周功夫,一套自動化下單系統開發出來,愉快地運行起來,心想這下該給老板節省不少人力開銷。運行了一段時間,感覺良好。且慢,怎么一個訂單下了兩次!!原來一個用戶訂單,包含了多個子訂單,分別對應幾個國外站點,程序居然注冊了多個轉運公司帳號。思前想后,又設計了一套基于數據庫的分布式鎖,同一時刻同一用戶只有一個子訂單能被處理。原以為萬事大吉了,結果網絡延遲,被美亞屏蔽各種砍單,各種原因分分鐘讓程序不工作。為此我們開發了一套監控系統,將下單過程中的每個步驟截屏,記錄下各個步驟的執行狀態,耗費時間,進而優化下單系統。后面,我們又采用人工下單系統與自動下單系統相結合的方式,對于出錯訂單再進行回滾處理,重試自動下單,大大提高了下單成功率(除了美亞外,其它站點有70%以上成功率)。
7.3物流信息對接了然后呢?
物流信息接口主要用于向轉運公司預報包裹中的商品信息,包括數量、品牌、名稱、金額、類別,方便轉運公司進行運輸處理以及海關清關,同時能時刻查詢到包裹最新的處理情況,以展示給用戶物流追蹤軌跡。原本以為信息對接后,就無須人工干預了,實際業務運行一段時間后,用戶打客服電話來查詢包裹物流信息,才知道物流公司接口根本查詢不了最新的物流信息。海淘屬于最近幾年才興盛起來的業務,轉運公司的IT系統也是剛剛建立,漏洞百出。
無奈之下,人工拿著物流跟蹤號(TrackingNo)每天去對方站點逐個掃一遍。人工維護更新物流信息的成本實在太高,效率也低。后面改為程序每天去對方站點掃一遍,也常常是包裹五六天拿不到物流更新。還有些物流公司根本沒有接口提供,只能人工登錄后,肉眼比對更新,效率極差。物流信息更新慢,運輸周期長(短則一周,長則兩個月都有)一直是海淘用戶的痛點。國內物流業發達,一般海關清關完,包裹兩三天就能發到用戶手中。國內物流跟蹤簡單,用戶只要拿到運單號到網上搜索都可以看到明細。
7.4訂單金額到底怎么算?
用戶購買的商品數量,乘以單價,再累加起來,不就是訂單金額嗎?在海淘業務中,計算規則要復雜得多。訂單金額除了商品本身的費用,還包含境外運費,轉運公司收取的運費(轉運費),平臺收的服務費,再減去各種營銷活動的優惠部分。商品單價受原網站影響,同時匯率波動也會產生影響,需要結算時換算成人民幣價格。境外運費和轉運費,一般是美元或者日元單位,也有些轉運公司直接人民幣價格結算。平臺收取的服務費,按照商品總金額乘以一定系數來計算。優惠部分計算規則更加復雜,有全場滿減優惠,專題活動優惠券,特殊種類商品優惠券,還要考慮各種運營規則。例如:優惠券不能疊加,全場滿減與優惠券可疊加,優惠券活動下線等等。訂單金額的算法部分,是最為復雜,也是平臺安全性要求最高的部分。稍微有個漏洞,就能被黑客以及一大波職業擼bug單的買手利用,造成很大的損失,任重道遠。
7.5用戶和商品如何匹配上?
平臺冷啟動時,肯定是先有第一批商品信息,才能有內容讓用戶瀏覽。用戶來了后,發現沒有找到自己感興趣的商品,怎么辦?這是很可能發生的事情,特別是商品庫品種有限的時候。運營人員根據掌握的推廣渠道不同,可能導入過來的用戶是數碼宅男,也可能是時尚女性,如果呈現的商品與用戶的需求不匹配,訂單轉化就會很低,用戶流失率就會很高。
最好是有上百萬數量的商品庫,各個主要品類的熱門商品都覆蓋到。用戶通過多級分類打開或者直接在搜索框輸入商品關鍵字就能找到自己所需要的商品。但是上百萬的商品庫,是海量的工作量積累而成,需要投入很多人力成本,不是小創業團隊能承受。后來想到兩個解決辦法,一是從同類導購網站、海淘網站去爬取;二是開發一鍵購功能,讓用戶主動輸入該商品在原網站上的鏈接地址后即時爬取。其實可以讓運營想想辦法,找一些返利平臺、轉運公司以及導購平臺甚至買手團隊拿到一定的歷史數據,會更有價值。有了一定數量的商品后,運營就可以搞些專題活動,針對不同的品類,不同的目標用戶群體,在合適的渠道上去推廣。
8小結
做這個項目給我最大的啟發就是,技術不是唯一解決問題的辦法。深入與產品經理和運營人員溝通,以實際業務需求為導向,不同的場景采用不同的設計方案;用最直接有效的技術手段,滿足業務功能和質量需求,同時又預留一定的擴展性,這才是架構師該做的事情。架構設計中簡單就是美,越是簡單的設計越易于維護。