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)队列削峰,秒杀成功后立即返回,然后以发送消息的形式创建订单