JAVA Web 学习(四)RabbitMQ、Zookeeper

十、消息队列服务器——RabbitMQ

RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、 安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

img

  1. Channel:网络信道,读写都是在Channel中进行(NIO的概念),包括对MQ进行的一些操作(例如clear queue等)都是在Channel中进行,客户端可建立多个Channel,每个Channel代表一个会话任务
  2. Message:由properties(有消息优先级、延迟等特性)和Body(消息内容)组成
  3. Exchange:Routing and Filter7、Binding:把Exchange和Queue进行Binding8、Routing key:路由规则
  4. Binding:把Exchange和Queue进行Binding
  5. Routing key:路由规则
  • 优点:
    1. 解除业务系统之间的耦合,降低系统之间的依赖关系
    2. 实现消息的异步处理,无需同步等待
    3. 削峰填谷,将流量从高峰期引到低谷期进行处理
  • 缺点:
    1. 增加了系统的复杂度,带入了幂等、重复消费、消息丢失的问题
    2. 系统的可用性比原先要低,MQ挂了以后,整个系统也会崩溃.
    3. 消费端数据一致性问题
  • 使用场景
    • 消息订阅
    • 日志采集
    • 埋点
    • 订单
基于消息的模型,关心的是“通知”,而非“处理”.
在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦.
为了保证库存肯定有,可以将队列大小设置成库存数量,或者采用其他方式解决。
四种交换机(Exchange)
  • i. 直连交换机,Direct exchange:带路由功能的交换机,根据routing_key(消息发送的时候需要指定)直接绑定到队列,⼀个交换机也可以通过过个routing_key绑定多个队列。
  • ii. 扇形交换机,Fanout exchange:⼴播消息。
  • iii. 主题交换机,Topic exchange:发送到主题交换机上的消息需要携带指定规则的routing_key,主题交换机会根据这个规则将数据发送到对应的(多个)队列上。
  • iv. ⾸部交换机,Headers exchange:⾸部交换机是忽略routing_key的⼀种路由⽅式。路由器和交换机路由的规则是通过Headers信息来交换的,这个有点像HTTP的Headers。将⼀个交换机声明成⾸部交换机,绑定⼀个队列的时候,定义⼀个Hash的数据结构,消息发送的时候,会携带⼀组hash数据结构的信息,当Hash的内容匹配上的时候,消息就会被写⼊队列。
1. 在RabbitMQ集群中的节点只有两种类型:内存节点/磁盘节点,单节点系统只运行磁盘类型的节点。而在集群中,可以选择配置部分节点为内存节点。
2. 内存节点将所有的队列,交换器,绑定关系,用户,权限,和vhost的元数据信息保存在内存中。
3. 磁盘节点将这些信息保存在磁盘中,但是内存节点的性能更高,为了保证集群的高可用性,必须保证集群中有两个以上的磁盘节点,来保证当有一个磁盘节点崩溃了,集群还能对外提供访问服务
两种模式
主从模式:默认的集群模式、(高性能)
  • 内存节点的性能只能体现在资源管理上,比如增加或删除队列(queue),虚拟主机(vrtual hosts),交换机(exchange)等,发送和接受message速度同磁盘节点一样。
  • rabbitmq集群中可以共享user,vhost,exchange等,所有的数据和状态都是必须在所有节点上复制的,在集群模式下只要有任何一个节点能够工作,RabbitMQ集群对外就能提供服务。
  • 消息实体只存在于其中一个节点,A、B两个节点仅有相同的元数据,即队列结构,但队列的元数据仅保存有一份,即创建该队列的rabbitmq节点(A节点),当A节点宕机,你可以去其B节点查看,./rabbitmqctl list_queues发现该队列已经丢失,但声明的exchange还存在。
