0

1

2

3

4

5

6

7

8

9

0

1

{{ noReadMessageTotal }}

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

尚硅谷Java技术之北京高频面试题:第十一章 电商项目篇之尚品汇商城

晴天 晴天 | 359 | 649天前

尚硅谷Java技术之北京高频面试题

版本:V6.0

尚硅谷Java技术中心

第十一章 电商项目篇之尚品汇商城

一、常见共性问题

1、介绍下最近做的项目

可以从2个方向出发

介绍项目背景、项目功能和自己负责的功能模块

介绍项目背景、项目使用技术栈和自己负责的功能模块

1.1 项目背景:

可以介绍项目是什么类型的(B2C、B2B2C、O2O这类),为什么要做这个项目,

有工作经验的找工作一般这样介绍:项目是自己公司开发,自己运营的,然后不断加功能进行迭代和维护;或者是项目定制的,给甲方客户开发的一个项目,上线后不负责维护和迭代,这样避免了很多后期问题,这两种都可以。

咱们可以借鉴以上的方式去介绍,刨除公司情况,以学习为主。

1.2 项目功能:

结合项目,进行主要的功能模块阐述,可以结合电商项目的核心购物流程去说:后台管理系统(商品的管理)、商品详情、商品搜索、购物车、单点登录+社交登录、订单、支付、秒杀等等。

1.3 技术栈:

使用springboot整合SpringCloud
以及MyBatis-Plus进行微服务构建,使用nacos作为注册中心和配置中心,使用feign进行服务远程调用,使用gateway网关进行请求负载、请求过滤、统一鉴权和限流,使用Sentinel进行服务的熔断和降级,使用Spring
Cloud
Sleuth进行链路追踪,针对于项目图片文件资源较多,采用FastDFS进行文件资源存储,使用redis数据库进行数据缓存以及分布式锁的实现,使用ElasticSearch进行商品的搜索业务实现…(这块基础架构说完后,主要结合自己负责的功能模块去说技术点的应用)

1.4 自己负责的功能模块:

已简历为主,简历上写了哪几个,就说那几个,一定要知道自己简历写的什么内容。

1.5 项目介绍参考:

尚品汇商城是B2C模式的综合性在线销售平台。商城分为后台管理部分与用户前台使用部分。后台管理部分包括:商品管理模块(商品分类、品牌、平台属性、SPU与SKU以及销售属性、商品上下架和商品评论管理等)、内容广告模块、库存管理模块、订单管理模块、促销管理(秒杀等商品设置)、客户模块、统计报表模块和系统基础权限等模块。

用户前台使用部分:商城首页、商品搜索(可按条件查询展示)、商品详情信息展示、购物车、用户单点登录和社交登录(微信登录)、用户会员中心、订单的创建修改、展示以及在线支付(支付宝、微信)、物流模块、商品评论以及秒杀活动等功能。

1.6 项目架构图:

346544.png

1.7 整体业务介绍:

首页 静态页面,包含了商品分类,搜索栏,商品广告位。
全文搜索 通过搜索栏填入的关键字进行搜索,并列表展示
分类查询 根据首页的商品类目进行询
商品详情 商品的详细信息展示
购物车 将有购买意向的商品临时存放的地方
单点登录 用户统一登录的管理
结算 将购物车中勾选的商品初始化成要填写的订单
下单 填好的订单提交
支付服务 下单后,用户点击支付,负责对接第三方支付系统。
订单服务 负责确认订单是否付款成功,并对接仓储物流系统。
仓储物流 独立的管理系统,负责商品的库存。
后台管理 主要维护类目、商品、库存单元、广告位等信息。
秒杀 秒杀抢购完整方案

1.8 后台管理系统功能:

电子商务网站整个系统的后端管理,按功能划分为九大模块,包括商品组织管理、订单处理、内容发布管理等模块。

1.8.1 后台主页:

各类主要信息的概要统计,包括客户信息、 订单信息、商品信息、库存信息、评论和最近反馈等。

1.8.2 商品模块:

1).商品管理:

商品SPU和SKU的添加、修改、 删除、复制、批处理、商品计划上下架、SEO、商品多媒体上传等,可以定义商品是实体还是虚拟,可以定义是否预订、是否缺货销售等。

2).商品分类管理:

树形的商品目录组织管理,并可以设置品类关联与商品推荐。

3).商品平台属性管理:

定义商品的属性类型,设置自定义属性项。

4).品牌管理:

添加、修改、删除、上传品牌 LOGO。

5).商品评论管理:

商品评论的搜索、条件查询列表展示、回复、删除等功能。

1.8.3 销售模块:

1).促销秒杀管理:

设置秒杀商品、购物车促销和 优惠券促销三类,可以随意定义不同的促销规则,满足日常促销活动:购物折扣、购物赠送积分、购物赠送优惠券、购物免运输费、特价商品、特定会员购买特定商品、折上折、买二送一等。

2).礼券、积分管理:

比如添加、发送礼券和积分

3).关联/推荐管理:

基于规则引擎,可以支持多种推荐类型,可手工添加或者自动评估商品。

1.8.4 订单模块:

1).订单管理:

可以编辑、解锁、取消订单、 拆分订单、添加商品、移除商品、确认可备货等,也可对因促销规则发生变化引起的价格变化进行调整。订单处理完可发起退货、换货流程。

2).支付:

常用于订单支付信息的查看和手工 支付两种功能。手工支付订单,常用于"款到发货"类型的订单,可理解为对款到发货这类订单的一种补登行为。

3).结算:

提供商家与第三方物流公司的结算 功能,通常是月结。同时,结算功能也是常用来对"货到付款"这一类型订单支付后的数据进行对帐

1.8.5 库存模块:

1).库存管理:

引入库存的概念,不包括销售规则为永远可售的商品,一个SKU对应一个库存量。库存管理提供增加、减少等调整库存量的功能;另外,也可对具具体的SKU设置商品的保留数量、最小库存量、再进货数量。每条SKU商品的具体库存操作都会记录在库存明细记录里边。

