五、詳情頁(yè)架構(gòu)設(shè)計(jì)原則

2018-02-24 15:49 更新

詳情頁(yè)架構(gòu)設(shè)計(jì)原則

數(shù)據(jù)閉環(huán)


?數(shù)據(jù)閉環(huán)即數(shù)據(jù)的自我管理,或者說(shuō)是數(shù)據(jù)都在自己系統(tǒng)里維護(hù),不依賴于任何其他系統(tǒng),去依賴化;這樣得到的好處就是別人抖動(dòng)跟我沒(méi)關(guān)系。

數(shù)據(jù)異構(gòu),是數(shù)據(jù)閉環(huán)的第一步,將各個(gè)依賴系統(tǒng)的數(shù)據(jù)拿過(guò)來(lái),按照自己的要求存儲(chǔ)起來(lái);

數(shù)據(jù)原子化,數(shù)據(jù)異構(gòu)的數(shù)據(jù)是原子化數(shù)據(jù),這樣未來(lái)我們可以對(duì)這些數(shù)據(jù)再加工再處理而響應(yīng)變化的需求;

數(shù)據(jù)聚合,將多個(gè)原子數(shù)據(jù)聚合為一個(gè)大JSON數(shù)據(jù),這樣前端展示只需要一次get,當(dāng)然要考慮系統(tǒng)架構(gòu),比如我們使用的Redis改造,Redis又是單線程系統(tǒng),我們需要部署更多的Redis來(lái)支持更高的并發(fā),另外存儲(chǔ)的值要盡可能的?。?/p>

數(shù)據(jù)存儲(chǔ),我們使用JIMDB,Redis加持久化存儲(chǔ)引擎,可以存儲(chǔ)超過(guò)內(nèi)存N倍的數(shù)據(jù)量,我們目前一些系統(tǒng)是Redis+LMDB引擎的存儲(chǔ),目前是配合SSD進(jìn)行存儲(chǔ);另外我們使用Hash Tag機(jī)制把相關(guān)的數(shù)據(jù)哈希到同一個(gè)分片,這樣mget時(shí)不需要跨分片合并。

我們目前的異構(gòu)數(shù)據(jù)時(shí)鍵值結(jié)構(gòu)的,用于按照商品維度查詢,還有一套異構(gòu)時(shí)關(guān)系結(jié)構(gòu)的用于關(guān)系查詢使用。

詳情頁(yè)架構(gòu)設(shè)計(jì)原則?/?數(shù)據(jù)維度化

對(duì)于數(shù)據(jù)應(yīng)該按照維度和作用進(jìn)行維度化,這樣可以分離存儲(chǔ),進(jìn)行更有效的存儲(chǔ)和使用。我們數(shù)據(jù)的維度比較簡(jiǎn)單:

1、商品基本信息,標(biāo)題、擴(kuò)展屬性、特殊屬性、圖片、顏色尺碼、規(guī)格參數(shù)等;

2、商品介紹信息,商品維度商家模板、商品介紹等;

3、非商品維度其他信息,分類信息、商家信息、店鋪信息、店鋪頭、品牌信息等;

4、商品維度其他信息(異步加載),價(jià)格、促銷、配送至、廣告詞、推薦配件、最佳組合等。?

拆分系統(tǒng)


?將系統(tǒng)拆分為多個(gè)子系統(tǒng)雖然增加了復(fù)雜性,但是可以得到更多的好處,比如數(shù)據(jù)異構(gòu)系統(tǒng)存儲(chǔ)的數(shù)據(jù)是原子化數(shù)據(jù),這樣可以按照一些維度對(duì)外提供服務(wù);而數(shù)據(jù)同步系統(tǒng)存儲(chǔ)的是聚合數(shù)據(jù),可以為前端展示提供高性能的讀取。而前端展示系統(tǒng)分離為商品詳情頁(yè)和商品介紹,可以減少相互影響;目前商品介紹系統(tǒng)還提供其他的一些服務(wù),比如全站異步頁(yè)腳服務(wù)。

Worker無(wú)狀態(tài)化+任務(wù)化?

1、數(shù)據(jù)異構(gòu)和數(shù)據(jù)同步Worker無(wú)狀態(tài)化設(shè)計(jì),這樣可以水平擴(kuò)展;

2、應(yīng)用雖然是無(wú)狀態(tài)化的,但是配置文件還是有狀態(tài)的,每個(gè)機(jī)房一套配置,這樣每個(gè)機(jī)房只讀取當(dāng)前機(jī)房數(shù)據(jù);

3、任務(wù)多隊(duì)列化,等待隊(duì)列、排重隊(duì)列、本地執(zhí)行隊(duì)列、失敗隊(duì)列;

