电商:流量大、数据多的商品详情页系统该如何设计

电商的商品系统主要功能是增删查改商品信息,没有很复杂的业务逻辑,支撑的主要页面是商品详情页。不过,这几这个系统的存储,主要考虑如下两个问题:

  • 第一,高并发。不管是什么电商系统,商品详情页一定是整个系统中DAU(日均访问次数)最高的页面之一。用户购物么,看商详了不一定买,买之前一定会看好多商详货比三家,所以商详的浏览次数要远比系统的其他页面高。如果没有考虑这个问题,大促的时候,支撑商详页的商品系统必然是第一个被流量冲垮的系统。
  • 第二,商品数量规模数量多、重量大
    • 先说为什么数量多,国内一线的电商,商品的数量大约在几亿到几十亿这个量级。当然实际上并没有这么多种商品,这里面有很多原因,比如同一个商品它有不同版本型号,再比如,商家为了促销需要,可能会反复上下架同一个商品或者给同一个商品配不同的马甲,这都导致了 SKU 数量爆炸。
    • 关于重量大。一个商品详情页里不仅有大量的文字,还有大量的图片和视频等。所以说,每个商详页都是个“大胖子”。

商品系统需要保存哪些数据

先来看一下,一个商详页都有哪些信息需要保存
在这里插入图片描述
这里面,右边灰色的部分,来自于电商的其他系统,我们暂且不去管这些,左边彩色部分,都是商品系统需要存储的内容。

这么多内容怎么存?能不能像保存订单数据那样,设计一张商品表,把这些数据一股脑都放进去。一张表存不下就再加几张子表。在电商早期可以这么干,但是,支撑不了多少数据量,也成不了多少并发。

当然,规模再大一点儿就不能这么干了。不能用数据库,那应该选择哪种存储系统来保存这么复杂的商品数据呢?任何一种存储都是没有办法满足的,解决思路是分而治之,我们可以把商品系统需要存储的数据按照特点,分成商品基本信息、商品参数、图片视频和商品介绍几个部分来分别存储。

商品基本信息该如何存储

我们先来分析商品的基本信息,它包括商品的主副标题、价格、颜色等一些商品最基本、主要的属性。这些属性都是固定的,不太可能会因为需求或者不同的颜色而变化,而且,这部分数据也不会太大。所以,建议在数据库中键一张表来保存商品的基本信息。

然后,还要在数据库前面,加一个缓存,帮助数据抵挡绝大部分的读请求。这个缓存,可以用redis或者memcached,这两种存储系统都是基于内存的KV存储,都能解决问题。

那如何使用前置缓存来缓存商品信息呢?

  • 处理商品信息的读请求时,先去缓存查找,如果找到就直接返回缓存中的数据。如果在缓存中没有找到,再去查数据库,把从数据库中查到的商品信息返回给页面,顺便把数据在缓存中也放一份
  • 更新商品信息的时候,在更新数据库的同时,也要把缓存中的数据删除掉。不然就有可能出现这种情况:数据库中的数据变了,而缓存中的数据没变,商品详情上看到的还是旧数据。

这种缓存更新的策略,叫做cache aside,是最简单实用的缓存更新策略,适用范围广泛,没有特殊情况就用这个策略。

除了cache aside,还有read/write through,write behind等几种策略

设计商品基本信息表的时候,必须记得保留商品数据的每一个历史版本。因为商品数据是随时变化的,但是订单中关联的商品数据,必须是下单那个时刻的商品数据,这一点很重要。你可以为每一个历史版本的商品数据保存一个快照,可以创建一个历史表保存到MySQL中,也可以保存一些到KV存储中

使用MongoDB保存商品参数

商品参数就是商品的特征。比如说,电脑的内存大小、手机的屏幕尺寸等等。和商品的基本属性一样,都是结构化的数据。但麻烦的是,不同类型的商品,它的参数是完全不一样的。

如果我们设计一个商品参数表,那这个表的字段就会太多了,并且每增加一个品类的商品,这个表就要加字段,这个方案行不通。

既然一个表不能解决问题,那就每个类别分别建一张表。比如说,建一个电脑参数表,里面的字段有CPU型号、内存大小等等;再建一个酒类参数表,里面的
字段有酒精度数、香型、产地等等。如果品类比较少,在100个以内,用几十张表分别保存不同品类的商品参数,也是可以的。但是,有没有更好的方法呢?

大多数数据库,都要求数据表有一个固定的结构。但是有一种数据库,没有这个要求。特别适合保存像“商品参数”这种,属性不固定的数据,这个数据库就是MongoDB。

MongoDB是一个面向文档存储的noSQL数据,在MongoDB中,表、行、列对应的概率分别是collection、document、field,其实都是一回事儿。

MongoDB最大的特点是,它的“表结构”是不需要事先定义的,其实,在MongoDB中根本没有表结构。由于没有表结构,它支持你把任意数据都放在同一张表中,你甚至可以在一张表中保存商品数据、订单数据、物流信息等这些结构完全不同的数据。并且,还能支持按照数据的某个字段进行查询。

