商品詳情頁系統架構

通常的電商演變:html


商品詳情頁系統架構演進歷程前端

第一個版本
架構設計
J2EE+Tomcat+MySQL
動態頁面,每次請求都要調用多個依賴服務的接口,從數據庫裏查詢數據,而後經過相似JSP的技術渲染到HTML模板中,返回最終HTML頁面
架構缺陷
每次請求都是要訪問數據庫的,性能確定不好
每次請求都要調用大量的依賴服務,依賴服務不穩定致使商品詳情頁展現的性能常常抖動

第二個版本
架構設計
頁面靜態化技術
經過MQ獲得商品詳情頁涉及到的數據的變動消息
經過Java Worker服務全量調用全部的依賴服務的接口,查詢數據庫,獲取到構成一個商品詳情頁的完整數據,並經過velocity等模板技術生成靜態HTML
將靜態HTML頁面經過rsync工具直接推送到多臺nginx服務器上,每臺nginx服務器上都有全量的HTML靜態頁面
nginx對商品詳情頁的訪問請求直接返回本地的靜態HTML頁面
在nginx服務器前加一層負載均衡設備,請求打到任何一臺應用nginx服務器上,都有全量的HTML靜態頁面能夠返回
架構缺陷
全量更新問題
若是某一個商品分類、商家等信息變動了
那麼那個分類、店鋪、商家下面全部的商品詳情頁都須要從新生成靜態HTML頁面
更新速度過慢問題
分類、店鋪、商家、商品愈來愈多
從新生成HTML的負載愈來愈高,rsync全量同步全部nginx的負載也愈來愈高
從數據變動到生成靜態HTML,再到全量同步到全部nginx,時間愈來愈慢
擴容問題
由於每一個商品詳情頁都要全量同步到全部的nginx上,致使系統沒法擴容,沒法增長系統容量
架構優化
解決全量更新問題
每次Java Worker收到某個維度的變動消息,不是拉去全量維度並生成完整HTML,而是按照維度拆分,生成一個變化維度的HTML片斷
nginx對多個HTML片斷經過SSI合併html片斷而後輸出一個完整的html
解決擴容問題
每一個商品詳情頁不是全量同步到全部的nginx
而是根據商品id路由到某一臺nginx上,同時接入層nginx按照相同的邏輯路由請求
更新速度過慢問題
增長更多機器資源
多機房部署,每一個機房部署一套Java Worker+應用Nginx,全部機房用一套負載均衡設備,在每一個機房內部完成全流程,不跨機房
架構優化後的缺陷
更新速度仍是不夠快的問題
商品的每一個維度都有一個HTML片斷,rsync推送大量的HTML片斷,負載過高,性能較差
Nginx基於機械硬盤進行SSI合併,性能太差
仍是存在全量更新的問題
雖然解決了分類、商家、店鋪維度的變動,只要增量從新生產較小的HTML片斷便可,不用全量從新生成關聯的全部商品詳情頁的HTML
可是若是某個頁面模板變動,或者新加入一個頁面模板,仍是會致使幾億個商品的HTML片斷都要從新生成和rsync,要幾天時間才能完成,沒法響應需求
仍是存在容量問題
nginx存儲有限,不能無限存儲幾億,以及增加的商品詳情頁的HTML文件
若是nginx存儲達到極限,須要刪除部分商品詳情頁的HTML文件,改爲nginx找不到HTML,則調用後端接口,回到動態頁面的架構
動態頁面架構在高併發訪問的狀況下,會對依賴系統形成過大的壓力,幾乎扛不住

