分布式Session的问题
问题描述
当我们做负载均衡时,可能用户登录后,Session信息保存在机器A,但是下订单时,请求发送到了机器B。
由于机器B上没有用户的Session数据,导致无法识别该用户是谁,那么就会需要再次登录一遍,用户体验差。
解决办法
方法一:IP_Hash做负载均衡
该方法能保证一个IP发送的请求都会发送到某台固定的服务器上,从而避免分布式Session问题。
缺点:
- 单点故障问题,如果某台服务器挂了,那么有一部分用户无法再使用服务,因为请求是固定发送到该服务器上的。
方法二:Session复制
即在多台服务器上做Session的复制,保证每台机器都有用户的session。
缺点:
- 开销非常大。因为每一次都需要进行广播来保证每台机器上有用户的Session;
方法三:Session Center
使用Session中心来统一保存用户的Session。例如Redis。
该方案比方法一和方法二都要好。也是比较普遍的方案,但是也有一些不足。
缺点:
- 使用了额外的技术
数据库优化
换数据库
例如,从mySQL换成Redis,Oracle等。
分库分表和读写分离
方式一:JDBC层的分库分表,例如ShardingSphere,TDDL
该方式将分库分表的逻辑放在应用层,即通过JAVA语言来完成。
优点:
- 性能高
缺点:
- 不能跨语言,而且会对业务代码有侵入性
方式二:Proxy代理层的分库分表
该方式多加一层代理层,分库分表的逻辑放在代理层来处理。
例如:mycat,mysql-proxy
优点:
- 可以跨语言
- 无侵入性
缺点:
- 因为多了一次通信过程,所以效率要比方式一低一点。
幂等性接口
定义
幂等性本来是数学上的概念,表示做一次变换和做N次变换得到的结果是一样的。
在编程方面,幂等性接口表示:
对一个接口调用一次或者N次, 对系统的影响是一样的。
举个例子:
抢红包只允许抢一次,即便你抢多次,也和抢一次的得到的钱是一样的。
再举个例子:
支付接口,对于同一笔订单,只允许支付一次,即便调用该接口多次,也只会支付一次的钱。
解决方案
方案一:全局唯一ID
例如,对于一笔订单设置唯一ID,如果该ID已经存在,就不会再去创建该订单了。
方案二:去重表
和全局唯一ID的思路一样,只是将该去重表放进Redis中维护,表里存在该ID就不创建了。
方案三:状态机
不太懂目前