12. 谷粒商城商品上架-es中sku的存储模型分析

前言

在决定哪些信息应该存储到es之前,首先要明确一点,es中的数据是存储到内存中的,虽然它原生支持分布式,理论上容量无限,但是毕竟内存的价格要比硬盘的价格贵的多,所以尽量能节省的就节省。

就是只保存有用的数据,没用的数据全部不保存,要用的时候,大不了检索出来,去数据库再查一遍。

哪些信息应该存储到es中

1. sku

  • 可能通过 sku 的标题、销量、价格区间检索

2. 品牌、分类

  • 点击分类,检索分类下的所有信息
  • 点击品牌,检索品牌下的商品信息

3. spu

  • 选择规格,检索拥有这个规格的商品

分析-怎么设计存储结构来保存数据

1. 空间换时间

{
    skuId:1
    spuId:11
    skyTitile:华为xx
    price:999
    saleCount:99
    attrs:[
        {尺寸:5寸},
        {CPU:高通845},
        {分辨率:全高清}
	]
}

好处:方便检索

缺点:会产生冗余字段,就会产生对于相同类型的商品,attrs 属性字段会重复,空间占用大

假设有100w条数据,每条数据有20个属性,一共占用2KB的空间, 那100W条数据也才占用2G的空间,其实就是多加一根内存条,即使占用20G,也不过是加多少内存的问题

2. 时间换空间

sku索引{
    skuId:1
    spuId:11
    sku其它的基本信息...
}
attr索引{
    spuId:11
    attrs:[
        {尺寸:5寸},
        {CPU:高通845},
        {分辨率:全高清}
	]
}

将数据分到两个索引下,这样就不会产生数据冗余的问题

那么如何查找attr属性呢?

每一个sku索引里面,都有spuId,获取到这个spuId之后,再去attr索引里面,根据spuId查找即可

动态计算

假如搜索“手机”,系统会找到标题里面包含手机的这些商品,并且它会把这些商品聚合起来,分析这些商品所涉及的所有属性,以及所有的属性值,然后再展示到页面,这样就会保证,点进某一个属性值,下面一定有商品,所以检索条件是动态计算的。

动态计算所带来的问题

假设搜索“小米”,会发现它存在于好几个分类中,比如:粮食、手机、电器等等,会有很多sku都包含“小米”

如果要检索出这些sku所包含的所有属性怎么办

假设标题带有“小米”两个字的商品有1w个,这1w个商品涉及到4000个spu,我们就需要找到这4000个spu所对应的属性,来进行聚合,我们会做分步查询

  1. 查出了1w个包含“小米”的商品,这1W个商品涉及到4000个spu
  2. 查出这4000个spu对应的所有可能属性

这里一分步,就相当于会调用第二次查询 ,第二次,es的客户端会给es发送请求,这个请求不说别的,就说spuId这个数组,里面就需要传4000个spuId,这4000个spuId因为都是Long类型,假设每个都占8字节,4000*8,那就是32000个字节,等与32kb

这么1次请求,就需要发送32kb的数据,假设现在有1w人正在商城检索商品,集群中光数据传输,就会产生320MB,

如果真是百万并发,点个检索,就会传出32GB的数据,这32GB的数据,光网络阻塞,时间可能就会非常长

这种方式看着可以,但是随着系统的不断壮大,未来可能就会产生上述的问题。

3. 最终方案-存储结构

完整结构(修改了部分字段,请按需选择):

PUT product
{
     
  "mappings": {
     
    "properties": {
     
      "skuId": {
      "type": "long" },
      "spuId": {
      "type": "keyword" },
      "skuTitle": {
     
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuPrice": {
      "type": "keyword" },
      "skuImg": {
     
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "saleCount":{
      "type":"long" },
      "stockOrNot": {
      "type": "boolean" },
      "hotScore": {
      "type": "long"  },
      "brandId":  {
      "type": "long" },
      "categoryId": {
      "type": "long"  },
      "brandName": {
     
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "brandImg":{
     
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "categoryName": {
     
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "attrs": {
     
        "type": "nested",
        "properties": {
     
          "attrId": {
     "type": "long"  },
          "attrName": {
     
            "type": "keyword",
            "index": false,
            "doc_values": false
          },
          "attrValue": {
      "type": "keyword" }
        }
      }
    }
  }
}

mapping结构字段说明

"mappings": {
     
  "properties": {
     
    "skuId": {
      "type": "long" },
    "spuId": {
      "type": "keyword" }, # 精确检索,不分词
    "skuTitle": {
     
      "type": "text", # 全文检索
      "analyzer": "ik_smart" # 分词器
    },
    "skuPrice": {
      "type": "keyword" },	# 为了避免精度问题,使用keyword
    "skuImg": {
     
      "type": "keyword",
      "index": false, # false 不可被检索,冗余字段都加上
      "doc_values": false # false 不可被聚合,冗余字段都加上
    },
    "saleCount":{
      "type":"long" }, # 商品销量
 	# 商品是否有库存
	# 可以避免每天都跟数据库核查数量,因为数据只要已修改,es就会重新把它索引一次,
	# 维护整片索引是一个很慢的操作,所以只在商品没有库存的时候,才将其改为false,
	# 上了库存,再将其改为true,这样会比实时更新库存好的多
    "hasStock": {
      "type": "boolean" },
    "hotScore": {
      "type": "long"  }, # 商品热度评分
    "brandId":  {
      "type": "long" }, # 品牌id
    "categoryId": {
      "type": "long"  }, # 分类id
    "brandName": {
     	# 品牌名,
      "type": "keyword",
      "index": false,
      "doc_values": false
    },
    "brandImg":{
     	# 品牌图片
      "type": "keyword",
      "index": false,
      "doc_values": false
    },
    "categoryName": {
     	# 分类名
      "type": "keyword",
      "index": false,
      "doc_values": false
    },
    "attrs": {
     	# 当前这个sku所拥有的所有属性规格
      "type": "nested",	# 嵌入式,内部属性
      "properties": {
     
        "attrId": {
     "type": "long"  },
        "attrName": {
     	# 属性名
          "type": "keyword",
          "index": false,
          "doc_values": false
        },
        "attrValue": {
      "type": "keyword" }	# 属性值
      }
    }
  }
}

你可能感兴趣的:(谷粒商城,elasticsearch)