第三個版本
須要支持的需求
迅速響應各類頁面模板的改版和個性化需求的新模板的加入
頁面模塊化,頁面中的某個區域變化,只要更新這個區域中的數據便可
支持高性能訪問
支持水平擴容的伸縮性架構
架構設計
系統架構設計
依賴服務有數據變動發送消息到MQ
數據異構Worker服務監聽MQ中的變動消息,調用依賴服務的接口,僅僅拉取有變動的數據便可,而後將數據存儲到redis中
數據異構Worker存儲到redis中的,都是原子未加工數據,包括商品基本信息、商品擴展屬性、商品其餘信息、商品規格參數、商品分類、商家信息
數據異構Worker發送消息到MQ,數據聚合Worker監聽到MQ消息
數據聚合Worker將原子數據從redis中取出,按照維度聚合後存儲到redis中,包括三個維度
基本信息維度:基本信息、擴展屬性
商品介紹:PC版、移動版
其餘信息:商品分類、商家信息
nginx+lua,lua從redis讀取商品各個維度的數據,經過nginx動態渲染到html模板中,而後輸出最終的html
如何解決全部的問題
更新問題:再也不是生成和推送html片斷了,再也不須要合成html,直接數據更新到redis,而後走動態渲染,性能大大提高
全量更新問題:數據和模板分離,數據更新呢就更新數據,模板更新直接推送模板到nginx,不須要從新生成全部html,直接走動態渲染
容量問題:不須要依賴nginx所在機器的磁盤空間存儲大量的html,將數據放redis,html就存放模板,大大減小空間佔用,並且redis集羣可擴容mysql

 

 

 

 

 

 

 

 

 

 

 

 


商品詳情頁總體架構組成nginx

動態渲染系統
將頁面中靜的數據,直接在變動的時候推送到緩存,而後每次請求頁面動態渲染新數據
商品詳情頁系統(負責靜的部分):被動接收數據,存儲redis,nginx+lua動態渲染
商品詳情頁動態服務系統(對外提供數據接口)
提供各類數據接口ajax

動態調用依賴服務的接口,產生數據而且返回響應
從商品詳情頁系統處理出來的redis中,獲取數據,並返回響應

OneService系統
動的部分,都是走ajax異步請求的,不是走動態渲染的
商品詳情頁統一服務系統(負責動的部分)

前端頁面
靜的部分,直接被動態渲染系統渲染進去了
動的部分,html一到瀏覽器,直接走js腳本,ajax異步加載
商品詳情頁,分段存儲,ajax異步分屏加載

工程運維
限流,壓測,灰度發佈redis

 


多級緩存架構
本地緩存
使用nginx shared dict做爲local cache,http-lua-module的shared dict能夠做爲緩存,並且reload nginx不會丟失
也可使用nginx proxy cache作local cache
雙層nginx部署,一層接入,一層應用,接入層用hash路由策略提高緩存命中率
好比庫存緩存數據的TP99爲5s,本地緩存命中率25%,redis命中率28%,回源命中率47%
一次普通秒殺活動的命中率,本地緩存55%,分佈式redis命中率15%,回源命中率27%
最高能夠提高命中率達到10%
全緩存鏈路維度化存儲,若是有3個維度的數據,只有其中1個過時了,那麼只要獲取那1個過時的數據便可
nginx local cache的過時時間通常設置爲30min,到後端的流量會減小至少3倍
4級多級緩存
nginx本地緩存,抗熱點數據,小內存緩存訪問最頻繁的數據
各個機房本地的redis從集羣的數據,抗大量離線數據,採用一致性hash策略構建分佈式redis緩存集羣
tomcat中的動態服務的本地jvm堆緩存
支持在一個請求中屢次讀取一個數據,或者與該數據相關的數據
做爲redis崩潰的備用防線
固定緩存一些較少訪問頻繁的數據,好比分類,品牌等數據
堆緩存過時時間爲redis過時時間的一半
主redis集羣
命中率很是低,小於5%
防止主從同步延遲致使的數據讀取miss
防止各個機房的從redis集羣崩潰以後,全量走依賴服務會致使雪崩,主redis集羣是後備防線
主redis集羣,採起多機房一主三從的高可用部署架構
redis集羣部署採起雙機房一主三活的架構,機房A部署主集羣+一個從集羣,機房B部署一個從集羣(從機房A主集羣)+一個從集羣(從機房B從集羣)
雙機房一主三活的架構,保證了機房A完全故障的時候,機房B還有一套備用的集羣,能夠升級爲一主一從
若是採起機房A部署一主一從,機房B一從,那麼機房A故障時,機房B的一從承載全部讀寫壓力,壓力過大,很難承受sql

 

動態渲染那套系統數據庫

(1)依賴服務 -> MQ -> 動態渲染服務 -> 多級緩存
(2)負載均衡 -> 分發層nginx -> 應用層nginx -> 多級緩存
(3)多級緩存 -> 數據直連服務後端

動態渲染系統

