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

銀河1號發表於2018-12-07

一、概念定義

1.什麼是類目

類目簡單來說就是商品的分類,用大家最常用的淘寶來看,就是圖中圈出來的地方。

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

為什麼會有類目,也是其功能決定的,類目目前已經作為電商網站導航的標配,只是不同網站的類目不同罷了。

如果我們的網站只有幾十個、上百個商品,或許類目對於我們來說不重要,但是如果商品有成千上萬個,甚至更多,那類目對我們來找到具有某些特點的商品就至關重要了。比如現在要找女式牛仔褲,可以通過類目 女裝->牛仔褲 就能找到了;否則那就一頁一頁去搜尋,就算我們平臺商品質量再好,價效比再高,相信使用者也會忍耐不住抓狂了。。

2.前後臺類目

類目分為前臺和後臺類目。

前臺類目的存在主要是面向使用者,搜尋導航欄,這個是易變的,季節、營銷活動都會影響類目導航;

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

好處:

比如現在我們平臺新推出一種活動,類目就是12.12,如果沒有前後臺類目分離,那我們需要找到需要做活動的商品把他們類目改為12.12,但明顯這個方式不妥;那重新維護一套和這些商品的關聯關係,這樣搞個新模組那還不如直接用類目來承載呢,這樣我們把前後臺類目做個對映關係就OK了。

關聯關係可以根據需求任意組合。

舉例:現在有批商品,分別有後臺類目A、B、C,我們要對A、B類目的商品做活動導航,則做個對映關係,12.12->(A、B),將前臺類目12.12和後臺A、B做關聯,這樣就可以通過導航12.12找到所有A、B類目下的商品了。

此外,前臺類目易變而且不和商品直接關聯還有個好處,它可以擴充套件成很多種方式。比如新增活動頻道,通過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的子屬性型號,對應的子屬性值可以為iPhone8、iPhone X等。

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

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


二、技術設計

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就能拿到所有資料。


該結構其實可適用於分散式快取和本地快取的資料結構。通過構建該資料結構就能快速拿到類目樹中的任一節點。


三、總結

雖然類目結構不復雜,但因為其使用非常頻繁,所有在電商系統中需要好好設計類目的存取。介紹了一些分散式快取和本地快取,但不詳細,詳細的快取知識可參考網上其他資料。上面講到的本地快取的實現方式也是借鑑了淘寶的類目體系,如果非要使用本地快取也可以參考一下。


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

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

(未經同意,請勿轉載)


相關文章