分布式
springCloud、dubbo
- 服务调用方式
- dubbo:RPC
- 远程方法调用,就是像调用本地方法一样调用远程方法
- 底层是tcp连接
- springcloud:REST
- 使用 HTTP 协议处理数据通信
- 面向资源的,而资源是通过 URI 进行暴露
- 注册中心
- dubbo:zookeeper
- 取CAP的CP,注重一致性
- 在选举期间注册服务瘫痪
- 选举机制
- 节点数必须为奇数
- 可用节点数 > 总节点数/2
- 有Leader和Follower角色
- 过半数存活原则
- springcloud:eureka
- 取CAP的AP,注重可用性
- 各个节点平等
- 自我保护机制
- 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁启动关闭客户端)节点会进入自我保护模式,保护注册信息,不再删除注册数据,故障恢复时,自动退出自我保护模式
- SOA、微服务
- SOA((面向服务的架构)
- 微服务
- 微服务的粒度更细
- 耦合度更低
- 服务规模相较于SOA一般要更大,并发量也更高
CAP理论
- 一致性(consistency)
- 可用性(availibity)
- 分区容错性(partition tolerance)
接口幂等性
- 全局唯一ID
- 根据业务操作和内容生成全局唯一的ID,然后在执行操作前先判断是否已经存在该ID,如果不存在则将该ID进行持久化,如果已经存在则证明该接口已经被调用过了(例如订单号)
- 乐观锁,添加version字段
- token机制,将token放在redis中
分布式锁
- 数据库乐观锁
- 根据版本号来判断更新之前有没有其他线程更新过,如果被更新过,则获取锁失败
- Redis 分布式锁
- 使用 SETNX(set if not exist)命令插入一个键值对时,如果 Key 已经存在,那么会返回 False,否则插入成功并返回 True
- EXPIRE 可以为一个键值对设置一个过期时间,从而避免了死锁的发生
- Zookeeper 分布式锁
session
- 粘性 Session
- 将用户锁定到某一个服务器上
- 缺乏容错性
- 服务器 Session 复制
- 任何一个服务器上的 Session 发生改变,该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要 Session
- Session 量大的话可能会造成网络堵塞,拖慢服务器性能
- Session 共享
- 分布式缓存方案比如 Memcached、Redis,但是要求 Memcached 或 Redis 必须是集群
- Session 持久化到数据库
- 对数据库造成很大压力,还需要增加额外的开销维护数据库
分布式事务
- 类型
- 二阶段提交2PC
- 请求阶段通过协调者来统计表决结果
- 执行表决后的结果,如果表决的结果是提交,那就提交执行,否则不执行提交
- 缺点:同步阻塞,而且万一协调者挂了就无法保证ACID
- 三阶段提交3PC
- 向参与者发出一个信号,看看大家是否都能提交,如果可以就返回yes,否则返回no
- PreCommit阶段,预提交一下,如果参与者可以完成commit,就返回ack进确认,如果不能则放弃提交本次事务
- doCommit阶段,进行真正的事务提交
- 解决方案
- XA
- 基于二阶段事务实现的一种标准协议,目前主流数据库都已支持该协议
- 业务补偿模式
- 使用一个额外的协调服务来协调各个需要保证一致性的微服务,协调服务按顺序调用各个微服务,如果某个微服务调用异常(包括业务异常和技术异常)就取消之前所有已经调用成功的微服务
- TCC模式
- try阶段进行检测
- commit提交执行,只要try阶段成功了commit就一定会被执行
- cancel业务出现错误时执行,回滚事务,释放资源
- 消息中间件MQ
- RocketMQ
- 消息生产者向消息集群发送prepared消息,获取消息地址
- 本地提交事务,并向集群发送确认消息
- 通过第一步获取到的地址,访问消息并改变消息状态
- RocketMQ
雪崩效应
- 一个服务之间出现了故障或者网络延迟,在高并发的情况下,会导致线程阻塞,在很短的时间内该服务的线程资源会消耗殆尽,最终使得该服务不可用。由于服务的相互依赖,可能会导致整个系统的不可用
熔断机制
- 当一个服务出现故障时,请求失败次数超过设定的阀值(默认50)之后,该服务就会开启熔断器,之后该服务就不进行任何业务逻辑操作,执行快速失败,直接返回请求失败的信息
- 自我修复机制
- 一个服务熔断后,经过一段时间(5s)半打开熔断器,检查一部分请求(只能有一个请求)是否正常,其他请求执行快速失败,检查的请求如果响应成功,则可判断该服务正常了,就可关闭该服务的熔断器
负载均衡
- Ribbon
- 使用HttpClient 或 RestTemplate 模拟http请求,步骤繁琐
- feign(底层是通过Ribbon实现)
- 采用接口+注解的方式 ,将需要调用的其他服务的方法定义成抽象方法
- 硬件负载均衡:F5
- 算法
- 轮询
- 将请求按顺序轮流分配到后台服务器上,均衡的对待每一台服务器,而不关心服务器实际的连接数和当前的系统负载
- 随机
- 通过系统随机函数,根据后台服务器列表的大小值来随机选取其中一台进行访问
- 一致性哈希
- 相同参数的请求总是发送到同一个服务提供者,当某一台服务提供者宕机时,原本发往该提供者的请求,基于虚拟节点,平摊到其
- 轮询