畅购商城项目,面试问答,项目详解及全部代码

本文详细介绍了畅购商城的微服务架构,包括使用SpringCloud构建的微服务、SpringSecurity OAuth2.0实现的单点登录、Seata处理分布式事务、Elasticsearch的实时检索、RabbitMQ的异步通信以及如何解决支付、秒杀等业务中的技术挑战。此外,还涵盖了支付、订单、购物车和秒杀业务的实现细节,以及数据库的同步和限流策略。
摘要由CSDN通过智能技术生成

商城项目

商城—微服务技术栈
1 商城介绍
1.1 项目介绍
此电商项目属于B2C模式的线上商城,支持用户在线浏览商品在线搜索商品,并且可以将喜欢的商品加入购物车从而下单购买商品,同时支持线上支付,支付模式支持支付宝、微信、银联支付。用户还可以参与低价商品秒杀

畅购商城采用了微服务架构,微服务技术采用了SpringCloud技术栈,各个微服务站点基于SpringBoot构建,并采用SpringCloud Gateway将各个微服务的功能串联起来,形成一套套系统,同时在微服务网关Gateway中采用过滤和限流策略,实施对微服务进行保护和权限认证操作。项目采用了SpringSecurity OAuth2.0解决了各个微服务之间的单点登录和用户授权。采用了当前非常热门的Seata来解决微服务与微服务之间的分布式事务。采用了Elasticsearch解决了海量商品的实时检索。数据存储采用了MySQL,并结合Canal实现数据同步操作,利用Redis做数据缓存操作。各个微服务之间采用RabbitMQ实现异步通信。我们采用了OpenResty集成的Nginx来控制微服务最外层的大量并发,利用Keepalived+Nginx来解决Nginx单点故障问题。

1.1 项目架构
在这里插入图片描述

2 商城业务总结
2.1 购物车业务
购物车分为2种情况,一种是用户登录或者不登录均能使用购物车,另一种是用户只能登录后使用购物车。
在这里插入图片描述

方案一:登录/不登录均能使用购物车

如果用户不登录也能使用购物车,此时我们会将购物车信息存入到Cookie中,如果用户浏览器禁用了Cookie,我们可以将购物车数据存入到localStorage或者WebSQL中
用户登录后,购物车数据存入到Redis中。
如果用户从未登录切换到登录状态,此时需要将用户Cookie/WebSQL/localStorage中的数据合并到Redis中。

该购物车实现方式比较方便,用户不登录也能使用购物车,但也存在安全问题,例如:未登录将商品加入购物车,清空浏览器缓存后数据就没了。

方案二:用户必须登录才能使用购物车

用户如果不登录就无法使用购物车,该方案会将用户数据存入到Redis中,使用该方案可以确保用户数据安全
用户将商品加入购物车后,我们会将购物车数据存入到Redis中,数据类型选中Hash类型,将用户的名字作为namespace,把要加入购物车的商品ID作为key,加入购物车的商品信息作为value

在这里插入图片描述

2.2 订单业务
在这里插入图片描述

订单流程:

用户添加订单的时候,可以在购物车列表页选择将哪些商品添加到订单中并下单操作。点击结算的时候,会进入到下单页面,下单页面会显示用户选中的购物车商品信息,点击提交订单的时候,会实现订单的添加操作。
这里需要注意下,添加订单后会将订单中的商品信息从购物车中移除,创建订单之前需要校验一下数据库中商品的价格,此时价格以数据库中的商品价格为准,下单后还需要调用商品微服务实现库存的递减操作,库存递减这里需要控制库存超卖问题,解决超卖问题可以使用数据库的行级锁(for update 悲观锁)实现。
用如下SQL语句操作,基于num>#{num}实现乐观锁:UPDATE tb_sku SET num=num-#{num} WHERE id=#{id} AND num>=#{num}
当返回所减库存>=剩余库存的时候,才表示减库存操作成功,否则抛出异常实现数据回滚。

乐观锁效率高于悲观锁,因为没有线程阻塞,最多也就是减库存失败,实现回滚。

在这里插入图片描述

2.3 支付业务
在这里插入图片描述

支付流程:

1)用户在订单微服务中下单,下单后,会向MQ发送一个延时队列,延时30分钟,队列的信息主要是订单信息
2)下单成功后,前端调用支付系统,根据订单号创建支付二维码,支付二维码的支付地址由订单微服务调用微信服务获取支付地址。
3)用户看到支付二维码后,开始扫码付款,并进行授权操作,此时如果授权成功,则用户扣款支付成功。
4)用户支付成功后,微信服务器会将支付状态发送给支付微服务,支付微服务会将该信息发给RabbitMQ。
5)在订单系统中会创建一个
支付信息消息的监听
,读到支付信息后,根据支付结果,如果支付成功,则修改订单状态,如果是支付失败,也修改对应订单状态。
6)防止用户长时间不支付,在订单系统中,还编写一个延时队列监听,半小时后,能监听到订单信息,并在数据库中检查订单是否已经支付,如果已经支付,则无需处理,如果未支付,则需要关闭微信支付,同时修改订单状态和商品状态。

