基於電商中臺架構-商品系統設計(二):類目設計

1、概念定義

1.什麼是類目

類目簡單來講就是商品的分類,用你們最經常使用的淘寶來看,就是圖中圈出來的地方。 緩存


爲何會有類目,也是其功能決定的,類目目前已經做爲電商網站導航的標配,只是不一樣網站的類目不一樣罷了。bash

若是咱們的網站只有幾十個、上百個商品,或許類目對於咱們來講不重要,可是若是商品有成千上萬個,甚至更多,那類目對咱們來找到具備某些特色的商品就相當重要了。好比如今要找女式牛仔褲,能夠經過類目 女裝->牛仔褲 就能找到了;不然那就一頁一頁去搜索,就算咱們平臺商品質量再好,性價比再高,相信用戶也會忍耐不住抓狂了。。服務器

2.先後臺類目

類目分爲前臺和後臺類目。網絡

前臺類目的存在主要是面向用戶,搜索導航欄,這個是易變的,季節、營銷活動都會影響類目導航;數據結構

後臺類目是直接和商品關聯的,商品建立的時候選擇好類目,那麼對應的類目幾乎就不會變化了,它是很穩定的。併發

好處:分佈式

好比如今咱們平臺新推出一種活動,類目就是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恤進行商品搜索的功能。

通常來講,不論是前臺類目仍是後臺類目都會分爲幾級,因此最終都會造成一棵類目樹。

3.屬性和屬性值

每一個類目都有屬性,屬性做爲該類目下商品都共有的特徵,好比顏色、大小等等。

屬性值則是該屬性具體的值,好比顏色能夠有紅色、白色、黑色。

正常來講,前臺類目有關聯後臺類目,則前臺類目的屬性都是從後臺類目的屬性集合中選擇的。

好比12.12->(A、B)這個關係中,對應屬性A(a1,a2),B(b1,b2),則12.12的屬性應該屬於(a1,a2,b1,b2)集合。

屬性也可分爲幾類,咱們使用到的大體爲:導航屬性、銷售屬性、普通屬性。

導航屬性:做爲根據類目進入篩選頁的屬性選項。


銷售屬性:商品詳情頁可供選擇的sku規格屬性,不一樣屬性價格可能會不一樣。


普通屬性:商品的其餘屬性。


建立商品的時候須要選擇類目,而後根據該類目的屬性來填充商品的屬性值,保存在商品上就相似於key-value的格式。這樣就能夠根據屬性值來篩選商品。

4.子屬性和子屬性值

這個關係通常用不上,設計不了這麼細緻,不過能夠預留着。

子屬性是掛在某個屬性值下面的。子屬性值就是該子屬性的取值。例如手機類目下,有個屬性爲品牌,存在一個屬性值爲iPhone的品牌,則再往下劃分可劃分出iPhone的子屬性型號,對應的子屬性值能夠爲iPhone八、iPhone X等。

因此這裏就存在一個關係:類目(手機)->屬性(品牌)->屬性值(iPhone)->子屬性(型號)->iPhone8(子屬性值)

子屬性也用屬性模型來承載,只是設計的時候要創建好屬性值和子屬性的關聯關係。


2、技術設計

1.關係圖


其中包含的對應關係有:

前臺類目:後臺類目(多對多);

類目:屬性(1對多);

屬性:屬性值(1對多);

屬性值:子屬性(1對多);

2.類目屬性樹形結構圖


類目和屬性的層級深度根據業務而定,由於是樹形結構,因此自己可擴展。

屬性掛在後臺葉子類目下。

3.類目表

