java架构篇 ——主从模式的选举

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: java架构篇 ——主从模式的选举

前言

本文主要分析现代三高架构中的一个经典集群结构————主从模式,并分析一些常见框架在集群上的异同


随着现代数据处理量和对稳定性要求的水涨船高,高并发,高可用,高性能逐渐成为Java程序员的日常,但是这种架构暗藏很多难点,如果你对这种架构还有很多疑惑,可以直接锁定本栏目,会持续推出有关三高架构的内容


一、集群与主从

计算机集群简称集群,是一种计算机系统, 它通过一组松散集成的计算机软件或硬件连接起来高度紧密地协作完成计算工作。在某种意义上,他们可以被看作是一台计算机。需要注意的是,一般我们在架构上讲的集群是从业务角度看的,只有具备同种功能的多台机器才算一个集群。


我们都知道,当前Java的架构体系在使用的大部分程序或中间件,都具有组成集群的能力,并且也推荐以集群模式去部署,比如Redis


d39bee6dbbfd493ea8178e6fef819bf3.png


之所以大家都采用了集群的模式,主要是因为其强大的作用和优势,我们先看看集群的几个作用:


  • 提高计算能力:集群可以同时运行多个计算任务,从而提高整个系统的计算能力和性能。

  • 提高可用性:通过在多个计算节点上分配和复制数据和应用程序,集群可以提高整个系统的可用性和容错能力,即使某个节点发生故障,也可以在其他节点上继续运行。

  • 提高可扩展性:集群可以根据需要添加或删除节点,从而提高系统的可扩展性和灵活性,使其能够适应不同的工作负载和需求。

  • 分布式计算:集群可以支持分布式计算,将大型计算任务分割成多个子任务并在多个节点上并行计算,从而加速计算速度。

  • 负载均衡:通过将负载分配到不同的节点上,集群可以实现负载均衡,避免某个节点过载而导致整个系统崩溃。


而主从模式是集群模式的一种,是指在一个集群中,有一个主节点和多个从节点。主节点负责协调和控制整个集群的工作(有的组件主节点也会执行任务),而从节点负责处理具体的请求和任务。主节点可以进行数据的分发、负载均衡、任务调度、故障检测和恢复等操作,从节点可以并行处理任务,提高计算效率和性能

a981fbd3aea94c03ac7cf2858789813a.png


如上图,master即主节点,slave即从节点。主从模式常用于分布式数据库、分布式缓存和分布式计算等场景。支持主从模式的常见框架有Mysql 、Zookeeper、Redis等


二、主从选举问题

上一章我们提到了主从模式。我们需要知道主从模式的设计一般都用于存储类的组件,主要是需要保证数据的高可用与一致性,且由于该模式的数据冗余备份,对于异常场景的数据恢复也大有裨益,那么采用了主从模式的组件,现在有哪些难点呢?其中,首当其冲的就是高可用问题


1. redis 哨兵选取(Raft)

Sentinel(哨兵)是Redis的高可用性解决方案。


即由一个或多个Sentinel实例(instance)组成的Sentinel系统 (system)可以监视任意多个主服务器,以及这些主服务器属下的所有 从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务 器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替 已下线的主服务器继续处理命令请求

effeff25f36c4c369ee1483e3725aadd.png

哨兵功能主要有以下三个责任


  • 监控
  • 监控是指哨兵进程运行时,周期性给所有主从库发送PING命令,检测他们是否仍然在线运行。
  • 从库没有在规定时间内响应哨兵的PING命令,哨兵就会把它标记为"下线状态";
  • 主库没有在规定时间呢响应哨兵的PING命令,哨兵就会判定主库下线启动选主流程。
  • 选主
  • 哨兵在主库挂了以后,按照一定规则从从库中选出作为新的主库。
  • 通知
  • 哨兵将选出的新主库连接信息发给其他从库,让他们执行replicaof命令,和新主库建立连接,复制数据。同时,哨兵会把新主库的连接信息通知给客户端,让它们将操作请求发送给新主库上。

其中,面试提及最多的的就是选举流程,我们可以仔细看看该流程

