谷粒商城项目重点


1. session在分布式下的问题

1.同一个服务,多个实例,每次的session分布不一样

解决办法:

  • 第一种解决方案:session复制(同步),存在带宽,占用很多内存
  • 第二种解决方案:客户端存储,浏览器cookie有有长度限制,不安全
  • 第三种解决方案:iphash一致性,水平扩展会有问题
  • 第四种:统一存储到数据库,使用了springsession,将用户的信息存储到了redis缓存中

2.不同服务,跨域名不能共享session

解决办法:
将域名范围扩大为父域名

springsession的原理:
通过过滤器来拦截请求,将request和response包装成wrappedRequest和wrappedResponse,做了功能增强,这样request.getSession就是从SessionRepository获取得到的,做到从redis获取session。

2. ThreadLocal

添加商品到购物车,要判断用户有没有登录,没有登录就操作临时购物车,登录了就操作登录购物车并且还要合并临时购物车

然后通过拦截器来拦截判断用户是否登录,然后将用户的信息封装起来,放到threadlocal中

3.缓存数据一致性的解决方案

1.双写模式

解决方案:

  • 1)给缓存数据设置过期时间,数据最终一致性(看用户是否可以忍受)
  • 2)加读写锁

失效模式

解决方案:加读写锁

  • 3.)延时双删

  • 4).canal来监听mysql的binlog日志,然后更新redis

  • 5).分布式的读写锁

4.微博登录的流程

首先去微博开放平台去申请一个应用,申请成功就会有对应的App Key和App Secret,设置授权成功页的回调地址和授权失败的回调地址。然后你在页面上点击微博登录会跳到微博提供的授权页,输入账号密码,如果成功就会跳到成功回调页,并且它携带了一个code,通过code来获取token,拿得token就可以访问微博提供的一些接口来访问用户信息

5.单点登录流程

环境:一台登录认证服务(server),两台客户端(client1,client2)

浏览器从client1访问受保护的资源,判断session中有没有用户信息,如果没有去认证服务器登录,可以携带一个登录成功要跳转的地址(redirect_url),登录成功可以把用户信息放入redis中,然后跳转地址的使用携带一个token,说明token是从认证服务登录返回的,判断如果token不为空,根据token查询用户信息放入session中,以后登录session有数据就可以直接访问了,client2访问受保护的资源,client1已经登录过了,所以client2就不需要登录了,就是服务器返回token的时候会往浏览器放一个cookie,下次登录判断cookie是否为null,如果不为null就说明以前有人登录过了,就不需要登录了

6.购物车的实现

购物车分为临时购物车和登录购物车,使用了redis的hash结构

整个存放结构:登录购物车key=gulimall:cart:userId field:skuId value:skuId对应的商品id

临时购物车key=gulimall:cart:uuid field:skuId value:skuId对应的商品id

添加商品到购物车都需要判断用户的登录状态,通过拦截器将用户的登录信息放到Threadlocal中,如果第一次使用购物车默认会为用户添加一个uuid

获取购物车:首先判断用户有没有登录,没有登录展示临时购物车,登录了首先要看临时购物车有没有数据,如果有数据就要合并到登录购物中去,合并完成删除临时购物车

7.下单流程

选中商品添加到购物车,点击去结算,来到结算详情页,需要查询会员的收货地址列表、所有选中的购物项、优惠信息(会员的积分),查询库存信息(有货无货),商品总金额,应付金额,商品总数,最重要的就是防重令牌,确认号商品信息就可以点击去支付,这样的话库存就会锁定,订单如果出现异常或者不支付就会通过消息队列进行通知,让库存解锁.

8.幂等性的解决方案

  • 1.使用令牌机制(token)

  • 2.各种锁机制(乐观锁,悲观锁,分布式锁)

  • 3.唯一约束(数据库唯一约束,set nx)

  • 4.防重表

  • 5.全局请求唯一id

9.RabbitMQ项目中怎么使用的

解锁库存和定时关单

  • 1)那说一下消息丢失是怎么解决的?

大致分为3个阶段:

生产者发送消息给mq消息丢失:开启事务(同步效率低)或者开启confirm机制(异步效率高)

mq自己内部出现了问题:开启持久化机制

消费者处理消息时丢失:取消自动Ack模式,开启手动Ack模式

  • 2)说一下消息积压怎么解决的吧?

现在生产者发送的流量

多增加几台消费者实例进行消费

将消息保存到数据库,离线慢慢处理

  • 3)消息重复消费怎么解决?

保证业务接口的幂等性

使用防重表,发送的每一个消息都有唯一标识,处理过了就不用处理了,比如redis,

可以配合set nx命令保存消息id,保存如果key已经存在,获取它的值(比如成功是1,正在执行是0),如果是1表示已经成功处理,直接ack,如果是0就什么都不做,为了防止死锁,加一个key的过期时间

10.秒杀功能

限流+异步+缓存+独立部署

限流方式:

1)前端限流,抢购的时候可以设置一个验证码,通过手速快慢可以降低一些请求,还有一个好处就是可以识别是人还是机器

2)nginx限流,直接将部分请求负载到错误的静态页面

3)网关限流

4)分布式信号量(本项目使用的这个)

5)rabbitmq限流

秒杀思路:

1)项目独立部署,独立秒杀模块gulimall-seckill

2)使用定时任务每天三点上架最新秒杀商品,削减高峰期压力

3)秒杀链接加密,为秒杀商品添加唯一商品随机码,在开始秒杀时才暴露接口

4)库存预热,先从数据库中扣除一部分库存以redisson信号量的形式存储在redis中

5)队列削峰,秒杀成功后立即返回,然后以发送消息的形式创建订单

参考博客


  目录