分布式
优势:处理高并发需求,大量的业务需求可以高效率的处理
根本问题:网络传输会造成根本问题.我们无法保障网络始终为高效率,因为影响因素很多.
分布式的一致性:
强一致性:永远保证各个节点的数据为相同的,不相同要等待相同后才能访问.
弱一致性:
读自写一致性:某个节点应用修改了数据后,它一定查询到最新的数据,其他节点可能读不到最新的数据
单调读一致性:不能读取比上一次旧的数据,应用不会访问到其他节点的旧数据
因果一致性:A应用是被B应用依赖的,所以当A应用修改数据时,B应用就要等到A应用处理完毕才可以访问数据
最终一致性:节点在读取数据时可能会读取到不一致的数据,但最终会保证一致性,换句话说就是数据延迟同步. 这是当前主流的一致性使用措施.他可以有效防止脏读等一系列的数据问题
会话一致性:在一个session中只会读到最新的数据
CAP理论:可用性、分区容错性、一致性不能同时都满足.在分布式情况下,无法割舍分区容错性,那么就只能在可用性和一致性中间进行平衡,这就有了BASE理论
Base理论:在保证可用性和分区容错性的前提下,利用应用自身的特点(软状态),达到最终一致性的分布式架构
一致性协议2PC:
两阶段提交协议(oracle和mysql支持协议):
准备阶段:中间管理协调向各个节点发送是否可提交请求. 节点发送是否.如果有否,那就发送回滚到第二阶段
提交阶段:中间管理向各个节点发送提交请求,如果都行那么提交成功,如果有不成,那就回滚,回滚各个节点要返回ask响应
优点:结构简单
缺点:过于依赖中间管理,如果中间管理挂掉,那么其他节点全部锁死.
三段提交协议3PC:
收集阶段:向节点发送是否能提交事物,能就进入二阶段,否则就中断进入二阶段中断请求
授权阶段:向节点发送准备提交的信息,节点准备好返回ask,进入三阶段,否则就进入中断三阶段.
提交阶段:向节点发送提交信息,节点准备好就yes来确定进行提交,如果中断,就发送取消请求.节点反馈并取消提交
三阶段如果发送的是取消请求,但节点没有收到,那么节点还是会提交,造成数据不一致
paxos算法:难…但解决了分布式系统的数据一致性问题
客户端:每一个节点数据库
提案(proposal):提出操作的模块 一堆提案只有一个被选中 没有提案就没有选定 提案决定后所有节点都将学习
决策(acceptor):决定操作的模块
1.必须选定接收的第一个提案
2.多数(半数以上)决策模块选定了这个提案,这个提案才会执行
3.如果提案被选定(就是已经有提案被接受了).那么新提出的高编号的提案和被acceptor决定的提案value必须是一样的.
4:同上条件,那么其他提案者提出高版本的提案,被acceptor接受的value也必须是一样
5.对于任何的提案,那么半数决定执行的决策模块中,所有模块都不会再接受比这个提案版本小的提案;之前接受的比这个提案编号小的提案,最大编号那个提案value和当前选中的提案value一样
学习(learners):进行复制并发放的模块
生成提案的规则:
当提案者发送一个新的提案,没有value只有版本号,acceptor接受并选定后,承诺不会再接受比这个版本号小的提案,并返回给proposal一个null值,这代表当前acceptor没接受过值 可以是随意.提案者进行赋值提交,携带版本号和value,acceptor接受并响应'
当决策者已经接受过版本为v的value一个提案,那么提案者发送一个提案接受并选定后,会检查提交的版本号,acceptor就将当前已经选定的提案的版本号n和value发送给提案者,提案者需要学习n和value格式并发送一个完整的提案(有n有value的),acceptor接受.如果小于acceptor当前的选定提案的版本号,那就忽略,如果大于那就执行并返回响应
算法优化(针对acceptor):
acceptor在之前是接受一个编号n的提案 然后返回当前选定的编号n1和value,如果提案者学习完后没有提交n1+1的版本号和value,那么acceptor才忽略,那么现在优化为,如果提案发送给acceptor时版本号(prepare请求)就小于当前acceptor选定的提案编号,那么不用再返回当前版本号,直接就给它忽略了
算法流程:
1:proposal -> prepare请求 ->acceptors
2:如果acceptors之前没接受过提案,那么承诺版本不会比当前旧,如果有接受,那么返回n和value,如果版本小,忽略
3:proposal接受并学习,发送n和value, acceptors接受执行,如果n小了,返回error
在1流程中,如果没有半数以上acceptors接受,那么重新1流程
在3流程中,如果没有半数以上acceptors接受执行,那么重新1流程
learner学习流程:
方案1:一个acceptor接受了提案就发给所有learner,那么有多少个acceptor,每一个learner就收多少个,总的来说就是acceptor*learner的通信次数
方案2:一个acceptor接受了提案就发给一个主learner(learner的leader),然后派发给各个learner,如果leader learner挂了,就不学了
方案3:一个acceptor接受了提案就发给一个主learner 集合(班干部群体),这个集合负责派发给所有learner,通信复杂度较高
算法活性:
保证1:选取leader proposer,它来提交提案
Raft算法:
与paxos算法的区别和共同点:功能相同,但结构不同,Raft算法更好理解
1leader选举:
learder:唯一一个,处理交互
candidate:leader挂掉,它就成为leader
follower:其他参与者,随时可能为候选者candidate.
流程:
1先选举候选者(无leader模式下超时机制,自荐成为候选者);
2候选者向各个参与者发送推荐票开始选取leader;
2*如果脑裂造成出现多个候选者,多个候选者又持有相同的选票,那么延迟一会再进行拉票阶段,哪个后选择先拉到足够票成为leader,其他候选者变为参与者进行同步
3当所有follower都同意后,成为leader;进入下一周期.leader不断发送心跳包证明自己存在,每次接受到leader的心跳包,参与者就重置自身超时机制,
-如果leader挂掉,那么重新选取投票选leader(1)的阶段.
-如果挂掉leader返回,那么因为日志不同步,把他的日志信息清除变为参与者.根据任期来判断
-如果新增节点或者节点挂掉又加入.那么自动跟leader同步.
2日志复制:
网络分区造成的多个leader,以多数那个分区为主,没有网络分区问题,单纯的节点挂机,挂到一般以上时,数据将不会同步.所以只有环境下半数以上的节点活动,那么日志才会同步
心跳检测:
按一定时间间隔不断发送请求以检测节点是否正常,设置累计失效检测机制,如果过半的节点挂掉或者形成网络分区,那么为濒死状态,会影响性能
高可用性设计:
主备:一主设多备用,当主挂掉了,备用立即上主,主负责写.然后通过机制同步给备用,备用只负责查询.
互备:多个主机相互同步,都可以读写
集群:zookeeper管理多个主机,然后分配请求.
容错性:
缓存穿透:在一定时间内大量ddos攻击下,我们可以设置一段时间内只查缓存,先查一次数据库,如果查不到,那么给缓存生成一个空key,让这个重复请求只去缓存查而不要再去数据库查询,防止数据库压力
负载均衡:
轮询:默认模式,轮流接收请求.
最少连接:谁连接最少给谁.
IPhash:根据IPhash进行分配到哪个IP,缺点:容易造成数据倾斜
权重分配:根据性能设置nginx的weight.
分布式架构网络通信:
rpc:底层是sockets通讯
客户端:调用请求
客户端存根 client stub:存放服务端地址信息 将请求打包发送 (request的概念)
服务端:服务者
服务端存根:接收客户端消息,解包并调用本地方法 (response的概念)
调用流程:client->client stub ->server stub ->server
响应流程:server -> server stub -> client stub -> client
核心就是通讯和序列化 抛弃了http协议而已.直接在tcp层进行包装,少包装了一层协议
RMI java原生的rpc框架:
客户端 stub就像服务层的代理对象存在在本地
远程引用层:将服务器代理对象序列化,发给传输层
skeleton:类似于客户端端的代理对象 存在服务端
服务远程引用层:将客户端代理对象序列化,发给传输层
注册中心:将客户端和服务端注册
开发注意:
实体需要序列化
服务端service需要继承Remote...并将构造方法抛出异常
服务端需要注册 LgionRegistry 装入监听端口(问题 多个service可否一次注册?)
Naming 进行服务与url的绑定 这里用的是rmi协议 url为rmi://host:port/xxx 将具体的业务类绑定到这个url传入实例对象
客户端需要从注册中根据url获取代理对象 Naming获取
IO模型:
BIO:同步阻塞IO流
NIO:同步非阻塞IO流
通道将数据写入缓冲区,缓冲区传数据给通道
sekector选择器,进行客户端的监听是否有请求
AIO:异步非阻塞IO流 需要操作系统支持
netty模型:
NIO缺点:API复杂,开发难度大.会导致空轮询
netty优点:统一API
核心组件:
ChannelHandler接口 实现类为ChannelInboundHandlerAdapter,自定义类要继承这个方法
ChannelPipeline Handler集合形成一个handler链
ChannelHandlerContext 一个handler的上下文对象 一些handler的操作
ChannelFuture:异步操作获取当前channel对象
EventLoopGroup接口 EventLoop的抽象
ServerBootstrap 配置服务端信息
Bootstrap 客户端配置信息