1.主要功能是在用户购买商品时和下单前,临时存储用户想购买的商品。购物车对数据可靠性和性能要求不高。是整个电子商务系统中比较容易设计和实现的一个子系统。购物车系统主要功能:在购物车列表页添加商品到购物车(以下简称“加购”),发起结算下单,所有界面显示的购物车小图标支持这些功能。如何设计存储模型?只有一个“购物车”实体。2、主要属性打开京东购物车页面:SKUID(商品ID)、数量、购买时间、查看状态备注:图片来源于网络,仅对本文中某个问题的介绍、评论和解释文章,并正确引用。“checkstatus”属性,即购物车界面每件商品前的小复选标记,表示结账时下单时是否包含该商品。至于商品价格、总价、商品介绍等,可以从其他系统实时获取,无需保存在购物车系统中。购物车在功能上很简单,但是在设计购物车系统的存储时还是有一些问题需要考虑的。3.原理3.1思考3.1.1用户未登录,用户在浏览器中购买,关闭浏览器再打开。刚才购买的产品还在吗?存在。如果用户没有登录,购买的产品也会保存在用户的电脑上。即使关闭浏览器再打开,购物车中的商品依然存在。3.1.2如果用户没有登录,用户在浏览器中添加了购买,然后登录,刚才添加的商品还在吗?存在。如果用户先购买,再登录,登录前购买的商品会自动合并到用户名中,所以登录后购物车里还有登录前购买的商品。3.1.3关闭浏览器再打开,上一步购买的商品还在吗?不存在。关闭浏览器并再次打开它。这时就变成了未登录状态,但是之前未登录时购买的商品已经合并到刚刚登录用户的用户名中,所以购物车是空的。3.1.4再次打开手机,用同一个用户登录,第二步购买的产品还在吗?存在。同一个用户用手机登录,看到的是用户的购物车。这时候无论是登录手机APP、电脑端还是微信,只要是同一个用户,看到的都是同一个购物车,所以第2步的追加购买是存在的。如果不仔细考虑这些问题,用户在使用购物车时就会感到不自在。要么是多买的商品无缘无故丢失,要么购物车里多了一些商品。要解决以上问题,只要在存储设计中把握好以下3.2的原则,如果没有登录,需要将购物车中的物品暂存。用户登录时,将临时购物车中的商品合并到用户的购物车中,清空临时购物车用户登录后,需要在浏览器、手机APP、微信中同步购物车中的商品等购物车系统需要保存两种购物车:未登录时的“临时购物车”“用户购物车”4“临时购物车”存储设计4.1保存在客户端还是服务端?如果有服务器,每个临时购物车都必须有一个全球唯一的标识符,这不容易设计。保存在服务器上,也浪费服务器资源。所以必须在客户端保存:节省服务器存储资源,不存在购物车识别问题。每个客户只需要保存自己唯一的购物车,无需身份识别。客户端存储的选择不多:Session不适合。SESSION的保留时间很短,SESSION的数据实际上保存在服务器端的CookieLocalStorage中。浏览器的LocalStorage类似于App的本地存储,用LocalStorage表示。Cookie和LocalStorage都可以用来保存购物车数据。选择哪个更好?每个都有其优点和缺点。在这种场景下,使用Cookie和LocalStorage的关键区别在于,客户端和服务端的每次交互都会自动来回携带Cookie数据,以便服务端读写客户端Cookie中的数据和LocalStorage中的数据,只能由客户端访问,使用Cookie存储,实现简单。购物车的加减合并过程,由于服务端可以读写cookies,所以所有的逻辑都可以在服务端实现,客户端和服务端的请求量比较少。使用LocalStorage存储,实现比较复杂,客户端和服务端都必须实现业务逻辑,但是LocalStorage的好处是它的存储容量远大于Cookie的4KB上限,而且不需要就像Cookie一样,不管用不用,每次请求都需要用它,可以节省带宽。因此,可以选择Cookie或LocalStorage来存储“临时购物车”,可以根据优缺点选择:设计是小型电商,cookie存储更容易实现。您的电子商务是面向批发行业用户的。用户需要购买大量商品,cookie容量可能不够用。选择LocalStorage比较合适。无论哪种存储方式,临时购物车中保存的4.2数据格式都是一样的。参考实体模型设计,JSON表示:{"cart":[{"SKUID":8888,"timestamp":1578721136,"count":1,"selected":true},{"SKUID":6666,"timestamp":1578721138,"count":2,"selected":false}]}5用户购物车存储设计用户购物车要保证多端数据同步,数据要保存在服务器上。总体思路:设计一张购物车表,数据存储在MySQL中。表结构也参考了实体模型:需要在user_id上建立索引,因为在查询购物车表时,user_id作为查询条件。也可以选择速度更快的Redis保存购物车数据:用户ID=KeyRedisHASH=Value,保存购物车中的商品,如:{"KEY":6666,"VALUE":[{"FIELD":8888,“FIELD_VALUE”:{“timestamp”:1578721136,“count”:1,“selected”:true}},{“FIELD”:6666,“FIELD_VALUE”:{“timestamp”:1578721138,“count”:2,“selected":false}}]}为了便于理解,在Redis中使用JSON表示HASH的数据结构:KEY中的值6666为用户IDFIELD,用于存放商品IDFIELD_VALUE为JSON字符串,节省购买时间,商品quantity和checkstatus读写性能,Redis比MySQL快很多,那么Redis就一定比MySQL好吗?5.1MySQLV.SRedisRedis的存储性能至少比MySQL高一个数量级,响应时间更短,支持更多的并发请求。MySQL的数据可靠性优于Redis,因为Redis是异步刷盘的。如果服务器断电,Redis可能会丢失数据。但是考虑到购物车中的数据,可靠性要求不高,少量数据丢失的后果是个别用户的购物车少了几个商品,问题不大。所以在购物车场景下,Redis数据可靠性不高的劣势。并不是说MySQL不能接受另一个优势:它支持丰富的查询方式和交易机制,但是对于购物车的核心功能来说就没用了。但是每个电子商务系统都有其独特的要求。如果需要通过其他方式访问购物车数据,比如统计今天购买的商品总数,用MySQL存储数据很容易,但是用Redis存储数据就麻烦了。除了综合比较效率低下,考虑到需求的变化,推荐使用MySQL存储购物车数据。如果追求性能或者高并发,也可以选择使用Redis。设计存储架构的过程是一个不断决策的过程。在许多情况下,有不止一组选项可供选择。选择时,需要考虑实现复杂度、性能、系统可用性、数据可靠性和可扩展性。这些条件中的每一个都不是绝对不可牺牲的。不要让一些“所谓的常识”禁锢了你的思维。例如,一般认为数据绝不能丢失,即不能牺牲数据的可靠性。然而,使用Redis而不是MySQL来存储用户购物车意味着牺牲数据可靠性来换取高性能。丢失少量数据的概率非常低是可以接受的。性能提升的好处远远超过丢失少量数据的代价,所以这个选择是值得的。如果不考虑需求变化的因素,牺牲一点点数据的可靠性来换取大幅度的性能提升,Redis是最优方案。6总结购物车系统主要功能包括:添加购买、购物车列表页和结算订单核心实体:只有一个“购物车”实体至少包括:购物中的SKUID、数量、添加购买时间和查看状态属性cart在设计存储时,为了保证用户登录前后购物车中的数据能够无缝衔接,除了每个用户的“用户购物车”外,还必须实现一个“临时购物车”保存用户未使用的数据。登录时购买的商品,用户登录后自动合并“临时购物车”和“用户购物车”。临时购物车存储在客户端浏览器或App中,可以存储在Cookie或LocalStorage中。用户的购物车存储在服务器端,可以随意使用:Redis存储会具有更高的性能,可以支持更多的并发请求。MySQL是一种比较常规和通用的方法,易于响应变化,具有更好的系统扩展性。考虑到用户购物将汽车数据存储在MySQL或Redis中各有优缺点。购物车数据可以存入MySQL,用Redis缓存吗?兼顾两者的优点不是更好吗?如果可行,如何保证Redis和MySQL数据中数据的一致性?使用Redis缓存购物车库在技术上是可行的。但考虑一下:这值得吗?每个人的购物车都不一样,所以这个缓存的读写比不会有很大的差异,缓存命中率不会太高,缓存的好处有限,维护缓存会增加系统的复杂度。所以我们要自己权衡一下,值不值?除非是非常大规模的系统,否则没有必要设置这个缓存。如果不需要这样的缓存,应该使用什么缓存更新策略?