2).查看库存明细记录。
3).备货/发货:

创建备货单、打印备货单、打印发货单、打印快递单、完成发货等一系列物流配送的操作。

4).退/换货:

对退/换货的订单进行收货流程的处理。

1.8.6 内容模块:

1).内容管理:

包括内容管理以及内容目录管理。内容目录由树形结构组织管理。类似于商品目录的树形结构,可设置目录是否为链接目录。

2).广告管理:

添加、修改、删除、上传广告、 定义广告有效时限。

3).可自由设置商城导航栏目以及栏目内容、栏目链接。

1.8.7 客户模块:

1).客户管理:

添加、删除、修改、重设密码、 发送邮件等。  ** **

2).反馈管理:

删除、回复。

3).消息订阅管理:

添加、删除、修改消息组 和消息、分配消息组、查看订阅人。

4).会员资格:

添加、删除、修改。

1.8.8 系统模块:

1).安全管理:

管理员、角色权限分配和安全日志

2).系统属性管理:

用于管理自定义属性。可关联模块包括商品管理、商品目录管理、内容管理、客户管理。

3).运输与区域:

运输公司、运输方式、运输 地区。

4).支付管理:

支付方式、支付历史。

5).包装管理:

添加、修改、删除。

6).数据导入管理:

商品目录导入、商品导入、 会员资料导入。

1.8.9 报表模块:

缺省数个统计报表,支持时间段过滤、支持按不同状态过滤、支持HTML、PDF和Excel格式的导出和打印。

1.用户注册统计   2.低库存汇总   3.缺货订单   4.订单汇总   5.退换货

2、项目开发周期:

开发、维护和运营一体化的: 开发周期8个月左右,后期维护与迭代时间会更长

项目定制: 前期架构+数据库设计+编码+开发+测试解bug共7个月左右进行项目交付

培训学习项目: 20天教程(咱们是学习20天课程)

3、项目参与人数:

一般公司: 项目经理(PM)1人、产品(PD)2人、界面设计(UI)2人、前端
3人、Java后台(DE)6人,其中1人是开发组长、测试(QA)2人、运维(SRE)1人

培训学习项目: 根据课程内容编写代码,自己实现部分功能

4、公司开发相关各岗位职责:

4.1 项目经理(PM):

企业建立以项目经理责任制为核心,对项目实行质量、安全、进度、成本管理的责任保证体系和全面提高项目管理水平设立的重要管理岗位。职责:

1、负责软件项目管理及计划实施;

2、具备较强管理、协调及沟通能力,帮助开发人员解决开发过程中遇到的技术问题,做好日常的开发团队管理工作;

3、与各团队协同工作,确保开发工作正常顺利的开展;

4.2 产品(PD):

企业中专门负责产品管理的职位,负责调查并根据用户的需求,确定开发何种产品,选择何种技术、商业模式等。并推动相应产品的开发组织,他还要根据产品的生命周期,协调研发、营销、运营等,确定和组织实施相应的产品策略,以及其他一系列相关的产品管理活动。职责:

  1. 根据公司产品及用户需求,结合市场调研情况,进行产品规划;

2. 负责用户沟通、需求分析诊断;

3. 负责产品定位、用户体验流程定位及产品设计;

4. 推动、协调与控制产品策划及研发工作,保证产品需求的有效实现;

5. 负责产品持续升级,不断提升用户满意度及忠诚度;

6. 对行业及竞争产品的分析,跟踪最新发展趋势,并提交分析报告。

4.3 界面设计(UI):

对软件的人机交互、操作逻辑、界面美观的整体设计。职责:

1、负责公司产品PC端和移动端的UI界面设计工作;

2、配合完成校样修改和界面调整;

3、深入了解负责的产品,并通过各种设计形式和视觉语言让用户感受到产品的优点和特性;

4、跟进设计的变化和需求,注重相关文档的整理、资料的收集;能独立完成界面设计工作。

4.4 开发组长(TL):

其实就是个更小一点的项目经理。其职责:1、
参与软件的设计负责系统需求的分析,进行系统设计和数据库设计;

2、 解决开发过程中技术问题和提供解决办法;

3、 能够带领小组负责模块的功能开发;

4、 负责项目组代码的审查工作,有效地控制项目的质量风险。

4.5 测试(QA):

测试工程师,软件质量的把关者,工作起点高,发展空间大。职责:
1.理解、分析需求文档,挖掘、细化需求;

2.根据软件需求及设计文档编写测试用例,参与文档评审并维护相关文档;

3.准备测试数据,执行测试用例,记录测试结果,整理测试报告;

4.负责BUG的提交、跟踪、验证、关闭;

5.负责测试部门测试环境及BUG系统管理与维护。

6.对产品进行必要的功能,性能,安全,兼容性及其它方面的测试工作;

7.公司安排的其它工作。

4.5 运维(SRE):

运维工程师最基本的职责都是负责服务的稳定性。

1.
产品发布前:负责参与并审核架构设计的合理性和可运维性,以确保在产品发布之后能高效稳定的运行。

2.
产品发布阶段:负责用自动化的技术或者平台确保产品可以高效的发布上线,之后可以快速稳定迭代。

3.
产品运行维护阶段:负责保障产品7*24H稳定运行,在此期间对出现的各种问题可以快速定位并解决;在日常工作中不断优化系统架构和部署的合理性,以提升系统服务的稳定性。

5、项目开发流程:

5.1 需求分析

image.png

项目前期主要指的是项目业务需求调研、包括配合用户制定项目建设方案、技术规范书、配合市场人员进行售前技术交流等环节,此阶段应该组织由售前工程师、需求分析师以及系项目经理等组成一个临时小组,负责跟踪项目。这个小组根据项目的大小和客户的要求确定小组成员。