數據閉環
數據閉環架構
依賴服務:商品基本信息,規格參數,商家/店鋪,熱力圖,商品介紹,商品維度,品牌,分類,其餘
發送數據變動消息到MQ
數據異構Worker集羣,監聽MQ,將原子數據存儲到redis,發送消息到MQ
數據聚合Worker集羣,監聽MQ,將原子數據按維度聚合後存儲到redis,三個維度(商品基本信息、商品介紹、其餘信息)
數據閉環,就是數據的自我管理,全部數據原樣同步後,根據本身的邏輯進行後續的數據加工,走系統流程,以及展現k
數據造成閉環以後,依賴服務的抖動或者維護,不會影響到整個商品詳情頁系統的運行
數據閉環的流程:數據異構(多種異構數據源拉取),數據原子化,數據聚合(按照維度將原子數據進行聚合),數據存儲(Redis)

數據維度化
商品基本信息:標題、擴展屬性、特殊屬性、圖片、顏色尺碼、規格參數
商品介紹
非商品維度其餘信息:分類,商家,店鋪,品牌
商品維度其餘信息:採用ajax異步加載,價格,促銷,配送至,廣告,推薦,最佳組合,等等

採起ssdb,這種基於磁盤的大容量/高性能的kv存儲,保存商品維度、主商品維度、商品維度其餘信息,數據量大,不能光靠內存去支撐
採起redis,純內存的kv存儲,保存少許的數據,好比非商品維度的其餘數據,商家數據,分類數據,品牌數據

一個完整的數據,拆分紅多個維度,每一個維度獨立存儲,就避免了一個維度的數據變動就要全量更新全部數據的問題
不一樣維度的數據,由於數據量的不同,能夠採起不一樣的存儲策略

系統拆分
系統拆分更加細:依賴服務、MQ、數據異構Worker、數據同步Worker、Redis、Nginx+Lua
每一個部分的工做專一,影響少,適合團隊多人協做
異構Worker的原子數據,基於原子數據提供的服務更加靈活
聚合Worker將數據聚合後,減小redis讀取次數,提高性能
前端展現分離爲商品詳情頁前端展現系統和商品介紹前端展現系統,不一樣特色,分離部署,不一樣邏輯,互相不影響

異步化
異步化,提高併發能力,流量削峯
消息異步化,讓各個系統解耦合,若是使用依賴服務調用商品詳情頁系統接口同步推送,那麼就是耦合的
緩存數據更新異步化,數據異構Worker同步調用依賴服務接口,可是異步更新redis

動態化
數據獲取動態化:nginx+lua獲取商品詳情頁數據的時候,按照維度獲取,好比商品基本數據、其餘數據(分類、商家)
模板渲染實時化:支持模板頁面隨時變化,由於採用的是每次從nginx+redis+ehcache緩存獲取數據,渲染到模板的方式,所以模板變動不用從新靜態化HTML
重啓應用秒級化:nginx+lua架構,重啓在秒級
需求上線快速化:使用nginx+lua架構開發商品詳情頁的業務邏輯,很是快速

多機房多活
Worker無狀態,同時部署在各自的機房時採起不一樣機房的配置,來讀取各自機房內部部署的數據集羣(redis、mysql等)
將數據異構Worker和數據聚合Worker設計爲無狀態化,能夠任意水平擴展
Worker無狀態化,可是配置文件有狀態,不一樣的機房有一套本身的配置文件,只讀取本身機房的redis、ssdb、mysql等數據
每一個機房配置全鏈路:接入nginx、商品詳情頁nginx+商品基本信息redis集羣+其餘信息redis集羣、商品介紹nginx+商品介紹redis集羣
部署統一的CDN以及LVS+KeepAlived負載均衡設備瀏覽器

 

隊列化
任務等待隊列
任務排重隊列(異構Worker對一個時間段內的變動消息作排重)
失敗任務隊列(失敗重試機制)
優先級隊列,刷數據隊列(依賴服務洗數據)、高優先級隊列(活動商品優先級高)

 

 

併發化
數據同步服務作併發化+合併,將多個變動消息合併在一塊兒,調用依賴服務一次接口獲取多個數據,採用多線程併發調用
數據聚合服務作併發化,每次從新聚合數據的時候,對多個原子數據用多線程併發從redis查詢

 redis:

 

 

 

 

 

 

 

 

相關文章
相關標籤/搜索