[skr shop]购物车设计之需求分析

skr shop是一群底层码农,因为被工做中的项目折磨的精神失常,加之因为程序员的自傲:别人设计的系统都是一坨shit,个人设计才是宇宙最牛逼,因而乎决定要作一个只设计不编码的电商设计手册。

项目地址:https://github.com/skr-shop/m...前端

对于一个电商来说,购物车是整个购买流程最重要的一步。由于电商发展到今天购物车不只仅只是为了完成打包下单的功能;也是收藏、对比、促销提醒、相关推荐的重要展现窗口。如此多的能力咱们该如何设计保证购物车的高性能、以及良好的扩展能力来知足将来的发展呢?git

今天开始咱们就以一个假定的场景来输出一个购物车设计:某某电商平台,是一个多租户模式(咱们前面的诸多设计都是多租户模式),用户能够把商品加入到购物车,并切按照商户纬度来展现、排序。固然购物车也支持常规的各类操做:选择、删除、清空、商品失效等。而且有相关的促销可以提醒用户。同时为了监控、运营,要支撑购物车数据同步到监控、数仓等能力。程序员

本文会从用户使用的角度以及服务端两个角度来说解系统的能力。本篇咱们的主要目的是说清楚购物车的能力以及一些逻辑。下一篇会进行购物车模型设计以及接口定义。github

用户视角

咱们先来定义一下在用户侧用户操做购物车的功能有哪些?后端

用户则需求

一个购物车基本的能力基本上都在上图中,下面咱们一一来分解。网络

操做

咱们从用户的角度来看,购物车对于用户来讲能够添加商品到购物车(加购物车、当即购买都属于一种添加方式);加入进购物车后,不想要了能够删除该商品(删一个、删多个、清空);想多买能够修改购买数量,发现钱不够能够减小购买数量;或者发现红色的比白色更漂亮,能够在购物车方便的进行更换规格;对于一些价格很贵的商品,可以在购物车添加一些保障服务(实际上是绑定的虚拟商品);在要去结算的时候,还会提供选择能力让用户决定哪些商品真的本次要购买。数据结构

经过上面的描述咱们能够看到这个过程是有其内在联系的。这里说一下关于选中功能,业界有两种作法,各有优劣,咱们来看一下。淘宝的产品选中状态是保存在客户端的,而且默认不选中,刷新、从新打开APP状态会消失;京东、苏宁这一类是保存在服务端,会记录用户选中状态。针对这两种状况各有优劣。并发

客户端:异步

  1. 性能,选中/不选中的逻辑直接放在本地作,减小网络请求
  2. 体验,多端不能同步,可是购物车相对来讲更像是一个收藏夹,每次用户本身选择也无可厚非
  3. 计算,价格计算时须要上传本地选中商品(也能够本地计算)
  4. 实现,主要靠客户端实现,与服务端无关,研发解耦合

服务端:性能

  1. 性能,每次操做选中都须要调用服务端,而该操做可能很频繁,除了网络损耗,服务端也须要考虑该如何快速找到修改的商品
  2. 体验,多端同步状态,记录历史状态
  3. 计算,服务端可获取数据,请求时无须上传额外数据
  4. 实现,服务端与客户端须要商定如何交互,以及返回数据(每次选中会致使价格变化),耦合在一块儿

我的认为这两种方式并没有谁具有明显优点,彻底是一种基于业务模式以及团队状况来作选择。咱们这里后续的设计会基于在服务端保存商品选中状态。

在整个操做逻辑中,有个两个比较重要的地方单独说明一下:购买方式与购物车内修改购买属性

购买方式

主要的购买方式有当即购买、加入购物车、拼团购三种方式。

首先普通的加入购物车没什么太多要说的。重点来看下当即购买与拼团。

当即购买在于操做上来讲就是选择商品后直接到了订单确认页面,没有购物车中去结算这一步。可是它的实现却能够依赖购物车的逻辑来作,咱们来看一下使用购物车与不使用购物车实现这个逻辑有什么差异?