## 消费流程
当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行消息传输,把A中的消息实体取出并经过B发送给consumer,所以consumer应平均连接每一个节点,从中取消息。
## 故障处理
该模式存在一个问题就是当A节点故障后,B节点无法取到A节点中还未消费的消息实体。如果做了队列持久化或消息持久化,那么得等A节点恢复,然后才可被消费,并且在A节点恢复之前其它节点不能再创建A节点已经创建过的持久队列;这种模式更适合非持久化队列,只有该队列是非持久的,客户端才能重新连接到集群里的其他节点,并重新创建队列。假如该队列是持久化的,那么唯一办法是将故障节点恢复起来。
镜像模式:高可用性

消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用

搭建注意
  • 各节点之间使用“–link”连接,此属性不能忽略。
  • 各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。
  • 整个集群中必须包含一个磁盘节点。
问题
如何保证MQ中消息不会丢失?
  • RabbitMQ允许将消息标记为持久化,这意味着消息将会被写入磁盘而不是仅保存在内存中。这样,在消息发送到队列之后,即使RabbitMQ服务器发生故障或重启,消息也能够存储在磁盘上,并在恢复后仍然可用。
  • 生产者发生异常没有把消息成功发送给MQ,MQ成功接收到消息之后发生宕机了,消息未被成功,消费消费端要设置签收机制为手动签收,只有当消息最终被处理,才告诉MQ已经消费,此时MQ再去删除这条消息。
  • 消息预取(Message Prefetch):RabbitMQ允许消费者一次从队列中获取多个消息,并将它们存储在本地缓冲区中。这样可以提高消费者的效率,并减少消费者与RabbitMQ服务器之间的通信次数。
/*消息持久化方法?
1.声明交换机Exchange的时候设置 durable=true;
2.声明队列Queue的时候设置 durable=true;
3.发送消息的时候设置消息的 deliveryMode = 2;*/
//public TopicExchange(String name, boolean durable, boolean autoDelete)
return new TopicExchange(EXCHANGE_NAME,true,false);
//durable:是否将队列持久化 true表示需要持久化 false表示不需要持久化
return new Queue(QUEUE_NAME, false);new MessageProperties() --> DEFAULT_DELIVERY_MODE = MessageDeliveryMode.PERSISTENT --> deliveryMode = 2;
如何解决消息堆积?
  • 启动多个消费者微服务
  • 优化消费者处理消息的能力,提高消费消息的性能
  • 调整RabbitMQ的队列容量
  • 设置过期时间,让一些不是那么重要的消息到达指定时间之后就丢弃
  • 将无法被消费的消息放到死信队列(DLQ)中
如何解决消息被重复消费?
  • 生产者发送消息的时候带上一个全局唯一的id,消费者拿到消息后,先根据这个id去 Redis 里查一下,之前有没消费过,没有消费过就处理,并且写入这个id到 Redis,如果消费过了,则不处理。
  • 基于数据库的唯一键
  • 消费者端幂等性:设计消费者端的处理逻辑具有幂等性。即无论消息被处理多次,最终结果都保持一致。这样,即使消息被重复消费,也不会对最终结果产生影响。
RabbitMQ 中 vhost 的作用是什么?

vhost:每个 RabbitMQ 都能创建很多 vhost,我们称之为虚拟主机,每个虚拟主机其实都是 mini 版的RabbitMQ,它拥有自己的队列,交换器和绑定,拥有自己的权限机制,主要是为了隔离,vhost 不仅消除了为基础架构中的每一层运行一个RabbitMq服务器的需要, 童谣避免为每一层创建不同的集群.

RabbitMQ 集群中唯一一个磁盘节点崩溃了会发生什么情况?

如果唯一磁盘的磁盘节点崩溃了,
唯一磁盘节点崩溃了,集群是可以保持运行的,但你不能更改任何东西。

RabbitMQ 每个节点是其他节点的完整拷贝吗?为什么?

不是,原因有以下两个:

  • 存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;

  • 性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟

rabbitMQ节点的关闭顺序?