项目前期小组的工作是项目的开始,这个小组工作成绩的优劣、工作质量的高低,将直接影响项目的成败。因此,从管理层的角度,一定要重视这个环节。

项目前期小组需要完成的工作包括以下方面:

1、 客户的各种项目前期要求,如:方案介绍、业务需求编写等

2、 提交项目可行性分析报告,包括成本/效益分析

3、 提交项目建议方案

4、 提交业务需求说明书或需求分析说明书

5.2 系统设计

image.png

系统设计是决定项目或软件系统"怎样做"的过程,这个过程回答了系统应该如何实现的问题。从软件工程的角度,设计阶段大约是整个项目开发成本的25%,所以,设计团队以及该团队的工作成绩对于整个系统来说至关重要。

人员需求

设计团队一般由3—8名设计人员组成,从这个阶段起,项目需要一名项目经理,行使项目组的各种管理职能。设计团队的成员具体包括:

1名项目经理

包括1—2名项目前期成员

1名系统构架师

1名数据库设计人员

1名用户界面设计人员组成

设计团队需要完成的工作包括:

1、项目开发计划

2、确定系统软硬件配置最佳方案

3、确定系统开发平台以及开发工具

4、确定系统软件结构

5、确定系统功能模块以及各个模块之间的关系

6、确定系统测试方案

7、提交系统数据库设计方案

8、提交系统概要设计文档

由于应用软件需求经常变化,因此设计需要考虑系统可扩展性,并需要在设计过程中对于重要的环节和用户进行及时沟通。

5.3 编码开发

image.png

将用户的需求变成真正可用的软件系统,是通过编码和系统实现阶段来完成的。虽然软件的质量主要取决于系统设计的质量,但是编码的途径和实现的具体方法对程序的可靠性、可读性、可测试性和可维护性产生深远的影响。

人员需求

这个阶段要根据用户对项目进度的要求灵活组织开发团队。为了工作的连贯性,同时也为了解决在开发过程中用户需求有可能变化的因素,开发团队应该保留1—3名设计团队的成员。

人员分工

开发过程中,项目经理的角色非常重要,项目经理负责项目组开发人员的日常管理,控制项目的进度,负责和设计部门、市场部门以及客户之间进行必要的沟通。这个阶段通常是多个部门的人员共同组成一个项目组,因此,项目管理的一定要保证统一管理,理想状态是项目经理全权负责项目组人员的人员工作安排、业绩考核、工资奖金等,因为项目经理最了解项目组成员的工作态度和工作业绩。

一般在大型项目开发团队中,应该设立专门的技术经理岗位,负责对项目组的技术方案进行管控,技术经理最好是由设计团队中抽调出来。技术经理在项目开发过程中需要注意程序风格、编码规范等问题,并必须进行有效的代码管理(版本管理)。

开发过程还应该进行系统的单元测试工作,确保各个独立模块功能的正确性和性能满足需求说明书的要求。

开发团队应该完成的工作包括:

1、 系统的实现代码编写

2、 单元测试

3、 提交源代码清单

4、 提交单元测试报告

5.4 系统测试

image.png

5.5 部署实施

image.png

由于从事的应用软件的开发,因此,在开发完成之后经常会有系统集成、软件的安装等工作。这个阶段还经常伴随着新的业务需求和本地化需求的产生,因此将会有一部分的开发工作需要在这个阶段完成。

6、项目版本控制:

使用git进行版本控制,剩下的主要是对git仓库的一些列操作,要记住操作命令,以及分支切换等等。

7、一般项目服务器数量:

开发测试阶段:

开发在自己电脑上开发,代码提交到git仓库(gitlab、gitee等)的开发分支,到测试时,公司有1-2台测试服务器,把开发分支代码合并到测试分支,使用jenkins进行测试环境代码部署,测试人员进行测试。

生产环境:

为了保证高可用,首先每个服务都要进行
集群部署,包括项目中依赖的第三方服务,这样的话,服务器的数量是很庞大的,以尚品汇商城所学功能实现为例,如下:

Nginx2台(主备);Nacos
3台(官方推荐最少3台);项目中有服务数量*2(19*2=38)共需要38台;redis无中心化集群6台(3主3从),如果是主从哨兵集群5台;mysql数据库(读写分离的情况下,1主2从
4*3
=12)共12台;ES集群3台;rabbitmq集群2台;fastDFS集群(保证高可用情况下,traker2台,storage2组4台)共6台。

以上所述
服务器数量一共为72台,数量很多,以目前市场硬件服务器平均一台5万块钱来计算,72*5=360万,投入成本和维护成本很大,在项目前期没有大用户量的情况下,不建议。

针对于这个问题,如果是项目定制(外包)的话,可以由甲方(客户)自己去部署,这种情况也是存在的。

还有一种情况是在项目前期没有那么大的用户量情况下,可以采用单机(主备)部署方案,把所有服务部署同一台服务器上,进行资源节省。

8、上线后QPS并发量,用户量、同时在线人数并发数等问题:

建议采用项目定制方案:项目给客户做的,甲方的数据我们拿不到。

但是要了解以下数据关键词:

(1)QPS(TPS):每秒钟request/事务 数量

(2)并发数: 系统同时处理的request/事务数

(3)响应时间: 一般取平均响应时间

QPS(TPS)= 并发数/平均响应时间或者并发数 = QPS*平均响应时间
一个典型的上班签到系统,早上8点上班,7点半到8点的30分钟的时间里用户会登录签到系统进行签到。公司员工为1000人,平均每个员上登录签到系统的时长为5分钟。可以用下面的方法计算。
QPS = 1000/(30*60) 事务/秒 平均响应时间为 = 5*60 秒 并发数=
QPS*平均响应时间 = 1000/(30*60) *(5*60)=166.7

说明:

一个系统吞吐量通常由QPS(TPS)、并发数两个因素决定,每套系统这两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统的吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换、内存等等其它消耗导致系统性能下降。