4、隊(duì)列優(yōu)先級(jí)化,分為:普通隊(duì)列、刷數(shù)據(jù)隊(duì)列、高優(yōu)先級(jí)隊(duì)列;例如一些秒殺商品會(huì)走高優(yōu)先級(jí)隊(duì)列保證快速執(zhí)行;

5、副本隊(duì)列,當(dāng)上線后業(yè)務(wù)出現(xiàn)問(wèn)題時(shí),修正邏輯可以回放,從而修復(fù)數(shù)據(jù);可以按照比如固定大小隊(duì)列或者小時(shí)隊(duì)列設(shè)計(jì);

6、在設(shè)計(jì)消息時(shí),按照維度更新,比如商品信息變更和商品上下架分離,減少每次變更接口的調(diào)用量,通過(guò)聚合Worker去做聚合。

異步化+并發(fā)化

?我們系統(tǒng)大量使用異步化,通過(guò)異步化機(jī)制提升并發(fā)能力。首先我們使用了消息異步化?進(jìn)行系統(tǒng)解耦合,通過(guò)消息通知我變更,然后我再調(diào)用相應(yīng)接口獲取相關(guān)數(shù)據(jù);之前老系統(tǒng)使用同步推送機(jī)制,這種方式系統(tǒng)是緊耦合的,出問(wèn)題需要聯(lián)系各個(gè)負(fù)責(zé)人重新推送還要考慮失敗重試機(jī)制。數(shù)據(jù)更新異步化 ,更新緩存時(shí),同步調(diào)用服務(wù),然后異步更新緩存??刹⑿腥蝿?wù)并發(fā)化, 商品數(shù)據(jù)系統(tǒng)來(lái)源有多處,但是可以并發(fā)調(diào)用聚合,這樣本來(lái)串行需要1s的經(jīng)過(guò)這種方式我們提升到300ms之內(nèi)。異步請(qǐng)求合并,異步請(qǐng)求做合并,然后一次請(qǐng)求調(diào)用就能拿到所有數(shù)據(jù)。前端服務(wù)異步化/聚合,實(shí)時(shí)價(jià)格、實(shí)時(shí)庫(kù)存異步化, 使用如線程或協(xié)程機(jī)制將多個(gè)可并發(fā)的服務(wù)聚合。異步化還一個(gè)好處就是可以對(duì)異步請(qǐng)求做合并,原來(lái)N次調(diào)用可以合并為一次,還可以做請(qǐng)求的排重。

多級(jí)緩存化

瀏覽器緩存,當(dāng)頁(yè)面之間來(lái)回跳轉(zhuǎn)時(shí)走local cache,或者打開(kāi)頁(yè)面時(shí)拿著Last-Modified去CDN驗(yàn)證是否過(guò)期,減少來(lái)回傳輸?shù)臄?shù)據(jù)量;

CDN緩存,用戶去離自己最近的CDN節(jié)點(diǎn)拿數(shù)據(jù),而不是都回源到北京機(jī)房獲取數(shù)據(jù),提升訪問(wèn)性能;

服務(wù)端應(yīng)用本地緩存,我們使用Nginx+Lua架構(gòu),使用HttpLuaModule模塊的shared dict做本地緩存(?reload不丟失)或內(nèi)存級(jí)Proxy Cache,從而減少帶寬;

另外我們還使用使用一致性哈希(如商品編號(hào)/分類)做負(fù)載均衡內(nèi)部對(duì)URL重寫(xiě)提升命中率;

我們對(duì)mget做了優(yōu)化,如去商品其他維度數(shù)據(jù),分類、面包屑、商家等差不多8個(gè)維度數(shù)據(jù),如果每次mget獲取性能差而且數(shù)據(jù)量很大,30KB以上;而這些數(shù)據(jù)緩存半小時(shí)也是沒(méi)有問(wèn)題的,因此我們?cè)O(shè)計(jì)為先讀local cache,然后把不命中的再回源到remote cache獲取,這個(gè)優(yōu)化減少了一半以上的remote cache流量;

服務(wù)端分布式緩存,我們使用內(nèi)存+SSD+JIMDB持久化存儲(chǔ)。

動(dòng)態(tài)化

數(shù)據(jù)獲取動(dòng)態(tài)化,商品詳情頁(yè):按維度獲取數(shù)據(jù),商品基本數(shù)據(jù)、其他數(shù)據(jù)(分類、商家信息等);而且可以根據(jù)數(shù)據(jù)屬性,按需做邏輯,比如虛擬商品需要自己定制的詳情頁(yè),那么我們就可以跳轉(zhuǎn)走,比如全球購(gòu)的需要走jd.hk域名,那么也是沒(méi)有問(wèn)題的;

模板渲染實(shí)時(shí)化,支持隨時(shí)變更模板需求;