在关闭 RabbitMQ 集群时,应该先关闭从节点,然后再关闭主节点。这是因为从节点的状态是依赖于主节点的,如果先关闭主节点,可能会导致从节点无法正常工作。

十一、分布式应用程序协调服务——ZooKeeper

ZooKeeper 是一个开源的分布式协调框架,它的定位是为分布式应用提供一致性服务,是整个大数据体系的管理员ZooKeeper 会封装好复杂易出错的关键服务,将高效、稳定、易用的服务提供给用户使用。

img

特点
  1. 集群:Zookeeper是一个领导者(Leader),多个跟随者(Follower)组成的集群。
  2. 高可用性:集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。
  3. 全局数据一致:每个Server保存一份相同的数据副本,Client无论连接到哪个Server,数据都是一致的。
  4. 更新请求顺序进行:来自同一个Client的更新请求按其发送顺序依次执行。
  5. 数据更新原子性:一次数据更新要么成功,要么失败。
  6. 实时性:在一定时间范围内,Client能读到最新数据。
  7. 设计模式角度来看,zk是一个基于观察者设计模式的框架,它负责管理跟存储大家都关心的数据,然后接受观察者的注册,数据反生变化zk会通知在zk上注册的观察者做出反应。
Zookeeper 有三种部署模式:单机部署:一台集群上运行;集群部署:多台集群运行;伪集群部署:一台集群启动多个 Zookeeper 实例运行。
Zookeeper 保持主从节点的同步?Zookeeper 的核心是原子广播机制,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式。
为什么要有主节点?在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能
ZooKeeper文件系统

ZooKeeper文件系统(ZooKeeper File System,ZFS)是ZooKeeper提供的一种类似于文件系统的数据模型,可以帮助用户通过树形节点结构,对ZooKeeper中的数据进行管理和访问。

在ZFS中,数据存储以节点(ZNode)的形式组织,每个ZNode可以保存一个Byte数组,同时也可以是一个目录节点,包含了子节点的信息。用户可以通过ZFS的API接口,对节点进行创建、读取、更新和删除等操作。

ZFS的根节点是"/“,通过这个节点,用户可以访问整个ZooKeeper文件系统。节点名字可以是任何的字符串,但是不能重复,节点名字可以有多级,中间用”/ "隔开。例如,/myapp/config是一个典型的ZFS节点路径。

ZNode节点四种类型:
  • 持久节点(persistent):这是最常见的节点类型,一旦创建,将一直存在于ZooKeeper的目录结构中,直到显式删除。
  • 临时节点(ephemeral):临时节点是指在创建客户端会话期间存在的节点。当客户端会话结束(由于某种原因)时,节点将被自动删除。临时节点非常有用,它们可以用于表示客户端会话是否处于特定状态。
  • 有序节点(sequential):有序节点还可以与上述两种节点类型结合使用,这样可以创建名称自动带有序增量的节点。有序节点用于排序构造出一种递增的节点名称集合。
  • 临时顺序节点(ephemeral sequential):这是一种组合节点类型,是临时节点和顺序节点的组合。这种节点将在客户端会话期间存在,并带有一个顺序号。当会话终止时,顺序号将自动从数据库中删除。
监听通知流程
  • 在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责网络连接通信(connet),一个负责监听(listener)。
  • 通过connect线程将注册的监听事件发送给Zookeeper。
  • 在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。
  • Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程。
  • listener线程内部调用了process()方法。
  • ZooKeeper 支持watch(观察)的概念。客户端可以在每个znode节点上设置一个观察。如果被观察服务端的znode结点有变更,那么watch就会被触发,这个watch所属的客户端将接收到一个通知包被告知结点已经发生变化,把相应的事件通知给设置过Watcher的Client端。
应用场景
1. 数据发布/订阅

