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

购物车系统的功能,主要的就三个:把商品加入购物车(后文称“加购”)、购物车列表页、发起结算下单。

如何设计“暂存购物车”的存储?

选择 Cookie 或者是 LocalStorage 来存储暂存购物车都是没问题的,你可以根据它俩各自的优劣势来选择。比如你设计的是个小型电商,那用 Cookie 存储实现起来更简单。 再比如,你的电商是面那种批发的行业用户,用户需要加购大量的商品,那 Cookie 可能容量不够用,选择 LocalStorage 就更合适。

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

image.png

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

接下来,我们再来看下用户购物车的存储该怎么实现。因为用户购物车必须要保证多端的数据同步所以数据必须保存在服务端。常规的思路是,设计一张购物车表,把数据存在MySQL 中。这个表的结构同样可以参照刚刚讲的实体模型来设计:

image.png

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

你也可以选择更快的 Redis 来保存购物车数据,以用户 ID 作为 Key,用一个 Redis 的 HASH 作为 Value 来保存购物车中的商品。比如:

image.png

MySQL和Redis两种存储的优劣势分析:

  1. Redis性能好,可以支撑更多的并发请求
  2. MySQL数据可靠性更好,因为Redis是异步刷屏的,如果服务器掉电等异常情况,Redis可能会丢数据。但是如果个别用户购物车少了几件商品,问题也不大。也不是不能接受。
  3. MySQL支持丰富的查询,比如统计一下今天加购的总数。Redis查询起来就特别麻烦而且低效。

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

你可以感受到,我们设计存储架构的过程就是一个不断做选择题的过程。很多情况下,可供选择的方案不止一套,选择的时候需要考虑实现复杂度、性能、系统可用性、数据可靠性、可扩展性等等非常多的条件。需要强调的是,这些条件每一个都不是绝对不可以牺牲的,不要让一些“所谓的常识”禁锢了你的思维。

思考题

能不能把购物车数据存在MySQL中,并且使用Redis做缓存呢?