聊聊分布式集群的基本概念

news2025/1/10 11:36:53

在当前主流的分布式架构中,各种各样的集群技术几乎成了任何想要提升系统稳定性和处理能力的团队的必备技能。虽然各种中间件和系统都有让人看似眼花缭乱的集群实现方案,但其背后仍然逃不过一些核心的技术概念,我会结合几个我比较熟悉的中间件,简单聊一下我对集群的理解:

集群的类型

按照搭建集群的目标来划分,大致可以划分为三类集群

高可用集群

高可用性集群的主要目的是使集群的整体服务尽可能可用,在集群中任意一个节点失效的情况下,该节点上的所有任务会自动转移到其他正常的节点上。此过程并不影响整个集群的运行,能够有效的避免单点故障。高可用集群要求节点间可以进行任务和状态的迁移。我们通常所说的双机热备,也就是某种意义上的高可用集群。

负载均衡集群

负载均衡集群的主要是通过一个或多个负载均衡器,基于一定的算法将客户端集中的访问请求负载压力尽可能平均地分摊在集群中的各个节点进行处理,实现访问请求在各节点之间动态分配,以提升集群整体的吞吐量和性能,避免单个节点的网络,硬件资源等成为性能瓶颈,实现服务的横向扩展。这个例子就很多了,比如通过nginx反向代理多个后端的web服务器实例,实现多实例间的负载均衡。

高性能集群

主要用于大型任务的并行计算,将一个复杂问题拆分为多个可以并行执行的任务在多个节点同时进行计算,主要用于大数据领域,比如hadoop的mapreduce,flink,spark等等。

常用中间件的集群实现

Kafka集群

kafka的集群基于副本机制来实现了高可用,然后通过多broker,多分区来实现消息生产和消费的负载均衡,整个集群的架构图如下:
kafka集群

核心概念作用
Broker消息中间件处理节点,一个Kafka节点就是一个broker,一个或者多个Broker可以组成一个Kafka集群
TopicKafka根据topic对消息进行归类,发布到Kafka集群的每条消息都需要指定一个topic
Partition分区,物理上的概念,一个topic可以分为多个partition,每个partition内部消息是有序的,一个分区可以简单的看作一个日志文件
Producer消息生产者,向Broker发送消息的客户端
Consumer消息消费者,从Broker读取消息的客户端
ConsumerGroup消费者组,每个Consumer属于一个特定的Consumer Group,一条消息可以被多个不同的Consumer Group消费,但是一个Consumer Group中只能有一个Consumer能够消费该消息Partition

Clickhouse集群

clickhouse集群有两个重要的概念:分片(shard)和 副本(replica),分片与分片间存储了不同的数据,而副本与副本之间数据是一致的(最终一致),一个分片可以有多个副本。从这里就可以看出它是通过分片实现负载均衡,而对分片创建副本来实现分片的高可用。一个典型的clickhouse集群主要由六个节点组成,分别为3个分片以及每个分片一个副本,:
在这里插入图片描述
这六个节点构成集群的配置如下:

<remote_servers>
  <!-- User-specified clusters -->
  <replicated>
    <shard>
      <internal_replication>true</internal_replication>
      <replica>
        <host>chi-clickhouse-replicated-0-0</host>
        <port>9000</port>
        <secure>0</secure>
      </replica>
      <replica>
        <host>chi-clickhouse-replicated-0-1</host>
        <port>9000</port>
        <secure>0</secure>
      </replica>
    </shard>
    <shard>
      <internal_replication>true</internal_replication>
      <replica>
        <host>chi-clickhouse-replicated-1-0</host>
        <port>9000</port>
        <secure>0</secure>
      </replica>
      <replica>
        <host>chi-clickhouse-replicated-1-1</host>
        <port>9000</port>
        <secure>0</secure>
      </replica>
    </shard>
    <shard>
      <internal_replication>true</internal_replication>
      <replica>
        <host>chi-clickhouse-replicated-2-0</host>
        <port>9000</port>
        <secure>0</secure>
      </replica>
      <replica>
        <host>chi-clickhouse-replicated-2-1</host>
        <port>9000</port>
        <secure>0</secure>
      </replica>
    </shard>
  </replicated>

