电商:购物车系统应该如何设计

首先,我们来看购物车系统的主要功能是什么。就是在用户选购商品时,下单之前,暂存用户想要购买的商品。购物车对数据可靠性要求不高,性能也没有特别的要求,在整个电商系统中,看起来是比较容易设计和实现的一个子系统。

购物车系统的功能,主要就三个:把商品加入购物车、购物车列表、发起结算下单,再加上一个在所有界面都要显示的购物车小图标。

支撑购物车的这几个功能,对应的存储模型应该怎么设计?很简单,只要一个“购物车”实体就够了。

设计购物车存储时需要把握什么原则?

比如下面这几个问题:

  1. 用户没登录,在浏览器中加购,关闭浏览器再打开,刚才加购的商品还在不在?
  2. 用户没登录,在浏览器中加购,然后登录,刚才加购的商品还在不在?
  3. 关闭浏览器再打开,上一步加购的商品在不在?
  4. 再打开手机,用相同的用户登录,第二步加购的商品还在不在呢?

回答:

  1. 如果用户没有登录,加购的商品也会保存到用户的电脑里,这样即使关闭浏览器再打开,购物车的商品依然存在
  2. 如果用户先加购,再登录,登录前加购的商品就会被自动合并到用户名下,所以登录有购物车仍然有登录前加购的商品
  3. 关闭浏览器在打开,这时又变为未登录状态,但是之前未登录时加购的商品已经被合并到刚刚登录的用户名下了,所以购物车是空的
  4. 使用手机登录相同的用户,看到的就是该用户的购物车,这时无论你在手机 App、电脑还是微信中登录,只要是相同的用户,看到是同一个购物车,所以第二步加购的商品是存在的

所以,上面这四个问题的答案依次是:存在、存在、不存在、存在。
如果你没有设计或者开发过购物车系统,你可能并不会想到购物车还有这么多弯弯绕。但是,作为一个开发者,如果你不仔细把这些问题考虑清楚,用户在使用购物车的时候,就会感觉你的购物车系统不好用,不是加购的商品莫名其妙地丢了,就是购物车莫名其妙地多出来一些商品。

要解决上面这些问题,其实只要在存储设计时,把握这几个原则就可以了:

  • 如果未登录时,需要临时暂存购物车的商品
  • 用户登录时,把暂存购物车的商品合并到用户购物车中,并且清除暂存购物车
  • 用户登录后,购物车中的商品,需要在浏览器、手机App等这些终端中保持同步

实际上,购物车系统需要保存两类购物车:未登录情况下的“暂存购物车”、登录后的“用户购物车”

如何设计“暂存购物车”

暂存购物车应该保存在客户端还是服务端?

  • 如果保存在服务端,那么每个暂存购物车都需要一个全局唯一的标识,这个标识不太容易设计,并且,存在服务端还要浪费服务端的资源。
  • 所以,肯定是保存在客户端好,即可以节约服务端的存储资源,也没有购物车标识的问题,因为每个客户端就保存它自已唯一一个购物车就可以了

客户端的存储可以选择的有:Session、Cookie 和 LocalStorage,其中浏览器的localStorage 和 App 的本地存储是类似的,我们都以 LocalStorage 来代表。那存在哪里比较合适呢?

  • session不太合适,因为session的保存时间短,而且session的数据实际上是存储在服务端的。剩余的两种存储,Cookie 和 LocalStorage都可以用来保存购物车数据,选择哪种方式更好呢?各有优劣。
  • 在我们这个场景中,使用cookie和localstorage最关键的区别是,客户端和服务端的每次交互,都会自动带着cookie数据往返,这样服务端可以读写客户端cookie中的数据,而localstorage里的数据,只能由客户端来访问
  • 使用cookie存储,实现起来比较简单,加减购物车、合并购物车的过程中,由于服务端可以读写cookie,这样全部逻辑都可以在服务端实现,并且客户端和服务端请求的次数也相对比较少一点
  • 使用localstorage存储,实现相对比较复杂一点,客户端和服务端都要实现一些业务逻辑,但localstorage的好处是,它的存储容量比cookie的4KB上限要大得多,而且不用像cookie那样,无论用不用,每次请求都要带着,可以节省带宽
  • 所以,选择cookie或者是localstorage来存储暂存购物车都没有问题,如果是小型电商,那么cookie存储更简单;如果电商是面向那种批发的行业用户,用户需要加购大量商品,那么cookiie可能容量不够用,选择localstorage更合适

不管选择哪种存储,暂存购物车保存的数据格式都是一样的,参照我们实体模型来设计就可以,我们可以直接用 JSON 表示:
在这里插入图片描述

如何设计“用户购物车”的存储

因为用户购物车必须要保证多端的数据同步,所以数据必须保存在服务端。常规思路是,设计一张购物车表,把数据存在MySQL中。其实体模型也可以设计如下:
在这里插入图片描述

注意,需要在user_id上建一个索引,因为查询购物车表时,都是以user_id作为查询条件来查询的。

也可以选择reids来保存购物车数据,以用户ID作为key,用一个redis的Hash作为value来保存购物车中的商品,比如:
在这里插入图片描述
从读写性能上来说,Redis 是比 MySQL 快非常多的,那是不是用 Redis 就一定比用 MySQL 更好呢?我们来比较一下使用 MySQL 和 Redis 两种存储的优劣势:

  • redis性能要MySQL要高出至少一个数量级,响应时间更短,可以支撑更多的并发请求
  • MySQL的数据可靠性是要好处Redis的,因为Redis是异步刷盘,如果出现服务端掉电等异常情况,Redis是有可能会丢数据的。但是考虑到购物车里的数据,对可靠性要求也没那么苛刻,丢少量数据的后果也就是,个别用户的购物车少了几件商品,问题也不大。所以,在购物车这个场景下,Redis 的数据可靠性不高这个缺点,并不是不能接受的。
  • MySQL的另一个优势是,它支持丰富的查询方式和事务机制,这两个特性,对我们今天讨论的这几个购物车核心功能没什么用。但是,每一个电商系统都有它个性化的需求,如果需要以其他方式访问购物车的数据,比如说,统计一下今天加购的商品总数,这个时候,使用 MySQL 存储数据,就很容易实现,而使用 Redis 存储,查询起来就非常麻烦而且低效。

综合比较下来,考虑到需求总是不断变化,还是更推荐MySQL。如果追求性能或者高并发,也可以选择Redis

小结

购物车系统的主要功能包括:加购、购物车列表页和结算下单。核心的实体就只有一个“购物车”实体,它至少要包括:SKUID、数量、加购时间和勾选状态这几个属性。

在给购物车设计存储时,为了确保购物车内的数据在多端保持一致,以及用户登录前后购物车内商品能无缝衔接,除了每个用户的“用户购物车”之外还要实现一个“暂存购物车”保存用户未登录时加购的商品,并在用户登录后自动合并“暂存购物车”和“用户购物车”。

暂存购物车存储在客户端浏览器或者 App 中,可以选择存放到 Cookie或者 LocalStorage中。用户购物车保存在服务端,可以选择使用 Redis 或者是 MySQL 存储,使用 Redis 存储会有更高的性能,可以支撑更多的并发请求,使用 MySQL 是更常规通用的方式,便于应对变化,系统的扩展性

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值