分布式里面包含各种概念,从对比的视角记录一下。
ca:关系型数据库
cp:redis,HBASE 强一致性(同步阻塞),分区容忍性(数据分开存储在多个节点)
paxos算法:分布式节点明确(多节点选主(数据最新+随机id),主节点负责增删改,从节点负责同步数据)
RocketMq:如果所有的 NameServer 全部挂掉,并且生产者有缓存 Topic 的路由信息,此时依然可以发送消息,procuder 每次发送消息,会采取轮询机制取下一个 MessageQueue,由于可能该 Message 所在的Broker挂掉,会抛出异常。30秒向namesrv不断上报自己的信息
消息持久化过程
- 消息处理器:消息到达SendMessageProcessor时,需要为消息随即分配队列,然后自己生成一个内部消息(msgInner),这个消息加入了一些broker内部的信息,例如:消息队列,消息内部标示,channel连接地址等。然后拿到broker的持久化模块,进行持久化。
- 消息持久化准备:processor将生成的内部消息交给commitLog时,生成消息的存储时间以及CRC消息体。拿到上一个存储消息的文件持久化工具,对文件准备进行持久化。
- 消息持久化:将刚刚的消息根据topic和消息队列号(queueId)拿到队列的偏移量,计算整个消息需要的存储长度,如果合规则写入缓存,然后写入文件中。
- 分发处理:在文件写入后将生成分发请求,有分发线程开始处理,将消息写入consumeQueue中
- 刷盘请求:根据消息的刷盘策略进行消息刷盘
Dubbo:刚开始初始化的时候,消费者会将提供者的地址等信息拉取到本地缓存,所以注册中心挂了可以继续通信。
高可用:1. 机器冗余,消除单点故障。数据复制会导致数据一致性问题,保证数据不丢失要做持久化
2. 对故障的检测和恢复。检测故障以及用备份的结点接管故障点。failover
3. 可靠的交汇点 dns,负载均衡
类型 | 集群架构 | 一致性协议 | 节点互联 | 分布式数据存储 | 节点动态扩容 | 节点故障检测(容错) | 高可用(故障转移) | |
redis | 分布式数据库 | M1 - M2 - M3 - S1 - S2 - S3 | gossip协议 | Cluster中的每个节点都维护一份在自己看来当前整个集群的状态,节点之间相互的心跳(PING,PONG,MEET)及其携带的数据(故障信息,节点的增加和删除,hash slot 信息) | 分片 采用虚拟哈希槽分区,所有的键根据哈希函数映射到 0 ~ 16383 整数槽内,计算公式:slot = CRC16(key) & 16383。每一个节点负责维护一部分槽以及槽所映射的键值数据 | 槽是 Redis 集群管理数据的基本单位,集群伸缩就是槽和数据在节点之间的移动 | 心跳消息和失效检测 一个节点在超时时间范围内没有返回pong,会认为节点pfail,如果节点认为某个节点pfail了会在gossip ping消息中ping给其他节点,如果超过半数的节点认为该节点pfail了,此时该节点fail | master宕机: 从节点过滤 从节点选举:从节点对于master复制的数据越多,优先进行选举 |
zookeeper | 分布式协调服务,注册 | Paxos算法 | 集群元数据(节点信息、故障等等)几种存储在某个节点上 | |||||
hdfs ha模式 | 分布式文件系统 | nn(多个,主备切换,元数据分片,journalnode),snn,dn | 主节点对外提供服务,发生故障时切换备机,备机从jn同步数据(主备可用性问题增加jn节点,jn节点使用paxos算法过半成功快速返回) |
Netty
每个 Boss NioEventLoop 循环执行的任务包含 3 步:
- 轮询 Accept 事件。
- 处理 Accept I/O 事件,与 Client 建立连接,生成 NioSocketChannel,并将 NioSocketChannel 注册到某个 Worker NioEventLoop 的 Selector 上。
- 处理任务队列中的任务,runAllTasks。任务队列中的任务包括用户调用 eventloop.execute 或 schedule 执行的任务,或者其他线程提交到该 eventloop 的任务。
每个 Worker NioEventLoop 循环执行的任务包含 3 步:
-
轮询 Read、Write 事件。
-
处理 I/O 事件,即 Read、Write 事件,在 NioSocketChannel 可读、可写事件发生时进行处理。
-
处理任务队列中的任务,runAllTasks
分布式服务:Dubbo
分布式消息:RocketMq
分布式缓存:Redis
当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件
I/O 多路复用程序允许服务器同时监听套接字的 AE_READABLE
事件和 AE_WRITABLE
事件, 如果一个套接字同时产生了这两种事件, 那么文件事件分派器会优先处理 AE_READABLE
事件, 等到 AE_READABLE
事件处理完之后, 才处理 AE_WRITABLE
事件
分布式调度:
分布式事务:TXC
分布式计算:Flink MapReduce
线程模型 | 负载均衡算法、失败策略 | 集群高可用 | 高并发 | 消息不丢失 | 备注 | |
Dubbo | I/O线程和业务线程分离,设置Netty的boss线程池数量为1,worker线程池(也就是I/O线程)为cpu核心数+1和向Netty中注册 Handler用于消息的编解码和处理 | 加权随机 加权轮询 一致性哈希 最小活跃
失败转移,快速失败,失败安全(记录日志),失败恢复(定时重试),并行调用,广播 | 注册中心down掉不会影响服务调用 | |||
Redis | I/O 多路复用程序,队列,事件分派器,事件处理器(命令请求,命令回复,连接应答,复制) | |||||
RocketMq | 启动多个
| 1. provider同步调用,发送失败后重试 2.在broker端,消息丢失的可能性主要在于刷盘策略和同步机制,同步复制可以保证即使Master 磁盘崩溃,消息仍然不会丢失 3. consumer端要保证消费消息的可靠性,主要通过At least Once+消费重试机制保证 | 解耦,削峰填谷,最终一致性 |
2. 动态扩容
3. 调用链
6. failover容错
7. 分布式事务
*分布式事务框架
*分布式消息
8. 幂等性
9. 分布式锁
10. 分布式session
为了使得集群能够水平扩展,首要解决的问题就是如何将整个数据集按照一定的规则分配到多个节点上,常用的数据分片的方法有:范围分片,哈希分片,一致性哈希算法和虚拟哈希槽等
哈希算法:CRC mermerHash FNV Ketama
参考