Sentinel 选举主节点的过程如下:


  1. Sentinel 监测到某个主从系统的主节点不可达;
  2. Sentinel 向其他 Sentinel 节点询问当前的主节点状态,并提出自己成为哨兵主节点的请求;
  3. 如果 Sentinel 节点的数量达到了 quorum(quorum=Sentinel 节点数/2+1),则开始选举;
  4. Sentinel 节点按照一定的优先级进行选举,优先级高的节点更有可能被选为新的哨兵主节点;
  5. 如果没有节点获得多数投票,则重新开始选举,直至选出新的哨兵主节点。
  6. 哨兵主节点开始为主从系统选取Leader,此时又遵循下列规则

过滤故障的节点

选择优先级slave-priority最大的从节点作为主节点,如不存在则继续

选择复制偏移量(数据写入量的字节,记录写了多少数据。主服务器会把偏移量同步给从服务器,当主从的偏移量一致,则数据是完全同步)最大的从节点作为主节点,如不存在则继续

选择runid(redis每次启动的时候生成随机的runid作为redis的标识)最小的从节点作为主节点


2. zookeeper Zab协议崩溃恢复

与redis相比,zk没有哨兵机制,而是使用了Zab协议,zab协议有两个方面


崩溃恢复

消息广播

我们这里仅谈崩溃恢复,即当zk的主节点失效时,新的主节点,是由该主从系统中的从节点相互协商及投票形成的,而且各节点默认是选举自己,并把信息告知其他节点。

444332fe60704c39b68f757bd72e7ac7.png

由于每个节点都自带投票箱,能根绝自己投票箱的票数情况,进行变卦,也就是重新投票给别的节点,如此往复,直到大部分节点的投票箱都选的某个节点,然后该节点即为新的主节点。更加具体的流程,以及选举的优先级判断,可通过下图了解


fa86ed8b86844365b53368a7c736665d.png

这其中,作为选举规则,zxid 和 epoch 其实是关键。其实,在实现上,这两者是拼接起来的,即两者合在一起(因此有的说法就只说 ZXID),实际上是一个 64 位的数字,高 32 位是 epoch( 时期; 纪元;)用来标识 leader 周期,如果有新的 leader 产生出来,epoch会自增;低 32 位用来递增计数,就是每向系统做一次数据更新(增删改)的请求,就会递增


zxid 初始化是 0,也就是这样

766991f688174217970dda416698e74c.png

每一次写请求都会增加后 32 位,假设现在进行了 10 次写请求(无论该请求有没有真的修改到数据),zxid 就会变成这样

536edc8553404b7689e3ae46179e1ec2.png

当进行一次选举的时候,前 32 位就会增加 1,并且清零后 32 位

85c3a0b7306d487cb037f6a5d89d8015.png

除了选举以外,当后 32 位彻底用完(变成全 1,也就是 ZK 正常执行了 2^32 - 1 次写请求都没进行过一次选举)也会让前 32 位增加 1,相当于

e5f20bd4c2a64bb2b99648a47b14dbea.png


3. kafka Controller选择

kafka的主从用法和上面的并不一样,一般的主从模式,主节点(leader)负责更新,从节点(follower)负责查询,从而进行分流,然而kafka的从节点本身并不承担查询的功能,仅仅是作为备份存在,且根据备份的进度分为


  1. ISR(in-sync replica):保持同步的副本
  2. OSR(out-sync replica):未同步的副本

而要实现保持同步,Producer发送消息时,消息只有被全部写到了ISR中,才会被视为已提交状态

-1d21b5f1abad4ece84ad1a784fc58881.png


如果ISR中没有副本,只能从OSR中选举一个作为Leader,但是OSR中副本的数据可能会存在数据丢失,所以这个功能是可以配置的,默认是打开的。

配置项:
unclean.leader.election.enable = true/false

同样的,kafka的选举方式也有所不同,它的选举是由 Controller 一手操控的,当检测到主节点挂了,Controller能够从ISR里任选一个重新作为主节点,那么Controller又是怎么来的,当Controller所在的机器挂了,又当如何呢?

28e641801fbb4dcdb61b74d291dfb0ce.png


