专栏名称: 石杉的架构笔记
专注原创、用心雕琢!十余年BAT一线大厂架构经验倾囊相授
目录
相关文章推荐
成都发布  ·  通知!考试时间定了 ·  昨天  
成都本地宝  ·  终于官宣!成都多场大型演唱会定档! ·  3 天前  
成都发布  ·  早安,成都!新闻来了 ·  2 天前  
成都本地宝  ·  即将上线!成都5000万消费券来了! ·  4 天前  
51好读  ›  专栏  ›  石杉的架构笔记

拉开差距的面试题:如何设计一个电商平台积分兑换系统??

石杉的架构笔记  · 公众号  ·  · 2020-11-16 12:30

正文


我的新课 《C2C 电商系统微服务架构120天实战训练营》 在公众号 儒猿技术窝 上线了,感兴趣的同学,可以长按扫描下方二维码了解课程详情:

课程大纲请参见文末

本文转自公众号:儒猿技术窝


目录

1.拉开差距的一类面试题

2.业务需求描述

3.对业务流程的思考

4.物流配送进度查询,考虑到了吗?

5.事务的保证

6.消息中间件的引入

7.重试机制的引入

8.引入幂等性机制

9.对这类面试题的总结


1、拉开差距的一类面试题

现在面试经常会遇到一类问题,面试官让你现场设计出某个业务场景下的一个系统,这个系统往往在业务或者技术上有一定难度,主要考察的是你多年积淀下来的系统设计的能力以及技术思维的能力。


类似的这类系统设计题目很多,比如:


  • 请你设计一个秒杀系统

  • 请你设计一个支撑百万用户的IM消息系统

  • 请你设计一个微信红包系统

  • 请你设计一个电商平台积分兑换系统


这些题目本身都是开放式命题,没有固定答案。遇到这种问题,一定不要慌,关键是在现场要思路清楚,有理有据,慢慢分析。


本文就其中一个问题: 设计一个电商平台的积分兑换系统 ,来详细阐述一下。文中会详细指出在系统设计的时候要考虑哪些要点,给大家展示出来这类问题思考的一个过程。



2、业务需求的描述


假设面试官现在给出来对于这个电商平台的积分兑换系统的相关需求如下:


  1. 用户在电商平台里平时通过购买商品、晒单评论可以有不断的积累积分

  2. 积累到足够的积分后,就可以在电商平台的积分兑换页面中,选择使用自己的积分来兑换一些礼品


需求其实就这么简单,那么面试官说了,针对这个业务场景给出你对这个机制实现的思考过程以及这里要注意的一些地方。



3、对业务流程的思考


如何思考?首先,用户不停的购买商品以及晒单评论,会不断的获取积分,那么是不是需要一张积分表,专门用来存储每个用户的积分呢?


没错,这个表是一定需要的,可以现场给出下述的表结构。


积分表

  • id (自增id主键)

  • user_id (用户id)

  • credit (积分)


继续来看,假设在积分兑换页面,用户选择用自己的20000积分兑换一瓶洗发水, 后台的逻辑应该如何设计呢?


这个也是必须得现场给出一个思考过程的,这个其实看起来简单,但是很多年纪较轻,经验不足的朋友,可能没法快速思考出来。


首先你要用20000积分去进行兑换,那么一定是必须要在积分表里扣减掉这20000积分的吧?所以在流程设计中,首先就得有一个20000积分扣减的过程。


其次,你用这20000积分兑换了什么东西呢?


所以你是不是还需要一张单独的表,叫做积分兑换记录表,记录下来你这个用户本次用多少积分兑换了一件什么商品?


这个积分兑换记录表的结构如下所示,你是不是需要在下面的那个表里插入一条记录,说这个用户本次用多少积分兑换了哪个商品?


积分兑换表

  • id (自增id主键)

  • user_id (用户id)

  • exchanged_credit (用于兑换的积分)

  • product_id (兑换的商品id)


最后,光是插入上述那条积分兑换记录是不够的,你必须得调用仓储业务模块的接口,通知仓储业务模块新增一条发货申请,而且应该是积分兑换对应的发货申请,这样保证仓库可以准备对应的商品进行发货。


这个发货申请大致对应如下的表结构:


发货申请表

  • id (自增id主键)

  • type (发货类型,1:购买,2:积分兑换)

  • credit_exchange_id (积分兑换表的id)

  • product_id (要发货的商品id)


其实这里的发货申请表简化了很多,按理说还得有发货商品的数量等等字段,但是这里可以简化处理也没事,毕竟是面试现场。


简单画出来这个流程大致如下所示。



4、物流配送进度查询, 考虑到了吗?


如果把上面那整个业务流程给面试官说了,就完事了吗?