我们做项目要排计划,可以多人同时并发做多项任务,也可以一个人或者多个人串行工作,始终会有一条关键路径,这条路径就是项目的工期。系统一次调用的响应时间跟项目计划一样,也有一条关键路径,这个关键路径是就是系统影响时间;
关键路径是有CPU运算、IO、外部系统响应等等组成。

如果非要说,以下提供一套参数,但是仅供参考,可以根据自己设计适当调整:

用户总量 几万+,日活 3000+,月活 12W+,一个月PV 30W+,并发量 500+

9、你们项目的微服务是怎么拆分的,拆分了多少?

根据功能模块进行拆分,有多少功能模块就基本上拆出来多少个服务。

10、如何解决并发问题的?

尚品汇商城是微服务架构构建,集群部署,数据库的分库分表读写分离,Redis缓存,RabbitMQ消息异步解耦,页面静态化等这些都是解决并发的手段。

开发层面:微服务架构、缓存(Redis)、异步(MQ)、队排好(限流和削峰)

部署层面:集群(高可用)和负载均衡----Nginx、Gateway、Feign

硬件层面:CPU性能、硬盘(SSD)性能、内存大小

网络层面:增加网络带宽、网络加速器

11、如何保证接口的幂等性?

1.
根据状态机很多时候业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态。如果这些状态的值是有规律的,按照业务节点正好是从小到大,我们就能通过它来保证接口的幂等性。假如id=123的订单状态是已支付,现在要变成完成状态。update
`order` set status=3 where id=123 and
status=2;第一次请求时,该订单的状态是已支付,值是2,所以该update语句可以正常更新数据,sql执行结果的影响行数是1,订单状态变成了3。后面有相同的请求过来,再执行相同的sql时,由于订单状态变成了3,再用status=2作为条件,无法查询出需要更新的数据,所以最终sql执行结果的影响行数是0,即不会真正的更新数据。但为了保证接口幂等性,影响行数是0时,接口也可以直接返回成功。

具体步骤:

1 用户通过浏览器发起请求,服务端收集数据。

2 根据id和当前状态作为条件,更新成下一个状态

3
判断操作影响行数,如果影响了1行,说明当前操作成功,可以进行其他数据操作。

4 如果影响了0行,说明是重复请求,直接返回成功。

主要特别注意的是,该方案仅限于要更新的表有状态字段,并且刚好要更新状态字段的这种特殊情况,并非所有场景都适用。

2.
加分布式锁其实前面介绍过的加唯一索引或者加防重表,本质是使用了数据库的分布式锁,也属于分布式锁的一种。但由于数据库分布式锁的性能不太好,我们可以改用:redis或zookeeper。鉴于现在很多公司分布式配置中心改用apollo或nacos,已经很少用zookeeper了,我们以redis为例介绍分布式锁。目前主要有三种方式实现redis的分布式锁:

1 setNx命令

2 set命令

3 Redission框架

具体步骤:

1
用户通过浏览器发起请求,服务端会收集数据,并且生成订单号code作为唯一业务字段。

2 使用redis的set命令,将该订单code设置到redis中,同时设置超时时间。

3 判断是否设置成功,如果设置成功,说明是第一次请求,则进行数据操作。

4 如果设置失败,说明是重复请求,则直接返回成功。

3. 获取token

除了上述方案之外,还有最后一种使用token的方案。该方案跟之前的所有方案都有点不一样,需要两次请求才能完成一次业务操作。

第一次请求获取token

第二次请求带着这个token,完成业务操作。

具体步骤:

1 用户访问页面时,浏览器自动发起获取token请求。

2 服务端生成token,保存到redis中,然后返回给浏览器。

3 用户通过浏览器发起请求时,携带该token。

4
在redis中查询该token是否存在,如果不存在,说明是第一次请求,做则后续的数据操作。

5 如果存在,说明是重复请求,则直接返回成功。

6 在redis中token会在过期时间之后,被自动删除。

12、你们项目中有没有用到什么设计模式?

这个建议提前去了解几种常见的设计模式及其应用场景,将其套用到项目的某个场景中,以下提供几种常见的设计模式及其应用场景

1) 单例模式。

单例模式是一种常用的软件设计模式。

在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。

应用场景:如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

2) 工厂模式。

工厂模式主要是为创建对象提供了接口。

应用场景如下:

a、 在编码时不能预见需要创建哪种类的实例。

b、 系统不应依赖于产品类实例如何被创建、组合和表达的细节。

3) 策略模式。

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换。此模式让算法的变化独立于使用算法的客户。

应用场景如下。

a、 一件事情,有很多方案可以实现。

b、我可以在任何时候,决定采用哪一种实现。

c.、未来可能增加更多的方案。

d、 策略模式让方案的变化不会影响到使用方案的客户。

举例业务场景如下。

系统的操作都要有日志记录,通常会把日志记录在数据库里面,方便后续的管理,但是在记录日志到数据库的时候,可能会发生错误,比如暂时连不上数据库了,那就先记录在文件里面。日志写到数据库与文件中是两种算法,但调用方不关心,只负责写就是。

4) 观察者模式。

观察者模式又被称作发布/订阅模式,定义了对象间一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

应用场景如下:

a、对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。

b、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

5) 迭代器模式。

迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

应用场景如下:

当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍
历的时候,就应该考虑用迭代器模式。其实stl容器就是很好的迭代器模式的例子。

6) 模板方法模式。

模板方法模式定义一个操作中的算法的骨架,将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。

应用场景如下:

对于一些功能,在不同的对象身上展示不同的作用,但是功能的框架是一样的。

13、生产环境出问题,你们是怎么排查的?

生产环境出问题一般由多方面引起,可以由多方面进行排查,可以借鉴以下链接文章进行参考,面试的时候只需提出大概的思路即可:

https://blog.csdn.net/GitChat/article/details/79019454

14、你做完这个项目后有什么收获?