实际上,Kafka的信息管理依赖于内置的zookeeper,所谓的Controller也只是一个注册在zookeeper上的Broker(可认为是某台服务器),只不过需要负责一些额外的工作(追踪集群中的其他Broker,并在合适的时候处理新加入的和失败的Broker节点、Rebalance分区、分配新的leader分区等)。值得注意的是:Kafka集群中始终只有一个Controller Broker。


而至于Controller 是怎么选出来的?其实并不是选出来的,而是得益于zookeeper的分布式锁的应用(最先在Zookeeper上创建临时节点/controller),由各Broker竞争,最终只有一个成功注册了,那么该Broker就是新的Controller

3d82305ae0384420b782b555aed8dd59.png


如果Controller 断连,需要重新竞争一个Controller时,kafka会在epoch numbe上加1,表示新的Controller诞生,此时即使原Controller恢复,也不再拥有Controller的权力, epoch number记录在Zookeepr的一个永久节点controller_epoch


4. 选举方式总结

  • Redis的选举机制是基于Raft协议,用于选举哨兵(Sentinel)集群中的主节点,再由该主节点为主从系统选出主节点;
  • Zookeeper的选举机制是基于Zab协议(选举模式基于Paxos),用于选举领导者节点。
  • Kafka的选举机制是基于Zookeeper的分布式锁,竞争出出控制器节点Controller,然后Controller从ISR集合中选一个作为主节点;

不难看出,从一堆从节点中选择一个主节点分为两种情况:


  1. 一种就是从节点(或部分从节点)有着强一致协议,即这些节点的数据与主节点保持一致。这样随便从里面选一个出来就可以作为主节点
  2. 如果节点间一致性较弱,也就是说从节点可能落后于主节点,此时就需要选举出数据最接近的从节点,这种选举可以由从节点之间自行选出,也可以由第三方来指出。
  3. 如果涉及到第三方,即第三方来决定谁做主节点,那么第三方本身也要支持高可用和选举,如redis的Sentinel系统,zookeeper的Controller
  4. 一群节点间的选举,本质是共识算法,目前通用的共识算法为Raft与Paxos

目录
相关文章
|
1月前
|
消息中间件 Java Kafka
Java 事件驱动架构设计实战与 Kafka 生态系统组件实操全流程指南
本指南详解Java事件驱动架构与Kafka生态实操,涵盖环境搭建、事件模型定义、生产者与消费者实现、事件测试及高级特性,助你快速构建高可扩展分布式系统。
153 7
|
4月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
5月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
189 5
|
5月前
|
数据采集 运维 Serverless
云函数采集架构:Serverless模式下的动态IP与冷启动优化
本文探讨了在Serverless架构中使用云函数进行网页数据采集的挑战与解决方案。针对动态IP、冷启动及目标网站反爬策略等问题,提出了动态代理IP、请求头优化、云函数预热及容错设计等方法。通过网易云音乐歌曲信息采集案例,展示了如何结合Python代码实现高效的数据抓取,包括搜索、歌词与评论的获取。此方案不仅解决了传统采集方式在Serverless环境下的局限,还提升了系统的稳定性和性能。
152 0
|
2月前
|
Java 应用服务中间件 Docker
java-web部署模式概述
本文总结了现代 Web 开发中 Spring Boot HTTP 接口服务的常见部署模式,包括 Servlet 与 Reactive 模型、内置与外置容器、物理机 / 容器 / 云环境部署及单体与微服务架构,帮助开发者根据实际场景选择合适的方案。
112 25
|
2月前
|
存储 Java 大数据
Java 大视界 -- Java 大数据在智能家居能源消耗模式分析与节能策略制定中的应用(198)
简介:本文探讨Java大数据技术在智能家居能源消耗分析与节能策略中的应用。通过数据采集、存储与智能分析,构建能耗模型,挖掘用电模式,制定设备调度策略,实现节能目标。结合实际案例,展示Java大数据在智能家居节能中的关键作用。
|
2月前
|
缓存 Java 数据库
Java 项目分层架构实操指南及长尾关键词优化方案
本指南详解基于Spring Boot与Spring Cloud的Java微服务分层架构,以用户管理系统为例,涵盖技术选型、核心代码实现、服务治理及部署实践,助力掌握现代化Java企业级开发方案。
140 2
|
3月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
100 5
|
2月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
122 0