问题说明:

支付中如果出现网络故障,而没有收到微信服务的支付装填响应没怎么处理?
微信服务器提供了一个根据订单号查询支付信息的方法,可以调用该方法查询支付状态信息。

微信支付一个订单付款两次问题处理
一是,网络延迟造成回调的数据包返回超时,没有收到支付成功状态,
二是,还有可能用户在支付的时候订单状态没有及时更新有问题。
三是,开始苦逼的支付测试,忽然发现有一单的订单支付确实成功后收不到任何状态信息,这就奇怪了,开始查问题,是不是服务器拦截了微信支付的回调,忽然想到上线的后,因为受到很多恶意ip攻击,把阿里云 云盾中记录的恶意ip屏蔽 ,大多恶意ip 都是出自一个网段,通过IP段方式加入阿里云安全组规则 屏蔽了。难道是微信支付服务器IP地址恰好增加了又在这个屏蔽的ip段内,赶紧调微信支付接口查看ip看下果然,增加很多微信支付的IP地址和ip段,大概是150多个ip了,这个坑终于是找到原因了,希望遇到这种问题朋友也各有好运咯。

2.4 秒杀业务
在这里插入图片描述

秒杀中的常见问题的解决
1)解决超卖的问题

1)Redis预减库存,有一个下单请求过来时预减库存,若减完后的redis库存小于0说明已经卖完,此时直接返回客户端已经卖完。后续使用内存标记,减少Redis访问。若预减库存成功,则异步下单,请求入队列,返回客户端排队中。

2)数据库层面防止超卖:Redis预减库存只是抢到了这个机会,真正是否购买成功还是要等到所有数据库操作的真正成功,即消息队列的消费端是否消费成功。

数据库层面,秒杀的订单表设置唯一索引,防止重复下单。

数据库层面,减库存的时候同时判断此时库存是否大于0。

由于是订单模块和库存模块,涉及到分布式事务的问题,使用seata框架。

2)如何保证Redis的库存与数据库库存的一致性

在我们的项目中,Redis的库存并不是真正的库存,而是用于阻挡多余的下单请求,用于保证有多少秒杀商品库存就放多少个请求到消息队列,大大减少数据库访问。

真正的下单和减库存操作还是操作数据库的。

所以我们不需要保证Redis缓存与数据库的一致性

3)如何保证MQ不丢失消息

消息丢失的三种情况:

**生产者丢失消息:**生产者发送消息到MQ时因为网络问题丢失消息。
**MQ丢失消息:**没来得及持久化,就挂掉后消息丢失
**消费端丢失消息:**刚从MQ获取消息,没处理完消费者就挂掉了
1 生产者丢失消息的解决方案:

1) rabbitmq提供事务支持,在生产者发送之前开启事务,然后发送消息,如果消息没有成功被rabbitmq接收到,那么生产者会受到异常报错,这时就可以回滚事物,然后尝试重新发送;如果收到了消息,那么就可以提交事物。但是这种方案会阻塞生产者,吞吐量下降。

2)==可以将channel开启confirm机制。==在生产者哪里设置开启了confirm模式之后,每次写的消息都会分配一个唯一的id,然后写入了rabbitmq之中;**如果rabbitmq没能处理这个消息,会回调你一个nack接口,告诉你这个消息失败了,你可以进行重试。**如果成功发送到mq,也会回调一个ack的接口方法,告诉你成功发送消息。

这里使用方案二!这样吞吐量更高。

2 MQ自己丢失数据的解决方案

设置持久化!持久化有两个步骤:

1)创建queue时设置持久化,但是这时候持久化的是queue的元数据,不会持久化queue里面的数据。

2)发送消息的时候将消息的deliveryMode设置为2,表示将消息持久化。

而且可以将持久化与生产者的confirm机制结合,只有持久化成功后才回调ack方法。超时未持久化成功或持久化失败也会回调nack。

3 消费者丢失数据的解决方案:

消费者端丢失数据都是因为开启了rabbitmq的autoACK功能,即消费者获取了数据之后就自动告诉MQ已经消费。

解决方案:==关闭rabbitmq的autoAck,==在确保消息被消费成功之后才发送ACK。消息没有成功消费的话rabbitmq会重发消息,这样能保证消息不会再消费者端丢失。

4)MQ如何保证不重复消费

这里不保证不重复消费

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值