重啟應(yīng)用秒級(jí)化,使用Nginx+Lua架構(gòu),重啟速度快,重啟不丟共享字典緩存數(shù)據(jù);

需求上線速度化,因?yàn)槲覀兪褂昧薔ginx+Lua架構(gòu),可以快速上線和重啟應(yīng)用,不會(huì)產(chǎn)生抖動(dòng);另外Lua本身是一種腳本語(yǔ)言,我們也在嘗試把代碼如何版本化存儲(chǔ),直接內(nèi)部驅(qū)動(dòng)Lua代碼更新上線而不需要重啟Nginx。

彈性化

我們所有應(yīng)用業(yè)務(wù)都接入了Docker容器,存儲(chǔ)還是物理機(jī);我們會(huì)制作一些基礎(chǔ)鏡像,把需要的軟件打成鏡像,這樣不用每次去運(yùn)維那安裝部署軟件了;未來(lái)可以支持自動(dòng)擴(kuò)容,比如按照CPU或帶寬自動(dòng)擴(kuò)容機(jī)器,目前京東一些業(yè)務(wù)支持一分鐘自動(dòng)擴(kuò)容。

降級(jí)開(kāi)關(guān)

推送服務(wù)器推送降級(jí)開(kāi)關(guān),開(kāi)關(guān)集中化維護(hù),然后通過(guò)推送機(jī)制推送到各個(gè)服務(wù)器;

可降級(jí)的多級(jí)讀服務(wù),前端數(shù)據(jù)集群--->數(shù)據(jù)異構(gòu)集群--->動(dòng)態(tài)服務(wù)(調(diào)用依賴系統(tǒng));這樣可以保證服務(wù)質(zhì)量,假設(shè)前端數(shù)據(jù)集群壞了一個(gè)?磁盤,還可以回源到數(shù)據(jù)異構(gòu)集群獲取數(shù)據(jù);

開(kāi)關(guān)前置化,如Nginx--àTomcat,在Nginx上做開(kāi)關(guān),請(qǐng)求就到不了后端,減少后端壓力;

可降級(jí)的業(yè)務(wù)線程池隔離,從Servlet3開(kāi)始支持異步模型,Tomcat7/Jetty8開(kāi)始支持,相同的概念是Jetty6的Continuations。我們可以把處理過(guò)程分解為一個(gè)個(gè)的事件。通過(guò)這種將請(qǐng)求劃分為事件方式我們可以進(jìn)行更多的控制。如,我們可以為不同的業(yè)務(wù)再建立不同的線程池進(jìn)行控制:即我們只依賴tomcat線程池進(jìn)行請(qǐng)求的解析,對(duì)于請(qǐng)求的處理我們交給我們自己的線程池去完成;這樣tomcat線程池就不是我們的瓶頸,造成現(xiàn)在無(wú)法優(yōu)化的狀況。通過(guò)使用這種異步化事件模型,我們可以提高整體的吞吐量,不讓慢速的A業(yè)務(wù)處理影響到其他業(yè)務(wù)處理。慢的還是慢,但是不影響其他的業(yè)務(wù)。我們通過(guò)這種機(jī)制還可以把tomcat線程池的監(jiān)控拿出來(lái),出問(wèn)題時(shí)可以直接清空業(yè)務(wù)線程池,另外還可以自定義任務(wù)隊(duì)列來(lái)支持一些特殊的業(yè)務(wù)。

多機(jī)房多活

應(yīng)用無(wú)狀態(tài),通過(guò)在配置文件中配置各自機(jī)房的數(shù)據(jù)集群來(lái)完成數(shù)據(jù)讀取。

數(shù)據(jù)集群采用一主三從結(jié)構(gòu),防止當(dāng)一個(gè)機(jī)房掛了,另一個(gè)機(jī)房壓力大產(chǎn)生抖動(dòng)。

多種壓測(cè)方案

線下壓測(cè),Apache ab,Apache Jmeter,這種方式是固定url壓測(cè),一般通過(guò)訪問(wèn)日志收集一些url進(jìn)行壓測(cè),可以簡(jiǎn)單壓測(cè)單機(jī)峰值吞吐量,但是不能作為最終的壓測(cè)結(jié)果,因?yàn)檫@種壓測(cè)會(huì)存在熱點(diǎn)問(wèn)題;

線上壓測(cè),可以使用Tcpcopy直接把線上流量導(dǎo)入到壓測(cè)服務(wù)器,這種方式可以壓測(cè)出機(jī)器的性能,而且可以把流量放大,也可以使用Nginx+Lua協(xié)程機(jī)制把流量分發(fā)到多臺(tái)壓測(cè)服務(wù)器,或者直接在頁(yè)面埋點(diǎn),讓用戶壓測(cè),此種壓測(cè)方式可以不給用戶返回內(nèi)容。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)