当然不是!


你可以站在用户的角度考虑一下,你是不是肯定还需要查看积分兑换的记录?这个在积分兑换表里可以查看到你用多少积分兑换了什么商品。


但是你兑换商品的物流配送进度,能查看到吗?不能。所以你应该在业务流程里再考虑进去对应的物流配送的逻辑。


通常来说一个基本的逻辑,就是在生产发货申请单的时候,需要调用第三方物流公司的接口申请一个物流单,这样仓库管理员打包准备好商品,坐等物流公司商品收快递就可以了。


物流公司会根据物流单去进行配送,这个配送地址当然是用户自己在电商平台选择的自己的某个地址。


此时发货申请单的表结构是不是如下所示?


发货申请表

  • id (自增id主键)

  • type (发货类型,1:购买,2:积分兑换)

  • credit_exchange_id (积分兑换表的id)

  • product_id (要发货的商品id)

  • express_no (物流单号)


所以在生产发货申请单时,先得调用第三方物流公司的接口申请一个物流单,这样发货申请单中是有一个物流单号的,而且每个积分兑换记录都通过id跟发货申请单关联起来。


这样在页面上对每个兑换记录,是不是可以找到发货申请单中的物流单号,然后根据物流单号调用第三方物流公司的接口,去获取配送的进度?


这就是一个非常典型的业务系统的技术实现的逻辑思考,一个经验丰富合格的工程师,往往都具备了一定的业务思维,可以很好的根据业务系统中的用户逻辑来考虑,反推自己的系统技术实现逻辑。


上述整个过程,如下图所示:


5、事务的保证


业务流程整个捋顺之后,接下来就涉及到技术的考虑了。你得考虑一下,这种业务系统里怎么能没有事务呢?


扣减积分、新增积分兑换记录、新增发货申请单,这三个步骤必须是要么一起完成,要么一起失败的。也就是说,这三个步骤必须是在一个事务里的。


现在有一个问题,对一个电商平台自身的业务系统来说,仅仅包含积分服务。但是仓储服务一般是独立部署的一套系统,或者是一个独立的服务。


也就是说,扣减积分和新增积分兑换记录可以在一个服务里是一个事务,但是新增发货申请单,他是在另外一个服务里的,这个事务如何保证呢?


有朋友可能马上回答:用分布式事务啊!先别急,咱们可以先用最简单的模式来实现一下。


比如积分服务在一个事务代码块中,先执行扣减积分、新增积分兑换记录两个步骤。


然后记住,在事务代码块中,最后一步调用仓储服务的接口,如果接口调用成功,那么就可以提交事务了。如果接口调用失败,那么就抛异常让事务回滚,这样可以不可以?


这个流程如下所示:


积分服务 事务 {

-> 扣减积分

-> 新增积分兑换记录

-> 调用仓储服务

}


6、消息中间件的引入


上述设计其实理论上是没问题的,但是这里你忽略了一个问题,在这个业务场景中,积分服务是没有必要同步调用仓储服务的。


因为积分兑换是一个用户执行的操作,假设你的仓储服务在生成发货申请单的时候调用第三方物流公司的接口,被卡住了,或者失败了,怎么办?


此时可能导致用户在页面上看到积分兑换按钮点击之后,卡在那儿可能几十秒都无法执行成功,所以这个系统如此设计是错误的。


那应该怎么做呢?你必须得在这里引入消息中间件进行异步化的解耦,保证用户点击积分兑换按钮之后,尽快返回。如下图所示:



7、重试机制的引入


到这里就OK了吗?还没呢!


一旦引入消息中间件之后, 好处 是用户点击积分兑换按钮,直接就是在积分服务里扣减积分以及新增积分兑换记录,然后发送一条消息到消息中间件里就结束了,速度很快,保证了用户体验。


但是 坏处 就是,万一仓储服务执行新增发货申请失败了怎么办?


这个时候就需要引入可靠消息服务了,他需要去保证仓储服务一定会完成新增发货申请这个事。


具体的流程如下:

  • 积分服务发送消息给可靠消息服务,可靠消息服务在消息表中新增记录,然后发送消息到MQ(消息中间件)








请到「今天看啥」查看全文


推荐文章
成都发布  ·  通知!考试时间定了
昨天
成都本地宝  ·  终于官宣!成都多场大型演唱会定档!
3 天前
成都发布  ·  早安,成都!新闻来了
2 天前
成都本地宝  ·  即将上线!成都5000万消费券来了!
4 天前
网易梦幻西游手游  ·  新角色漠少君与虎头怪不得不说的故事……
7 年前
高考数学左老师  ·  2015浙江文科数学第8题
7 年前