客户端在使用clickhouse集群时,一般会用到两种特定类型的表引擎,用于在集群间分发和同步数据,一个是ReplicatedMergeTree,这类表引擎在写入时如果某个分区配置了副本,就会基于zk的异步复制机制去同步所有的副本节点。另一类是Distributed,这类表引擎创建的表并不会实际存储数据,只是起到一个代理的作用,将SQL操作分发到各个分区去执行。使用示例如下:

-- 创建数据的的物理表,使用ReplicatedMergeTree进行副本复制,注意需要添加**on cluster**关键字,这样才会在所有的集群节点上创建表,否则只会在当前执行SQL的节点上创建。
create table IF NOT EXISTS testdb.table_local on cluster replicated (
    `id` String,
    `value` String,
    `ts` DateTime64
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/table', '{replica}')
PARTITION BY toYYYYMM(time)
ORDER BY (time,pk,deviceId,identifier,tenantId)
TTL toDateTime(time)  + INTERVAL 7 DAY
SETTINGS index_granularity = 8192;

-- 创建物理表的代理表,实现请求分发和负载均衡
create table IF NOT EXISTS  testdb.data_table_all on cluster replicated  as table_local ENGINE = Distributed(replicated, testdb, table_local, rand());

整个客户端将数据写入clickhouse集群的数据流图如下:
clickhouse集群

EMQX集群

emqx集群中的每个emqx实例称之为一个节点(node),集群中的所有节点之间都会相互建立TCP连接进行通讯,形成一个网状结构:
在这里插入图片描述EMQX 分布式的基本功能是将消息转发和投递给各节点上的订阅者,如下图所示:
在这里插入图片描述
为实现此过程,EMQX 维护了几个与之相关的数据结构:订阅表,路由表,主题树。

订阅表:

主要保存了从主题(topic)到订阅者(Subscriber)的映射关系,订阅表只保存在于订阅者所在的 EMQX 节点上,并不会在整个集群间共享,数据结构如下:

node1:

topic1 -> client1, client2
topic2 -> client3

node2:

topic1 -> client4
路由表:

主要保存了从主题(topic)到节点(node)的映射关系,这里的节点是指连接了该主题订阅者(客户端)的节点,例如:

topic1 -> node1, node2
topic2 -> node3
topic3 -> node2, node4

集群中的所有节点都会复制一份相同的路由表。

主题树:

每个emqx节点除了都会维护一份路由表以外,还会维护一份主题树,保存的信息为带通配符的主题与实际的topic之间的映射关系,例如如果存在下述主题订阅关系:

客户端节点订阅主题
client1node1t/+/x, t/+/y
client2node2t/#
client3node1t/+/x, t/a

在所有订阅完成时,EMQX 中会维护如下主题树 (Topic Trie) 和路由表 (Route Table):
在这里插入图片描述
由此可见,EMQX集群只实现了分片,而没有通常意义上的副本,而是通过将需要维护状态的数据广播到所有节点来保持系统的高可用,这样在某个节点离线后,连接到该节点的客户端只需要重新连接一次集群,即可恢复对消息的处理。

消息派发过程:

根据上面的例子,整个消息派发过程如下:
在这里插入图片描述

订阅者负载均衡

emqx提供共享订阅机制来在客户端订阅者中实现负载均衡,多个订阅者可以订阅同一个topic,emqx根据一定的算法将消息分发给不同的订阅者

                                                   [subscriber1] got msg1
             msg1, msg2, msg3                    /
[publisher]  ---------------->  "$share/g/topic"  -- [subscriber2] got msg2
                                                 \
                                                   [subscriber3] got msg3

上图中,共享 3 个 subscriber 用共享订阅的方式订阅了同一个主题 $share/g/topic,其中topic 是它们订阅的真实主题名,而 $share/g/ 是共享订阅前缀。EMQX 支持两种格式的共享订阅前缀:

示例前缀真实主题名
$queue/t/1$queue/t/1
$share/abc/t/1$share/abct/1

在同一个订阅群组内,可以选择以下的负责均衡策略:

均衡策略描述
hash_clientid按照发布者 ClientID 的哈希值
hash_topic按照源消息主题的哈希值
local优先选择和发布者在同一各节点的共享订阅者来派发消息,否则进行随机派发
random在所有订阅者中随机选择
round_robin按照一个固定的顺序选择下一个订阅者
sticky首次分发时随机选择一个订阅者,后续消息一直发往这一个订阅者直到该订阅者离线或该发布者重连
生产者负载均衡

emqx没有提供broker的代理,所以客户端连接emqx集群时依赖于外部机制来确保负载均衡,比如在OS内部是使用K8S服务名的方式,将每个客户端的连接请求均匀的分发到不同的emqx broker。客户端断线重连后可能会连接到不同的broker节点。

集群技术总结

不同的中间件虽然在集群实现细节上有不少差异,但是一些基本概念是共同的:

  1. 都存在分片(分区)副本的概念,集群中不同的分片保存了不同的数据和状态,但同一个分片一般具备多个副本,副本与副本间的数据和状态是一致的(最终一致),副本一般分为master(leader)slave两种角色,仅master接收读写请求(clickhouse例外,多个副本可以同时接收写请求,是多写结构),slave在master挂掉以后通过选举算法确定出新的master。分片的目标是负载均衡,副本的目标是高可用;
  2. 集群的状态和数据分为两种,一种算是元数据,元数据需要在集群所有实例间进行共享;另一种是实例状态数据,这部分数据一般只保留在实例节点本地;
  3. 集群间状态和数据的共享分为两种形式,一是利用外部独立的中间件作为分布式协调器(比如zookeeper,etcd等等)保存需要共享的元数据,确保元数据在不同节点上的强一致性;另一种是通过某种协议主动在集群节点间同步需要共享的数据,比如redis的gossip协议,这种一般只能做到数据的最终一致性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1820538.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java.nio.charset.UnmappableCharacterException

问题 java.lang.IllegalArgumentException: java.nio.charset.UnmappableCharacterException: Input length 1 解释为编码转换有问题 问题错在位置 非汉字存在 打包的时候就会报异常

怎么把wma格式转化为mp3格式?四种wma格式转成MP3格式的方法

怎么把wma格式转化为mp3格式&#xff1f;转换WMA格式音频文件为MP3格式是一个常见的需求&#xff0c;尤其是在我们希望在不同设备或平台上播放音频时。WMA格式虽然在Windows系统中较为常见&#xff0c;但在其他平台上的兼容性可能不如MP3格式。因此&#xff0c;将WMA转换为MP3是…

c#引用dll报错cs8370功能“本地函数特性“在c#7.3中不可用

cs8370:功能"本地函数特性"在c#7.3中不可用 解决方法&#xff1a; 代码放在form类里面

YOLOv5改进 | Head | 将yolov5的检测头替换为ASFF_Detect

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 在目标检测中&#xff0c;为了解决尺度变化的问题&#xff0c;通常采用金字塔特征表示。然而&#xff0c;对于基于特征金字塔的单次检测器来…

NestJS学习笔记

一、安装NestJS CLI工具 环境检查 //查看node版本 node -v//查看npm版本 npm -v 安装nest/cli 使用npm全局安装nestjs/cli npm i -g nestjs/cli 查看nest版本 nest -v 结果如图&#xff1a; 创建nest项目 //命令行创建nest项目 nest new 【项目名】 VScode扩展下载 1、…

体验版小程序访问不到后端接口请求失败问题解决方案

文章目录 解决方案一&#xff1a;配置合法域名解决方案二&#xff1a;开发调试模式第一步&#xff1a;进入开发调试模式第二步&#xff1a;启用开发调试 注意事项结语 &#x1f389;欢迎来到Java面试技巧专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&…

银行业信息技术外包(ITO)深度解析:现状、挑战、业务分类与协同策略

一、引言 最近有朋友在咨询关于银行业信息技术外包&#xff08;ITO&#xff09;这块业务&#xff0c;同时也在网上看到了关于银行业信息技术外包&#xff08;ITO&#xff09;的相关信息&#xff0c;今天正好有时间&#xff0c;通过采集的相关信息结合自己的相关工作接触到的相关…

推挽与开漏输出

一般来说&#xff0c;微控制器的引脚都会有一个驱动电路&#xff0c;可以配置不同类型的数字和模拟电路接口。输出模式一般会有推挽与开漏输出。 推挽输出 推挽输出&#xff08;Push-Pull Output&#xff09;&#xff0c;故名思意能输出两种电平&#xff0c;一种是推&#xf…

STM32开发过程中碰到的问题总结 - 1

文章目录 前言1. 怎么生成keil下可以使用的文件和gcc下编译使用的makefile2. STM32的时钟树3.怎么查看keil5下的编译工具链用的是哪个4. Arm编译工具链和GCC编译工具链有什么区别吗&#xff1f;5. 怎么查看Linux虚拟机是x86的还是aarch646. 怎么下载gcc-arm的编译工具链7.怎么修…

JavaScript的数组排序

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

css设置滚动条样式;滚动条设置透明

滚动条透明代码 .resizable-div {resize: both;/* 允许水平和垂直调整大小 */overflow: auto;/* 确保内容超出边界时出现滚动条 */ } /* 滚动条整体样式 */ .resizable-div::-webkit-scrollbar {width: 4px; /* 竖直滚动条宽度 */height: 4px; /* 水平滚动条高度 */ }/* 滚动条…

使用uniapp设置tabbar的角标和移除tabbar的角标

使用场景描述 在一进入到小程序的时候就要将用户在购物车中添加的商品总数&#xff0c;要以角标的形式显示在tababr中。 代码实现 //index.vue<script setup> import { onLoad } from dcloudio/uni-apponLoad(()>{uni.setTabBarBadge({index: 1,text: 5 //为了实现…

VBA实现关闭Excel自动计算,关闭屏幕刷新

Excel代码提速神器 涉及到提取表格大量数据操作&#xff0c;复制粘贴多个单元格时&#xff0c;尽量避免一个个单元格提取&#xff0c;或者一行行一列列提取数值&#xff0c;设计大量IO流操作非常浪费时间。尽量找出数据之间的规律&#xff0c;批量选中复制粘贴&#xff0c;找到…

【大数据】Spark使用大全:下载安装、RDD操作、JAVA编程、SQL

目录 前言 1.下载安装 2.RDD操作 3.JAVA编程示例 4.Spark SQL 前言 本文是作者大数据系列中的一文&#xff0c;专栏地址&#xff1a; https://blog.csdn.net/joker_zjn/category_12631789.html?spm1001.2014.3001.5482 该系列会成体系的聊一聊整个大数据的技术栈&…

P3388 【模板】割点(割顶)

题目背景 割点 题目描述 给出一个 n 个点&#xff0c;m 条边的无向图&#xff0c;求图的割点。 输入格式 第一行输入两个正整数 n,m。 下面 m 行每行输入两个正整数 x,y 表示 x 到 y 有一条边。 输出格式 第一行输出割点个数。 第二行按照节点编号从小到大输出节点&am…

实验五 网络中的树

文章目录 5.1 网络中的树第一关 认识树相关知识编程要求代码文件 第2关 根节点的二阶邻居求解方法相关知识编程要求代码文件 第3关 根节点的n阶邻居求解方法相关知识 5.2 权值矩阵与环&#xff08;无向网络&#xff09;第1关 无向网络的权值矩阵相关知识编程要求代码文件 第2关…

CrossOver 2024软件下载-CrossOver 2024详细安装教程

Crossover软件是一款可以在Mac、Linux和Chromebook上运行Windows程序的软件。 它是一款商业软件&#xff0c;由CodeWeavers公司开发&#xff0c;Crossover不是一个虚拟机或模拟器&#xff0c;它使用Wine技术来将Windows程序直接转换成可以在其他操作系统上运行的程序&#xff0…

基于SpringBoot3+Vue3宠物小程序宠物医院小程序的设计与实现

大家好&#xff0c;我是程序员小孟。 最近开发了一个宠物的小程序&#xff0c;含有详细的文档、源码、项目非常的不错&#xff01; 一&#xff0c;系统的技术栈 二&#xff0c;项目的部署教程 前端部署包&#xff1a;npm i 启动程序&#xff1a;npm run dev 注意事项&…

HSP_07章 排序和查找

P96_ 冒泡排序 排序的基本介绍 冒泡排序介绍 冒泡排序思路分析 代码 # 说明,如果只是完成排序功能,我们可以直接使用list的方法sort # 排序的列表 num_list[24,69,80,57,13,0,900,-1] print("排序前".center(32,"-")) print(f"num_list: {num_list}…

Ceph入门到精通-Bucket 生命周期的作用,新手该如何设置?

存储桶(Bucket)生命周期策略的作用主要是帮助存储管理员高效地管理对象的存储周期,包括对象的转换、存档和删除。以下是关于桶生命周期的作用和配置的概述: 一、桶生命周期的作用: 存储优化:通过将对象转换到更经济的存储类别,降低存储成本。 数据管理:自动删除不再需…