首先,在数据库方面,我现在是真正地体会到数据库的设计真的是一个程序或软件设计的重要和根基。因为数据库怎么设计,直接影响到一个程序或软件的功能的实现方法、性能和维护。由于我做的模块是要对数据库的数据进行计算和操作的,所以我对数据库的设计对程序的影响是深有体会,就是因为我们的数据库设计得不好,搞得我在对数据库中的数据进行获取和计算利润、总金时,非常困难,而且运行效率低,时间和空间的复杂也高,而且维护起来很困难,过了不久,即使自己有注释,但是也要认真地看自己的代码才能明白自己当初的想法和做法。加上师兄的解说,让我对数据库的重要的认识更深一层,数据库的设计真的是重中之重。

其次,就是分工的问题。虽然这次的项目我们没有在四人选出一个组长,但是,由于我跟其他人都比较熟,也有他们的号码,然后我就像一个小组长一样,也是我对他们进行了分工。俗话也说,分工合作,分好了工,才能合作。但是这次项目,我们的分工却非常糟糕,我们在分工之前分好了模块,每个
责哪些模块。本以为我们的分工是明确的,后来才发现,我们的分工是那么的一踏糊涂,一些功能上紧密相连的模块分给了两个人来完成,使两个人都感到迷惘,不知道自己要做什么,因为两个人做的东西差不多。我做的,他也在做,那我是否要继续做下去?总是有这样的疑问。从而导致了重复工作,浪费时间和精力,并打击了队员的激情,因为自己辛辛苦苦写的代码,最后可能没有派上用场。我也知道,没有一点经验的我犯这样的错是在所难免,我也不过多地怪责自己,吸取这次的教训就好。分工也是一门学问。
再者,就是命名规范的问题。可能我们以前都是自己一个人在写代码,写的代码都是给自己看的,所以我们都没有注意到这个问题。就像师兄说的那样,我们的代码看上去很上难看很不舒服,也不知道我们的变量是什么类型的,也不知道是要来做什么的。但是我觉得我们这一组人的代码都写得比较好看,每个人的代码都有注释和分隔,就是没有一个统一的规范,每个人都人自己的一个命名规则和习惯,也不能见名知义。还有就是没有定义好一些公共的部分,使每个人都有一个自己的"公共部分",从而在拼起来时,第一件事,就是改名字。而这些都应该是在项目一开始,还没开始写代码时应该做的。
然后,我自己在计算时,竟然太大意算错了利润,这不能只一句我不小心就敷衍过去,也是我的责任,而且这也是我们的项目的核心部分,以后在做完一个模块后,一定要测试多次,不能过于随便地用一个数据测试一下,能成功就算了,要用可能出现的所有情况去测试程序,让所有的代码都有运行过一次,确认无误。

最后,也是我比较喜欢的东西,就是大家一起为了一个问题去讨论和去交流。因为我觉得,无论是谁,他能想的东西都是有限的,别人总会想到一些自己想不到的地方。跟他人讨论和交流能知道别人的想法、了解别人是怎样想一个问题的,对于同样的问题自己又是怎样想的,是别人的想法好,还是自己的想法好,好在什么地方。因为我发现问题的能力比较欠缺,所以我也总是喜欢别人问我问题,也喜欢跟别人去讨论一个问题,因为他们帮我发现了我自己没有发现的问题。在这次项目中,我跟植荣的讨论就最多了,很多时候都是不可开交的那种,不过我觉得他总是能够想到很多我想不到的东西,他想的东西也比我深入很多,虽然很多时候我们好像闹得很僵,但是我们还是很要好的!
嘻嘻!而且在以后的学习和做项目的过程中,我们遇到的问题可能会多很多,复杂很多,我们一个人也不能解决,或者是没有想法,但是懂得与他人讨论与交流就不怕这个问题,总有人的想法会给我们带来一片新天地。相信我能做得更好。
还有就是做项目时要抓准客户的要求,不要自以为是,自己觉得这样好,那样好就把客户的需求改变,项目就是项目,就要根据客户的要求来完成。

15、在做这个项目的时候你碰到了哪些问题?你是怎么解决的?

(1)开发SpringBoot接口出现客户端和服务端不同步,导致接口无法测试,产生的原因沟通不畅。

(2)订单提交时由于本地bug或者意外故障导致用户钱支付了但是订单不成功,采用对账方式来解决。

(3)上线的时候一定要把支付的假接口换成真接口。

(4)项目中用到了曾经没有用过的技术,解决方式:用自己的私人时间主动学习

(5)在开发过程中与测试人员产生一些问题,本地环境ok但是测试环境有问题,环境的问题产生的,浏览器环境差异,服务器之间的差异

(6)系统运行环境问题,有些问题是在开发环境下OK,但是到了测试环境就问题,比如说系统文件路径问题、导出报表中的中文问题(报表采用POI),需要在系统jdk中添加相应的中文字体才能解决;

二、介绍功能模块

这块面试官的问法不同,有的会让你从你负责的模块中,挑选一个你认为做的最好的或者有亮点的模块去说,有的面试官是把你负责的模块问个遍,所以只要你简历上写了是你负责的模块,一定要去弄的非常熟练,如果你自己做的东西,你都不知道,那对于整个项目来说也就没必要再问了,所以这块是重点。在介绍自己负责的功能模块时,可以通过2个方向去介绍,一个是模块业务,另一个是模块开发中的技术解决方案。这两个方向全掌握了,才是真正的把负责的模块掌握了。

下面是所学项目中所有功能模块的业务以及常见面试问题,仅供参考,不要去背,要结合项目进行理解为主。

1、商品管理模块

数据库表设计:(重点,要知道表中字段与表直接的关系)

image.png

1.1 业务参考话术:

我们这个电商平台是不支持商家入驻功能的,因此整个商品管理主要是我们这个电商后台系统的一个核心功能模块。主要的功能分为:

对于商品品牌、商品分类、销售属性和平台属性进行管理的一些操作;