若是使用购物车来实现,也就是用户点击当即购买时,商品本质上仍是加入到购物车中,但这个购物车却与原型的购物车不一样,由于该购物车只能加一个商品,而且每次操做都会被覆盖。在视角效果上也是直接从商品详情页面跳转到订单确认页面。来看看这种方式的好处

  1. 与购物车在订单确认、下单逻辑上一致,内部能够直接经过购物车获取数据
  2. 须要一个独立的专门用于一键购买的购物车来实现,内存有消耗

另一种实现方式使用一个新的数据结构,由于通常来讲一键购买更简单,它只须要商品信息、价格信息便可。每次交互都可以根据sku_id来获取。

  1. 订单确认、下单逻辑上须要进行改造,每次请求之间要传递约定参数
  2. 节省内存,上下交互经过sku_id来保证

咱们会采用使用在服务端一键购买以独立的购物车形式来实现。购物车的数据模型一致,保证了后续处理流程上的一致。

对于拼团,他其实分为两部分,首先是开团这个动做,当团成立后。咱们能够选择将成团的商品加入普通购物车,同时能够加购其它商品。也能够选择将成团商品加入一键购买的购物车,保证成团商品只能买一个。拼团模式更像是加入购物车的一个前置条件。本质上它对于购物车的设计没有影响。

购物车内修改购买属性

这里主要是指能够在购物车便捷的操做一些须要在spu纬度操做的事情,好比:变动规格(也就是更换sku),以及选择绑定到spu纬度的服务(保险、延保等)。

咱们重点说一下选择绑定的服务。例如:咱们买一个手机,厂家提供了延保、各类其它附加服务,通常状况这种服务都是虚拟商品。可是这有个特殊状况。这些保障服务首先不能单独购买,其次他是跟主商品的数量息息相关。好比买两个手机,若是选择了加购服务,那么这些服务的数量必须是2,这会是一个联动关系。

这些保障服务是不能进行单独购买的,它必定要跟特定的商品捆绑销售。

服务端在存储这部分数据时必定须要考虑如何保存这种层级关系,这部分咱们后面模型设计的时候你们会看到。

绑定商品关系

提醒

促销提醒很简单,返回的购物车数据,每个商品应该携带当前的促销信息。这部分重点在于怎么获取促销信息,会在服务端看到。

而后说下购物车数量的提醒,也就是显示当前购物车商品的数量。通常来讲进入到APP就会调用一个接口,获取用户的未读消息数、购物车商品数等。这里是须要很是高的读取速度。那么这种需求该如何知足呢?

方案一: 咱们能够设计一个结构保存了用户相关的这种提醒信息数量,每次直接读取这个数据便可。不须要去跟消息服务、购物车服务打交道拿这些数据。

方案二: 在消息、购物车的模型中均设计一个保存总数量的字段,在读取数据的接口中,经过并发的方式调用这些服务拿到数据后进行聚合,这样在速度上只取决于最慢的服务。

这里咱们的设计会采用 方案二,由于这样在某种程度上效率能够获得保证,同时整个系统的结构数据的一致性更容易获得保障。固然这里有个细节必定要注意,并发读取必定要设计超时,不要由于某个服务读数问题而致使拖累整个接口的性能。

接下来再来看看促销,这部分除了提醒,还须要提供对应的入口,让用户完成促销的操做。好比说某个商品有券,那么能够直接提供入口去领取;可凑单,有入口进入凑单列表并选择商品等。这部分须要解决的问题是服务端该如何及时从商品纬度拿到这些促销活动。

从用户的视角看完了,咱们再来站在研发的角度看看服务端有哪些事情要作

研发视角

仍是先来看看需求的汇总图:

服务端则需求

存储

对于存储,首选确定是内存存储,至于要不要落库,我以为没有必要。说下个人理由:

  1. 购物车的数据相对变化很是频繁,落库成本比较高,若是异步方式落库,很难保障一致性
  2. 极端状况,cache奔溃了,仅仅须要用户从新加入购物车,而且咱们能够经过cache的持久化机制来保证数据的恢复

因此对于购物车,咱们只会把数据彻底保存在内存中。

商品销售类型发生变化

如今咱们来讨论 商品销售类型发生变化 这个问题。这是什么意思呢?你们想一下:好比我把A商品加入到购物车,可是一直没有结算。这时运营说针对A商品搞一个活动,拿出10个库存5折购。那么问题来了,对于以前购物车中就有该商品的用户该如何处理?这里解决的主要问题是:购物车有该商品的用户不能直接以5折买。几种方案,咱们来看一下:

方案一: 促销配置后,全部购物车中有该商品的用户失效或删除,这个方案首先被pass,操做成本过高,而且用户体验差

方案二: 购物车中要区分同一个SKU,不一样销售类型。也就是说在咱们的购物车中不是按照SKU的纬度来加商品,而是经过 SKU+售卖类型 来生成一个惟一识别码。

能够看到 方案二 解决了同一个sku在购物车并存的问题,而且库存以前互相不影响。不过这里又有一个问题?商品的售卖类型(或者说这个标记),该怎么什么地方设置?好像商品系统能够设计、促销系统也能够设置。咱们的逻辑中会在促销系统中进行配置。由于商品属于基础逻辑,若是一改就是全局库存受到影响。活动结束后很难作到自动正常售卖。所以这个标记应该落到活动中进行设置(活动设置时会经过促销系统获取该商品以前的活动是否互斥,以确保配置的活动不会互相矛盾)。

依赖系统

购物车系统依赖了很是多的其它系统。

  • 商品系统
  • 库存系统
  • 促销系统
  • 结算系统

这些依赖的系统,有的是为了传输数据,有的是为了获取数据。咱们按照这两个纬度来看一下。

促销提醒与计算

服务端要解决的是促销的提醒与价格计算问题。

现来讲计算,针对这部分最佳的方式是,调用结算中心的价格计算。咱们来看一下购物车中的价格计算与订单结算时的价格计算的差别。

首先购物车中计算价格时不知道用户的地址,这会影响运费的计算;再是不知道用券的状况。那么其实若是解决了这两个问题,咱们就可让价格计算出自同一个逻辑,仅仅是部分入参不一样罢了。所以咱们这里计算时能够按照最高运费来计算,同时用券默认在购物车都不使用券。对于促销问题这里是能够经过促销系统确认选中的商品能够享受哪些价格的。所以促销的价格应该计算在内。

接下来在再来讲说如何为用户高效的提供促销的信息。先从咱们的配置视野出发。

咱们在配置一个促销活动或者发一张券时,都是将多个商品归到一个促销活动或者券的下面。若是按照活动、券的纬度来获取商品效率相对比较高。

活动-商品

可是在购物车的场景中发生了一个变化。咱们是须要从商品纬度获取到该商品的全部活动信息(全平台活动、店铺活动);
那么购物车中为了展现这些信息该怎么作?很常规的一个作法(也确实很多公司是这样):把全部活动信息取出来,遍历出全部跟该商品相关的信息。这种作法效率很低,而且没法知足大规模的应用场景,好比双十一期间。

所以这里为了知足该需求,促销系统须要提供一个能力按照商品获取对应促销(活动、券)。所以通常来说促销系统配置的活动不能仅仅是按照活动纬度存储,同时还须要生成一份商品纬度的促销信息。

商品-活动

购物车数据分析

对于购物车数据来讲,前端会经过埋点记录加入购物车数据的状况,可是前端埋点通常是记录触发了某个前端操做,可是并不知道该操做是否成功与否。以及没法及时了解当前总体购物车的数据状况。

为了让运营团队更完整的了解购物车当前状况,咱们经过后端打本地日志,而后经过日志收集的方式将日志同步给数据、监控等服务。

失效与排序

还有两个小部分没有讲到,一是商品该如何失效,好比:库存没有了、下架了;二是购物车中的商品是多个店铺的,排序的策略是什么?

因为本文咱们还只是讨论需求,不涉及具体的模型设计,所以只是介绍方案。首先是商品失效,这很像一个软删除操做,一旦设置,用户侧看到的商品将是没法进行结算的,只能进行删除操做。

对于排序咱们会采用的设计是:根据某个店铺在购物车中最后发生操做的时间,最新的操做确定在最上面。

结尾

经过上面咱们基本上搞清楚了购物车设计中咱们要作什么,依赖的系统要提供什么能力。下篇开始进入数据模型的设计、先后端接口设计。

若是你对购物车上面的需求还有哪些补充,欢迎留言。咱们一块儿来完善。

项目地址:https://github.com/skr-shop/m...

相关文章
相关标签/搜索