類目簡單來講就是商品的分類,用你們最經常使用的淘寶來看,就是圖中圈出來的地方。 緩存
爲何會有類目,也是其功能決定的,類目目前已經做爲電商網站導航的標配,只是不一樣網站的類目不一樣罷了。bash
若是咱們的網站只有幾十個、上百個商品,或許類目對於咱們來講不重要,可是若是商品有成千上萬個,甚至更多,那類目對咱們來找到具備某些特色的商品就相當重要了。好比如今要找女式牛仔褲,能夠經過類目 女裝->牛仔褲 就能找到了;不然那就一頁一頁去搜索,就算咱們平臺商品質量再好,性價比再高,相信用戶也會忍耐不住抓狂了。。服務器
類目分爲前臺和後臺類目。網絡
前臺類目的存在主要是面向用戶,搜索導航欄,這個是易變的,季節、營銷活動都會影響類目導航;數據結構
後臺類目是直接和商品關聯的,商品建立的時候選擇好類目,那麼對應的類目幾乎就不會變化了,它是很穩定的。併發
好處:分佈式
好比如今咱們平臺新推出一種活動,類目就是12.12,若是沒有先後臺類目分離,那咱們須要找到須要作活動的商品把他們類目改成12.12,但明顯這個方式不妥;那從新維護一套和這些商品的關聯關係,這樣搞個新模塊那還不如直接用類目來承載呢,這樣咱們把先後臺類目作個映射關係就OK了。高併發
關聯關係能夠根據需求任意組合。網站
舉例:如今有批商品,分別有後臺類目A、B、C,咱們要對A、B類目的商品作活動導航,則作個映射關係,12.12->(A、B),將前臺類目12.12和後臺A、B作關聯,這樣就能夠經過導航12.12找到全部A、B類目下的商品了。url
此外,前臺類目易變並且不和商品直接關聯還有個好處,它能夠擴展成不少種方式。好比新增活動頻道,經過URL的方式直接跳轉;經過關鍵詞的方式定義,好比類目T恤就是經過關鍵詞T恤進行商品搜索的功能。
通常來講,不論是前臺類目仍是後臺類目都會分爲幾級,因此最終都會造成一棵類目樹。
每一個類目都有屬性,屬性做爲該類目下商品都共有的特徵,好比顏色、大小等等。
屬性值則是該屬性具體的值,好比顏色能夠有紅色、白色、黑色。
正常來講,前臺類目有關聯後臺類目,則前臺類目的屬性都是從後臺類目的屬性集合中選擇的。
好比12.12->(A、B)這個關係中,對應屬性A(a1,a2),B(b1,b2),則12.12的屬性應該屬於(a1,a2,b1,b2)集合。
屬性也可分爲幾類,咱們使用到的大體爲:導航屬性、銷售屬性、普通屬性。
導航屬性:做爲根據類目進入篩選頁的屬性選項。
銷售屬性:商品詳情頁可供選擇的sku規格屬性,不一樣屬性價格可能會不一樣。
普通屬性:商品的其餘屬性。
建立商品的時候須要選擇類目,而後根據該類目的屬性來填充商品的屬性值,保存在商品上就相似於key-value的格式。這樣就能夠根據屬性值來篩選商品。
這個關係通常用不上,設計不了這麼細緻,不過能夠預留着。
子屬性是掛在某個屬性值下面的。子屬性值就是該子屬性的取值。例如手機類目下,有個屬性爲品牌,存在一個屬性值爲iPhone的品牌,則再往下劃分可劃分出iPhone的子屬性型號,對應的子屬性值能夠爲iPhone八、iPhone X等。
因此這裏就存在一個關係:類目(手機)->屬性(品牌)->屬性值(iPhone)->子屬性(型號)->iPhone8(子屬性值)
子屬性也用屬性模型來承載,只是設計的時候要創建好屬性值和子屬性的關聯關係。
其中包含的對應關係有:
前臺類目:後臺類目(多對多);
類目:屬性(1對多);
屬性:屬性值(1對多);
屬性值:子屬性(1對多);
類目和屬性的層級深度根據業務而定,由於是樹形結構,因此自己可擴展。
屬性掛在後臺葉子類目下。
`cate_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`gmt_create` datetime NOT NULL COMMENT '建立時間',
`gmt_modified` datetime NOT NULL COMMENT '修改時間',
`pid` bigint(20) DEFAULT NULL COMMENT '父id',
`leaf` tinyint(4) NOT NULL COMMENT '是否葉子節點 1:是0:不是',
`level` tinyint(4) NOT NULL COMMENT '層級',
`title` varchar(64) NOT NULL COMMENT 'title',
`cate_type` tinyint(4) NOT NULL COMMENT '前臺後臺類目 1:前臺 2:後臺',
`back_categories` varchar(255) DEFAULT NULL COMMENT '後臺類目id集合 適用於前臺 英文逗號分隔',
`root_cate_id` bigint(20) DEFAULT NULL COMMENT '根類目id',
`order_seq` int(11) NOT NULL COMMENT '排序序列',
`picture_url` varchar(255) DEFAULT NULL COMMENT '圖片url',
`need_audit` tinyint(4) NOT NULL COMMENT '是否須要審覈 1:是0:不是',
`is_delete` tinyint(4) NOT NULL COMMENT '狀態0:正常 1:刪除',
`biz_type` varchar(64) NOT NULL COMMENT '平臺類型',
`language` varchar(64) DEFAULT 'zh' COMMENT '語言',
`country` varchar(64) DEFAULT 'CN' COMMENT '國家',
`extension` mediumtext COMMENT '擴展字段',
`version` int(11) NOT NULL DEFAULT '0' COMMENT ‘版本',複製代碼
其中pid存儲上級類目ID
level表示該類目處於第幾級
因爲類目做爲電商系統的基礎數據,不少模塊都會依賴它,隨着電商系統規模的擴大,類目查詢請求、併發量會不斷增長,因此一開始咱們就採用緩存的方式。
採用類目作緩存的幾點考量:
緩存的兩種方式:分佈式緩存和分佈式本地緩存
4.1分佈式緩存:
使用Redis來存儲類目數據結構。
優勢:全部client共享一份數據,沒有數據不一致的問題
缺點:當系統規模很大,qps將不斷增長,緩存中心壓力變大。
總體流程以下圖:
刷新策略:定時更新,1.2兩步經過定時任務執行、執行頻率可根據具體業務可接受程度而定。
該方法的好處是無需在類目更改的全部方法路徑加入緩存失效、推送的邏輯。全部邏輯都統一在定時任務裏面處理。
4.2分佈式本地緩存:
優勢:全部client本地內存有一份副本,直接從內存讀取,速度快。
缺點:全部client須要與server數據同步,關鍵問題是數據不一致很難保證;
須要封裝單獨的client jar包以供使用,當jar包升級時須要同步全部依賴方升級,維護成本大;
總體流程圖以下:
這裏有幾點須要注意:
1.能夠經過不少種方式來達到client的數據刷新:
因爲咱們系統中對類目的更新實時性要求不高、沒有嚴格一致性要求。因此設計時可採用定時刷新的方式。jar包的方式對於依賴方是最易用的方式。也正是實時性、一致性要求不高,因此纔可以使用本地緩存。若是系統由於本地緩存數據不一致而將致使很嚴重的後果,那仍是慎用。
2.類目client是開發後打包給須要使用類目服務的應用引用。該包裏面已封裝好了關於類目的全部操做,包括定時拉取、解析服務器構建的數據結構、數據校驗、本地緩存刷新等功能,對應用提供的就是類目的基本操做,好比根據ID獲取類目、獲取類目樹等等。
3.服務器每次構建類目數據結構應維護版本號,這樣client可判斷是不是最新數據,從新拉取等等。經過先判斷版本號,再拉取是一種不錯的選擇。這樣可減小數據未更新而產生的沒必要要網絡傳輸。
4.爲何經過類目client主動從服務器拉取的方式,由於若是服務器主動推送,首先得維護client列表,其次還要維護全部client的推送狀態。若是把這個放在client維護,那就大大減小了複雜性。
經過比較分佈式緩存和本地緩存兩種方式,總結出分佈式緩存實現簡單,數據一致性易保證。本地緩存須要本身實現client包,會出現短暫的不一致,在高併發下優點更加明顯,但強一致業務慎用。最終咱們使用分佈式緩存即能知足要求。
結構設計:
類目面向電商前臺頁面,用的最多的就是類目樹的獲取,因此能夠這樣來設計。
經過根類目ID列表和子類目ID列表就可以索引到類目樹中全部的類目ID,經過ID就能拿到全部數據。
該結構其實可適用於分佈式緩存和本地緩存的數據結構。經過構建該數據結構就能快速拿到類目樹中的任一節點。
雖然類目結構不復雜,但由於其使用很是頻繁,全部在電商系統中須要好好設計類目的存取。介紹了一些分佈式緩存和本地緩存,但不詳細,詳細的緩存知識可參考網上其餘資料。上面講到的本地緩存的實現方式也是借鑑了淘寶的類目體系,若是非要使用本地緩存也能夠參考一下。
更多文章歡迎訪問 http://www.apexyun.com/
聯繫郵箱:public@space-explore.com
(未經贊成,請勿轉載)