对商品有对应操作权限的业务员对于商品的添加、上下架、修改、删除、批量操作、模糊查询等功能。

针对商品这个模块来说,因为不同的分类对应不同的平台属性,平台属性和SKU进行关联,用于后期商品搜索功能实现,可以通过平台属性查询出所选属性下的所有SKU信息;

同时,一个分类下又有多个品牌,品牌下对应多个SPU商品,每一个SPU下有多种销售属性,我们通过商品SPU的不同销售属性组合生成多个SKU。例如
iPhone7是一个SPU,由于iPhone7分内存、颜色等销售属性,内存有64G、128G和256G,颜色有红色、金色和黑色,这样每种不同销售属性组合就是一个新的SKU,64G+黑色、64G+金色、64G+红色,128G+金色…等。(主要就是说表设计和表关系)

1.2 商品添加

先判断是否有对应的商品添加的权限,如果没有,直接不显示操作按钮;

如果有,先选择商品所属的分类,然后商品分类选择之后会对应的查询出所有平台属性和所关联的所有品牌;

然后添加产品SPU的一些基本信息(SPU名称、标题、商城价格等);

其次,上传产品SPU对应的图片,这块因为整个电商平台中需要保存大量的图片,因此我们使用了一个分布式文件存储系统FastDFS来存储商品的图片,这样的话后期也可针对容量进行水平扩展,不影响原来的使用,并且针对于高并发、高可用的问题,FastDFS的容灾性、负载均衡也是个优势;

在SPU列表中有添加sku的按钮,点击后可以添加给SPU添加SKU。进入SKU添加页面时会查出当前SPU的所有销售属性和图片,然后添加SKU信息,选择对应的销售属性,选择对应的图片。调用后台的商品添加接口/服务,然后对应的接口/服务中生成商品添加时的一些默认数据(添加时间、更新时间、操作人等),在商品添加的时候我们默认是下架状态。需要拥有审核功能的业务员针对商品中是否有一些不合法的数据进行审核。

1.3 商品上下架

因为商品添加之后,默认是下架状态,如果商品想处于销售状态,必须将商品的状态改为上架状态。在SKU列表页面中有上、下架操作按钮:

上架时将SKU信息添加Redis进行缓存,将SKU信息添加到ES一份以供搜索

修改上架状态 0未上架 1已上架 2已下架

这里要注意ES、Redis和MySQL数据同步(一致性)问题

1.4 模块相关问题:

1)SPU与SKU的概念,SKU是怎么划分的?

比如,咱们购买一台iPhoneX手机,iPhoneX手机就是一个SPU,但是你购买的时候,不可能是以iPhoneX手机为单位买的,商家也不可能以iPhoneX为单位记录库存。必须要以什么颜色什么版本的iPhoneX为单位。比如,你购买的是一台银色、128G内存的、支持联通网络的iPhoneX
,商家也会以这个单位来记录库存数。那这个更细致的单位就叫库存单元(SKU)。

2)介绍下FastDFS?

开源的分布式文件系统,主要对文件进行存储、同步、上传、下载,有自己的容灾备份、负载均衡、线性扩容机制;

FastDFS架构主要包含Tracker server和Storage server。客户端请求Tracker
server进行文件上传、下载的时候,通过Tracker server调度最终由Storage
server完成文件上传和下载。

Tracker server:跟踪器或者调度器,主要起负载均衡和调度作用。通过Tracker
server在文件上传时可以根据一些策略找到Storage server提供文件上传服务。

Storage
server:存储服务器,作用主要是文件存储,完成文件管理的所有功能。客户端上传的文件主要保存在Storage
server上,Storage
server没有实现自己的文件系统而是利用操作系统的文件系统去管理文件。

image.png
存储服务器采用了分组/分卷的组织方式。整个系统由一个组或者多个组组成;

组与组之间的文件是相互独立的;所有组的文件容量累加就是整个存储系统的文件容量;一个组可以由多台存储服务器组成,一个组下的存储服务器中的文件都是相同的,组中的多台存储服务器起到了冗余备份和负载均衡的作用;在组内增加服务器时,如果需要同步数据,则由系统本身完成,同步完成之后,系统自动将新增的服务器切换到线上提供使用;当存储空间不足或者耗尽时,可以动态的添加组。只需要增加一台服务器,并为他们配置一个新的组,即扩大了存储系统的容量。

2、商品详情模块

2.1 业务参考话术:

商品详情页,就是以购物者的角度展现一个sku的详情信息。这个页面不同于传统的页面,使用者并不是管理员,需要对信息进行查删改查,取而代之的是点击购买、放入购物车、切换颜色等等。另外一个特点就是该页面的高访问量,虽然只是一个查询操作,但是由于频繁的访问所以我们必须对其性能进行最大程度的优化。所以我们页面数据放入Redis缓存来提高性能,为了防止缓存击穿,我们采用了分布式锁。由于商品详情展示的数据需要要调用多个查询接口,为了提高响应速度,我们采用线程异步编排的方式进行接口调用。

2.2 模块相关问题:

Redis是这块的重点之一,有关Redis的高频问题,详见高频面试题,这里只说项目相关Redis常见问题

1)Redis在你们项目中是怎么用的?

商品详情中的数据放入缓存,价格是实时获取的;

单点登录系统中也用到了redis。因为我们是微服务系统,把用户信息存到redis中便于多系统之间获取共用数据;

我们项目中同时也将购物车的信息设计存储在redis中,用户未登录采用UUID作为Key,value是购物车对象;用户登录之后将商品添加到购物车后存储到redis中,key是用户id,value是购物车对象;

因为针对评论这块,我们需要一个商品对应多个用户评论,并且按照时间顺序显示评论,为了提高查询效率,因此我们选择了redis的list类型将商品评论放在缓存中;

在统计模块中,我们有个功能是做商品销售的排行榜,因此选择redis的zset结构来实现;

2)缓存击穿解决(分布式锁)