当某些数据由几个机器共享,且这些信息经常变化数据量还小的时候,这些数据就适合存储到ZK中。

  • 数据存储:将数据存储到 Zookeeper 上的一个数据节点。
  • 数据获取:应用在启动初始化节点从 Zookeeper 数据节点读取数据,并在该节点上注册一个数据变更 Watcher
  • 数据变更:当变更数据时会更新 Zookeeper 对应节点数据,Zookeeper会将数据变更通知发到各客户端,客户端接到通知后重新读取变更后的数据即可。
2. 分布式锁

主要是避免了羊群效应,临时节点已经预先存在,所有想要获得锁的线程在它下面创建临时顺序编号目录节点,编号最小的获得锁,用完删除,后面的依次排队获取。

img

3. 负载均衡
  • 多个服务注册
  • 客户端获取中间件地址集合
  • 从集合中随机选一个服务执行任务

img

  1. 命名服务

利用 zk 创建一个全局唯一的路径,这个路径就可以作为一个名字,指向集群中的集群,提供的服务的地址,或者一个远程的对象等等。

  1. Leader选举

    利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,即:同时有多个客户端请求创建 /Master 节点,最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很轻易的在分布式环境中进行集群选举了。

    就是动态Master选举。这就要用到 EPHEMERAL_SEQUENTIAL类型节点的特性了,这样每个节点会自动被编号。允许所有请求都能够创建成功,但是得有个创建顺序,每次选取序列号最小的那个机器作为Master

## ZooKeeper集群节点个数一定是奇数个
在节点数量是奇数个的情况下, zookeeper集群总能对外提供服务(即使损失了一部分节点);如果节点数量是偶数个,会存在zookeeper集群不能用的可能性(脑裂成两个均等的子集群的时候)。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT研究笔记(一)windows 开发环境安装部署

一、Qt 是什么? Qt 是一个跨平台的应用程序开发框架,最初由挪威的 Trolltech 公司开发,并于2008年被诺基亚收购。后来,Qt 框架由 Digia 公司接手,并在2012年成立了 The Qt Company。Qt 提供了一套丰富的工具和类库&am…

Django模型(五)

一、数据的条件查询 参考文档:QuerySet API 参考 | Django 文档 | Django 1.1、常用检索字段 字段检索,是在字段名后加 __ 双下划线,再加关键字,类似 SQL 语句中的 where 后面的部分, 如: 字段名__关键字 exact :判断是否等于value,一般不使用,而直接使用 =contai…

微信网页授权之使用完整服务解决方案

目录 微信网页授权能力调整造成的问题 能力调整的内容和理由 原有运行方案 is_snapshotuser字段 改造原有方案 如何复现测试场景 小结 微信网页授权能力调整造成的问题 依附于第三方的开发,做为开发者经常会遇到第三方进行规范和开发的调整,如开…

2023年上-未来几年我要做什么

1月份,离职。 2月份,春节休假回来,中旬去参加了一个月的瑜伽培训,学会了倒立、鹤蝉。。。。 3月份,瑜伽培训结束,开始收拾房子,并调研各类项目。 4月份,参与了朋友的区块链项目 …

Java学习-常用API-ArrayList