它是怎么做到的呢?MongoDB中的每一行数据,在存储层就是简单的被转换为BSON格式后存起来,这个BSON就是一种1更紧凑的JSON。所以,即使在同一张表里面,它每一行数据的结构都可以不一样。当然,这种灵活性是有代价的,MongoDB不支持SQL,多表级联和复杂事务比较弱,不太适合存储一般的数据。

但是,对于商品参数信息,数据量大,数据结构不统一,这些MongoDB都可以很好的满足。我们也不需要事务和多表联查,MongoDB简直就是为了保存商品参数量身定做的一般

mysql支持json数据类型了,是不是可以不用mongodb了,多一个数据库,系统就会更复杂

是的,如果能满足业务需求的话,尽量不要用太多的技术。

使用对象存储保存图片和视频

图片和视频由于占用存储空间比较大,一般的存储方式都是,在数据库中只保存图片视频的ID或者URL,实际的图片视频以文件的形式单独存储。

现在图片和视频存储技术已经非常成熟了,首选方式就是保存在对象存储(object storage)中。各大云厂商都提供对象存储服务,比如七牛云。虽然每个产品的 API 都不一样,但功能大同小异

对象存储可以简单理解为一个无限容量的大文件KV存储,它的存储单位是对象,其实就是文件,可以是一张图片、一个视频、也可以是其他任何文件。每个对象都有一个唯一的key,利用这个key就可以随时访问对应的对象。基本的功能就是写入、访问和删除对象。

云服务产商的对象存储大多提供了客户端API,可以在Web页面或者App中直接访问而不需要通过后端存储来中转。这样,App和页面在上传图片视频的时候,直接保存到对象存储中,然后把对应key保存在商品系统中就可以了。

访问图片视频的时候,真正的图片和视频也不需要经过商品系统的后端服务,页面直接通过对象存储提供的URL来访问,又省事儿又节约带宽。而且,几乎所有的对象存储云服务都自带 CDN(Content Delivery Network)加速服务,响应时间比直接请求业务的服务器更短

国内的很多云厂商的对象存储对图片和视频,都做了非常多的针对性优化。最有用的是,缩放图片和视频转码,你只要把图片和视频丢到对象存储中,就可以随时获得任意尺寸大小的图片,视频也会自动转码成各种格式和码率的版本,适配各种 App 和场景。

将商品介绍静态化

商品介绍在商品详情页占的比重最大,包含了大量的带格式文字、图片和视频。其中图片和视频存放在对象存储里面,而商品介绍的文本,一般都是随着商品详情页一起静态化,保存在HTML中。

什么是静态化呢?静态化是相对于动态页面来说的。一般我们部署到tomcat中的web系统,返回的都是动态页面。也就是说,在web请求时,动态生成的。比如说商详页,一个Web 请求过来,带着 SKUID,Tomcat 中的商详页模块,再去访问各种数据库、调用后端服务,动态把这个商详页拼出来,返回给浏览器。

不过,现在基本没有系统会这么干了,你想,对于每个商品的详情页,你每次动态生成的页面内容不是完全一样吗?生成这么多次,不仅浪费服务器资源,速度还慢,关键是,Tomcat 能能抗的并发量和 Nginx 完全不是一个数量级的。

商详页的绝大部分内容都是商品介绍,它是不怎么变的。那不如就把这个页面事先生成好,保存成一个静态的 HTML,访问商详页的时候,直接返回这个 HTML。这就是静态化。

商详页静态化之后,不仅仅是可以节省服务器资源,还可以利用 CDN 加速,把商详页放到离用户最近的 CDN 服务器上,让商详页访问更快。

至于商品价格、促销信息等这些需要频繁变动的信息,不能静态化到页面中,可以在前端页面使用 AJAX 请求商品系统动态获取。这样就兼顾了静态化带来的优势,也能解决商品价格等信息需要实时更新的问题。

初始化的方式一般就是在商家后台修改了商详页中的商品介绍之后,重新
生成一个该SKU的新的商详页HTML文件,这个HTML文件的内容直接就包含商品介绍等大段的文字。然后把这个HTML推送到CDN上,或者等CDN回源来拉取。

其实静态化都是“过时”的技术了。但是特定的场景还是非常有用。

现在的动态Web页面,都是用JS请求动态数据,在浏览器中填充内容。

早期的Web页都是Server端渲染,比如Java中的thymeleaf,FreeMarker 模板引擎,包括PHP本身就是个模板引擎,这些都是在服务端来填充好动态内容,再返回给浏览器的。页面静态化就是利用这些模板引擎技术,事先就把页面中的动态内容填充好,生成一个一个静态的HTML。

这种静态化技术只适合页面内容很多,页面又不会经常变化的场景。比如我们电商的商详页,再比如很多新闻、咨询类的网站(一篇新闻发了之后很少会修改)。

小结

商品系统的存储需要提供商品的基本信息、商品参数、图片和视频以及商品介绍等等这些数据。

  • 商品的基本信息和商品参数分别保存在MySQL 和 MongoDB 中,用 Redis 作为前置缓存
  • 图片和视频存放在对象存储中
  • 商品介绍随着商详页一起静态化到商详静态页中。

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值