`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.緩存

因爲類目做爲電商系統的基礎數據,不少模塊都會依賴它,隨着電商系統規模的擴大,類目查詢請求、併發量會不斷增長,因此一開始咱們就採用緩存的方式。

採用類目作緩存的幾點考量:

  • 類目做爲基礎數據,查詢請求巨大;
  • 類目數據相比其餘基礎數據來講內存佔用不高;
  • 類目是共享數據;
  • 類目變動實時性要求不高,沒有嚴格的數據一致性要求;

緩存的兩種方式:分佈式緩存和分佈式本地緩存

4.1分佈式緩存:

使用Redis來存儲類目數據結構。

優勢:全部client共享一份數據,沒有數據不一致的問題

缺點:當系統規模很大,qps將不斷增長,緩存中心壓力變大。

總體流程以下圖:


  1. 從DB查詢類目數據
  2. 構建須要保存的數據結構,並推到緩存
  3. 接收client查詢請求
  4. 從構建好的緩存中查詢
  5. 返回數據


刷新策略:定時更新,1.2兩步經過定時任務執行、執行頻率可根據具體業務可接受程度而定。

該方法的好處是無需在類目更改的全部方法路徑加入緩存失效、推送的邏輯。全部邏輯都統一在定時任務裏面處理。


4.2分佈式本地緩存:

優勢:全部client本地內存有一份副本,直接從內存讀取,速度快。

缺點:全部client須要與server數據同步,關鍵問題是數據不一致很難保證;

須要封裝單獨的client jar包以供使用,當jar包升級時須要同步全部依賴方升級,維護成本大;

總體流程圖以下:



  1. 1.從DB讀取類目數據
  2. 2.構建須要緩存的類目數據結構。
  3. 3.經過開發的類目client jar包向服務器拉取數據。
  4. 4.返回構建好的數據結構。


這裏有幾點須要注意:

1.能夠經過不少種方式來達到client的數據刷新:

  • 將構建好的數據包存放在DB,client統一從DB刷新;
  • 服務器經過發消息廣播的方式,client監聽刷新本地緩存;
  • 經過jar包實現封裝定時拉取的方式,定時刷新本地緩存。

因爲咱們系統中對類目的更新實時性要求不高、沒有嚴格一致性要求。因此設計時可採用定時刷新的方式。jar包的方式對於依賴方是最易用的方式。也正是實時性、一致性要求不高,因此纔可以使用本地緩存。若是系統由於本地緩存數據不一致而將致使很嚴重的後果,那仍是慎用。

2.類目client是開發後打包給須要使用類目服務的應用引用。該包裏面已封裝好了關於類目的全部操做,包括定時拉取、解析服務器構建的數據結構、數據校驗、本地緩存刷新等功能,對應用提供的就是類目的基本操做,好比根據ID獲取類目、獲取類目樹等等。

3.服務器每次構建類目數據結構應維護版本號,這樣client可判斷是不是最新數據,從新拉取等等。經過先判斷版本號,再拉取是一種不錯的選擇。這樣可減小數據未更新而產生的沒必要要網絡傳輸。

4.爲何經過類目client主動從服務器拉取的方式,由於若是服務器主動推送,首先得維護client列表,其次還要維護全部client的推送狀態。若是把這個放在client維護,那就大大減小了複雜性。


經過比較分佈式緩存和本地緩存兩種方式,總結出分佈式緩存實現簡單,數據一致性易保證。本地緩存須要本身實現client包,會出現短暫的不一致,在高併發下優點更加明顯,但強一致業務慎用。最終咱們使用分佈式緩存即能知足要求。


結構設計:

類目面向電商前臺頁面,用的最多的就是類目樹的獲取,因此能夠這樣來設計。

  • rootCategoryIds:保存根類目ID列表索引
  • subCategoryIds + 類目ID:保存該類目下級類目ID列表索引
  • category + 類目ID:保存該類目具體數據data

經過根類目ID列表和子類目ID列表就可以索引到類目樹中全部的類目ID,經過ID就能拿到全部數據。


該結構其實可適用於分佈式緩存和本地緩存的數據結構。經過構建該數據結構就能快速拿到類目樹中的任一節點。


3、總結

雖然類目結構不復雜,但由於其使用很是頻繁,全部在電商系統中須要好好設計類目的存取。介紹了一些分佈式緩存和本地緩存,但不詳細,詳細的緩存知識可參考網上其餘資料。上面講到的本地緩存的實現方式也是借鑑了淘寶的類目體系,若是非要使用本地緩存也能夠參考一下。


更多文章歡迎訪問 http://www.apexyun.com/

聯繫郵箱:public@space-explore.com

(未經贊成,請勿轉載)

相關文章
相關標籤/搜索