ArrayList的遍历并删除元素(案例)ArrayList的常用apiArrayList是一种泛型集合ArrayList是什么?有何特点?作用? importjava.util.ArrayList; importjava.util.List; publicclassapiArrayListDemo1{ publicstaticvoidmai…

vue3.0中从proxy中取值

使用vue3.0时,因为底层是使用proxy进行代理的所以当我们打印一些值的时候是proxy代理之后的,是Proxy 对象,Proxy对象里边的[[Target]]才是真实的对象。也是我们需要的 第一种获取target值的方式: import { toRaw } from vue; le…

Logback学习

logback 1、logback介绍 Logback是由log4j创始人设计的另一个开源日志组件,性能比log4j要好。 lockback优点: 内核重写、测试充分、初始化内存加载更小,这一切让logback性能和log4j相比有诸多倍的提升。logback非常自然地直接实现了slf4j…

学习Spring的第十三天

非自定义bean注解开发 设置非自定义bean : 用bean去修饰一个方法 , 最后去返回 , spring就把返回的这个对象,放到Spring容器 一 :名字 : 如果bean配置了参数 , 名字就是参数名 , 如果没有 , 就是方法名字 二 : 如果方法产生对象时 , 需要注入数据 , 在方法参数设置即可 , …

基于springboot就业信息管理系统源码和论文

随着信息化时代的到来,管理系统都趋向于智能化、系统化,就业信息管理系统也不例外,但目前国内仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化,而…

Unity animator 动画实现指定时间开始播放

在我们使用Unity帧动画时,如用到同一个帧动画的部分动画,那么我们可以考虑用指定播放时间的方法实现。 如我在场景中创建一个2D帧动画,并创建一个2D对象使用该帧动画。 然后复制该2D对象,并创建一个控制脚本GameController1.cs&a…

【Docker】Docker Registry(镜像仓库)

文章目录 一、什么是 Docker Registry二、镜像仓库分类三、镜像仓库工作机制四、常用的镜像仓库五、常用命令镜像仓库命令镜像命令(部分)容器命令(部分) 六、docker镜像仓库实战综合实战一:搭建一个 nginx 服务综合实战二:Docker hub上创建自己私有仓库综…

【数据结构 09】哈希

哈希算法:哈希也叫散列、映射,将任意长度的输入通过散列运算转化为固定长度的输出,该输出就是哈希值(散列值)。 哈希映射是一种压缩映射,通常情况下,散列值的空间远小于输入值的空间。 哈希运…

正则表达式 与文本三剑客(sed grep awk)

一,正则表达式 (一)正则表达式相关定义 1,正则表达式含义 REGEXP: Regular Expressions,由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意…

编程实例分享,眼镜店电脑系统软件,配件验光管理顾客信息记录查询系统软件教程

编程实例分享,眼镜店电脑系统软件,配件验光管理顾客信息记录查询系统软件教程 一、前言 以下教程以 佳易王眼镜店顾客档案管理系统软件V16.0为例说明 如上图, 点击顾客档案,在这里可以对顾客档案信息记录保存查询,…

XUbuntu22.04之如何创建、切换多个工作区(二百零九)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

远程手机搭建Termux环境,并通过ssh连接Termux

背景 Termux只能通过鼠标点击,无法使用电脑键盘,输入速度很慢,你想通过ssh 连接Termux,获得友好体验搞了个云手机,想像普通手机那样充当服务器想把自己的手机公开到局域网中供同事调试想把自己的模拟器公开到局域网中…

红外模块详解

和红外有关的模块有很多,比如红外循迹,红外感应,红外发射,红外接收,红外对射,红外编解码等等。 今天我们要介绍的是红外编解码模块,它最常见的应用就是我们家里的电视、空调,当我们…

Java语法学习线程基础

Java语法学习线程基础 大纲 概念创建线程线程终止常用方法用户线程和守护线程线程的七大状态线程的同步互斥锁线程死锁释放锁 具体案例 1.概念 2. 创建线程 第一种: class Cat extends Thread {int time 0;Overridepublic void run() {while (true) {System.o…

HttpRunner自动化测试工具之获取响应数据extract提取值到变量

获取响应数据 extract: 提取 注:extract 应与request保持同一层级 1、响应行,响应头;通过 extract 提取响应的数据并存储到变量中,如下图: 注:变量名的前面要有 - # 获取响应数据: 响应行(…

通过Nacos权重配置,实现微服务金丝雀发布效果(不停机部署)

在微服务项目迭代的过程中,不可避免需要上线;上线对应着部署,或者升级部署;部署对应着修改,修改则意味着风险。 传统的部署都需要先停止旧系统,然后部署新系统,之后需要对新系统进行全面的功能测试&#xf…