缓存击穿是指对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常"热点"的数据。这个时候,需要考虑一个问题:如果这个key在大量请求同时进来之前正好失效,那么所有对这个key的数据查询都落到db,我们称为缓存击穿。

使用分布式锁,采用redis的KEY过期时间实现

Redis:命令

# set skuid:1:info “OK” NX PX 10000

EX second :设置键的过期时间为 second 秒。

PX millisecond :设置键的过期时间为 millisecond 毫秒。

NX :只在键(key)不存在时,才对键(key)进行设置操作。

XX :只在键(key)已经存在时,才对键(key)进行设置操作。

Redis
SET命令用于设置给定key的值,如果key已经存在其他值,SET就会覆盖,且无视类型。

image.png

由于redis删除操作缺乏原子性,可以使用lua脚本进行删除,但是由于redis主从切换时,有误删锁的情况,所以不建议使用,后来咱们演变为redission框架进行分布式锁的实现,原理和redis的一样,redission给进行了封装,通过调用lock以及unlock方法进行加锁和解锁,使用更简单。

最终我们自定义了一个注解结合AOP+redission框架的方式,把这个分布式锁加以复用,需要用到分布式锁的地方可以直接打注解就可以了。

有关于redis分布式锁的演变,你可以当做在开发中遇到的问题来讲。

3. 商品搜索模块

3.1 业务参考话术:

商品搜索是根据关键字进行拼配,从已有的数据库中摘录出相关的记录反馈给用户,在我们项目中有两个搜索入口,一个是商品的三级分类还有个就是用户在搜索框中输入关键字。我们主要是采用ES来实现业务,在ES中我们主要存入了分类id与名称、skuId、价格、名称、图片、品牌的id、名称、logo的url、平台属性数据以及热度排名字段等内容,我们把商品名称使用ik分词器进行了中文分词,同时还可以通过平台属性值、分类、价格区间以及品牌等作为搜索过滤条件,给用户展示商品名称、价格和默认图片等信息。

3.2 模块相关问题:

1)ES的倒排索引?

正排索引:根据id去找到相对应的词

Id(索引)
1 红海行动
2 红海事件
3 红海行动事件
4 湄公河行动

倒排索引:根据词,看这个词都在哪个id(索引)里出现了

Id
红海 行动 红海1、2、3;行动1、3、4
红海 事件 红海1、2、3;事件2、3
红海 行动 事件 红海1、2、3;行动1、3、4;事件2、3
湄公河 行动 湄公河4;行动1、3、4

2)ES过滤条件有哪些?

分类信息、平台属性、品牌、价格区间、热度、评论数等

3)ES数据同步问题怎么处理?

当商品上架时,发送mq消息通知搜索服务,当搜索服务监听到消息后把商品数据加入ES中,同样,当商品下架时也是通过mq进行消息传输来实现。

4. 单点登录模块

4.1 业务参考话术:

单点登录就是访问项目时,用户只需要登录一次,就可以去访问所以内容。我们是采用网关自定义全局过滤器、token认证以及redis来实现,
登录业务,用接收的用户名密码(密码采用MD5+密码盐的形式存储)核对后台数据库,核对通过,用uuid生成token,将用户id加载到写入redis,redis的key为token,value为用户id。登录成功返回token与用户名和昵称,将token与用户信息记录到cookie里面重定向用户到之前的来源地址。用户再次访问其他需要登录的内容时通过网关过滤器进行拦截校验。具体业务参考以下流程图:

{width=“3.78125in” height=“9.015277777777778in”}

{width=“7.268055555555556in”
height=“6.978472222222222in”}

4.2 模块相关问题:

1)cookie被禁用了能登录吗?怎么解决的?

不能登录,因为token存在cookie中,解决办法是参考京东的给用户提示:请您启用浏览器Cookie功能或更换浏览器

2)怎么防止cookie盗用(盗链)?

采用https进行加密传输,或者在token中加入以用户访问ip作为秘钥,解密token比对用户访问ip地址,ip不匹配,重新登录。

5. 购物车模块

5.1 业务参考话术:

我们项目对于购物车的设计主要分为两个部分:用户未登录和已登录两种状态。在添加购物车时需要进行判断用户是否登录(主要看能不能获取到用户的真实id,获取到了就是已登录),如果未登录,则将购物车的信息放在redis中,采用hash结构存储,key为uuid(用户的临时id,前端再商品详情页点击加入购物车按钮时生成的随机数,存储在cookie中),field为skuId,value是商品购物项信息(CartInfo对象),同时在数据库进行持久化操作。用户已登录状态下,cookie中会存放token,根据token我们能获取到用户的id,所以采用userId作为hash结构的key,field为skuId,value是商品购物项信息(CartInfo对象)。在进入购物列表时,会判断用户的登录状态,如果是未登录的话直接返回未登录购物车数据,如果是已登录,就判断是否存在未登录购物车,存在就进行购物车合并,然后再删除未登录购物车数据。

添加购物车流程:

5555.png

合并购物车流程:

6664.png

5.2 模块相关问题:

1)购物车未登录有过期时间吗?已登录后有吗?

未登录的话:7天或15天

淘宝的设计是没有未登录购物车(如果面试不好说,咱们也可以说这种模式)

已登录情况下是永久存储,reids的数据有过期,主要是释放
redis’中数据,数据库采用永久存储。

2)购物车能添加多少个商品?

49件或者99件商品,只要合理就行

3)每个商品最多能加多少件?

库存充足的情况下可以添加99个,京东是200个

4)添加购物车减库存吗?

添加购物车不减库存,验库存数量

5)进入购物车列表的时候验价格吗?

验价格,如果价格有变化,展示新价格,给用户提示

6)购物车里的商品价格变换了有提示吗?库存无货了有提示吗?

因为进入购物车列表时进行库存和价格的验证,所以会有提示。

6. 订单微服务:

6.1 业务参考话术:

整个订单模块有结算页、下单、对接支付服务和对接库存管理系统等功能,当用户发起结算请求时,由于用户在没有登录的情况下也可以点击结算,所以我们要先判断用户是否登录,只有已登录的情况下,才能跳转到结算页面,在结算页,用户可以选择收货地址,给用户展示订单信息,用户选择支付方式,提供了微信支付和支付宝支付,确认订单信息,然后提交数据到后台,生成对应的订单表、订单详情表和订单物流表(当订单生成的时候,我们要调用对应的库存系统针对订单的商品数量进行验库存,还要进行验价格)。当订单创建成功之后,自动跳转到成功页面(将订单数据和到期时间传递过去)。

这块我们设置的订单的有效时间为24小时(这个时间可以自己定,只要合理就行),因为我们利用延时队列实现定时消息发送,消费者到时间后监听到消息,进行订单校验,如果订单是未支付状态,把订单状态修改为关闭订单。

订单的主要状态有
未支付、已支付、待发货、已收货、待评价、已完成、已关闭等。

45546544.png

6.2 模块相关问题:

1)订单有效期是多久,怎么取消订单?

订单有效期为24小时,我们采用rabbitmq的延时队列,在生成订单时,发送延时消息,设置消息24小时后触发,然后监听到这个消息后,进行订单的取消。

2)怎么防止订单重复提交?

在进入结算页面是我们生产了一个流水号,然后保存到结算页面的隐藏元素中一份,Redis中存一份,每次用户提交订单时都检查reids中流水号与页面提交的是否相符,如果相等可以提交,当订单保存以后把后台的流水号删除掉。那么第二次用户用同一个页面提交的话流水号就会匹配失败,无法重复保存订单。

3)订单超卖问题怎么解决的?(库存只剩1件商品,多个用户同时下单)

我们采用的是下订单不减库存,只验证库存,在支付成功后再去扣减库存,如果库存扣减失败,通知后台进行补货,如果这个商品不能补货,人工客户介入,和买家进行沟通,给予退款或相应补偿。

如果想实现不超卖,就得在下单时进行库存锁定,(可以使用数据库锁方式)然后减库存操作。

7. 支付微服务

7.1 业务参考话术:

当用户发起支付请求时,我们采用支付宝或者微信支付,以支付宝为例,我们要制作调用支付宝统一下单接口(支付接口)需要的签名和参数,我们先封装了一个AlipayClient配置类,把商户appid,支付宝公钥,开发者私钥,统一下单接口url以及签名方式等默认参数进行传入,从而生成AlipayClient对象交于spring管理。当调用支付时,我们会把订单交易标号、商品码,交易金额以及同步回调地址和异步回调地址等参数传给支付宝,从而生成支付页面,在这个过程中我们会记录支付信息存储到数据库中,当用户扫码支付后,支付宝回给用户跳转页面,主要是我们设定的同步回调地址。平台这块是根据支付宝的异步回调来判断用户是否支付成功,接收到异步回调时我们会验证签名,以校验合法性,同时会使用rabbitmq给订单模块发送一个校验成功的消息,以便于订单模块的后续处理。

支付宝还提供了退款、对账、关闭交易等接口,在项目中也都使用了。

image.png

7.2 模块相关问题:

1)支付宝支付需要的参数?

主要参数有appid、开发者私钥、支付宝公钥、支付网关地址,同步回调url、异步回调url、请求数据格式、编码方式、签名方式、订单交易编号、订单金额、商品编码等

2)支付锁库存吗?

我们做的是支付不锁库存,只有在支付成功后,去锁定库存进行响应的扣减。这块面试官会说超卖了,可以参考上面订单超卖内容进行解答。

3)支付日志表(信息表)中记录了什么东西? 有什么作用?

主要记录 支付类型、金额、交易号、订单编号、交易内容、支付状态和时间等。

支付日志表主要是记录支付的状态转换和数据以便于和支付宝微信等三方平台进行对账等。

4)重复支付问题?

场景1

对同一个支付平台web端和app端的重复支付,同一个支付平台针对同一笔业务订单生成的流水号是唯一的,第三方支付平台对同一个流水号只进行一次支付,不会重复支付。

场景2

例如银行的扣款成功的通知结果延迟了,在同一笔业务订单因为没有收到成功的结果通知,发生第二次支付并正常成功后,才收到第一次支付成功的通知。如下图所示

image.png

解决方案

在第三方支付中心异步回调时,实现以下功能:

查询支付中心流水表,按订单号查询支付状态是否为申请支付状态,如果是,将此订单支付状态修改为支付完成,记录到支付中心流水表;如果不是申请支付状态,对比支付中心流水表中现有记录的第三方平台交易流水号和第三方平台返回的第三方平台交易流水号,如果两者都相同则不进行任何操作,表示是第三方支付的重复通知,直接返回结果即可;如果两者不同,则记录到异常支付单表中。需要运营人员进行线下退款处理或者直接调用退款接口退款。

流程图如下:

image.png

8. 秒杀微服务

使用下面的流程图对比代码,多去看几遍,熟悉了就知道秒杀的解决方案了,需要理解。

004.png

相关文章:
第一章 面试技巧篇
第二章 数据结构、设计模式与手写代码
第三章 Java基础篇
第四章 Java高级篇
第五章 MySQL数据库篇
第六章 Java Web篇
第七章 Java框架篇
第八章 Redis数据库篇
第九章 分布式技术篇
第十章 Git与Linux篇
第十一章 电商项目篇之尚品汇商城

真诚点赞 诚不我欺~

{{ praiseUserVoList.length }}人点赞

item.nickname

尚硅谷Java技术之北京高频面试题:第十一章 电商项目篇之尚品汇商城

{{ isPraise ? '已点赞' : '点赞'}}
{{ isCollect ? '已收藏' : '收藏'}}
评论
gOod mornIng
没有更多啦~ 加载中...

关于作者

晴天
晴天

人因梦想而伟大!

目录