rabbitmq的binding key和routing key的区别?

创建一个topic,这个topic会划分为多个partition,每个partition存在于不同的broker上,每个partition就放一部分数据。

binding

rabbitmq交换机_rabbitmq交换机和队列rabbitmq交换机_rabbitmq交换机和队列


rabbitmq交换机_rabbitmq交换机和队列


key是队列和交换机之间的绑定key,而routing

key是生产者发给交换机的一个信息,当routing

keAMQP(高级消息队列协议)是一个异步消息传递所使用的应用层协议规范,作为线路层协议,而不是API(例如JMS),AMQP客户端能够无视消息的来源任意发送和接受信息。AMQP的原始用途只是为金融界提供一个可以彼此协作的消息协议,而现在的目标则是为通用消息队列架构提供通用构建工具。因此,面向消息的中间件(MOM)系统,例如发布/队列,没有作为基本元素实现。反而通过发送简化的AMQ实体,用户被赋予了构建例如这些实体的能力。这些实体也是规范的一部分,形成了在线路层协议顶端的一个层级:AMQP模型。这个模型统一了消息模式,诸如之前提到的发布/,队列,事务以及流数据,并且添加了额外的特性,例如更易于扩展,基于内容的路由。AMQP当中有四个概念非常重要virtualhost,虚拟主机exchange,交换机queue,队列binding,绑定一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢?因为RabbitMQ当中,用户只能在虚拟主机的粒度进行权限控制。因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个RabbitMQ都有一个默认的虚拟主机/。何谓虚拟主机(virtualhost),交换机(exchange)y和binding

key能对应上message持久化:的时候就发到相应的队列中

spring boot中使用rabbitmq怎么在代码里面获取消费端的重试次数?

list_connections [ ...] 打印l连接列表

在使用SpringBoot中,笔者使用到了RabbitMQ,其中踩了不少地雷,经过些许的刻版终于把它调通了,

到此,RabbitMQ提供的几种机制都介绍完了,但这样还不足以保证消息可靠性投递RabbitMQ中,上面我也提到了会有极端情况,比消息丢失会出现在三个环节,分别是生产者、mq中间件、消费者:如RabbitMQ收到消息还没来得及将消息持久化到硬盘时,RabbitMQ挂了,这样消息还是丢失了,或者RabbitMQ在发送确认消息给生产端的过程中,由于网络故障而导致生产端没有收到确认消息,这样生产端就不知道RabbitMQ到底有没有收到消息,就不好做接下来的处理。

首先说明下整个过程.

在 Spring-AMQP 中比较重要的类就是 Message ,因为要发送的消息必须要构造成一个 Message 对象来进行传输。Message 对象包括两部分 Body 和 Properties

消息生产者构造好 Message 之后,就会将 Message 发送到指定的 Exchange (交换机),再根据 Exchange 的类型及 routing-key 将消息路由到相应的 queue 中,被该 queue 的消费者消费.

rabbitmq一定要绑定交换机才可以发送消息吗

笔者主要说的是从生产者生产数据并发送给消费者到后者接收并处理数据这么一个全过程,我这里的数据指的是实体对象.生产者和消费者是处在两个不同的项目中的.

1. 需要“消息延迟”功能 这对我们来说是很重要的业务需求。当顾客订了一个服务,首先我们会发送描述相信指令的短信,然后我们会在两分钟后发送第二条描述详情的短信,而不是两条一起发送mament可以做的任何事外加Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输,:。我们希望通过这样,留给用户阅读的时间(每次间隔2分钟)

如何在windows下 修改rabbitmq node name

普通集群模式

rabbitmqctl管理工具的使用标准格式为:rabbitmqctl [-n node] [-t timeout]rabbitmqctl set_permissions -p myvhost userName ‘.’‘.’‘.’ [-q] {command} [command options...]

其中-n -t -q为管理工具的参数,

-n 指定默认为rabbit@server,即所有的命令都是在这个上执行的;

-t 设置超时时间,该参数只对list相关的命令适用,默认为无穷大。

以上三个参数一般很少用到,只有在集群管理时可以指定非常有用,如不是运维人员,只是为了开发方便,一般选择默认就足够了。

rabbitmqctl提供了非常丰富的connmand,下面将会对相对常用的一些命令分组进行介绍,当然也包括使用时应该注意的一些事项。

add_user

添加一个用户,需要指定用户名和密码;

delete_user 删除一个用户,只需指定用户名;

change_password 修改指定用户的密码;

clear_password 删除密码;

set_user_tags 设置用户角色,执行命令时会清空原有角色,角色可以设置多个或零个;

list_users列出所有已经存在的用户;

注:即消息的Ackownledge确认机制,为了保证消息不丢失,消息队列提供了消息Acknowledge机制,即ACK机制,当Consumer确认消息已经被消费处理,发送一个ACK给消息队列,此时消息队列便可以删除这个消息了。如果Consumer宕机/关闭,没有发送ACK,消息队列将认为这个消息没有被处理,会将这个消息重新发送给其他的Consumer重新消费处理。

rabbitmq的角色有以下几种:

none、mament、policymaker、monitoring、administrator

none

不能访问 mament plugin

mament

用户可以通过AMQP做的任何事外加:

列出自己可以通过AMQP登入的virtual hosts

查看自己的virtual hosts中的queues, exchanges 和 bindings

查看和关闭自己的channels 和 connections

查看有关自己的virtual hosts的“全局”的统计信息,包含其他用户在这些virtual hosts中的活动。

policymaker

查看、创建和删除自己的virtual hosts所属的policies和parameters

monitoring

列出所有virtual hosts,包括他们不能登录的virtual hosts

查看其他用户的connections和channels

查看级别的数据如clustering和memory使用情况

查看真正的关于所有virtual hosts的全局的统计信息

administrator

policymaker和monitoring可以做的任何事外加:

创建和删除virtual hosts

查看、创建和删除users

查看创建和删除permissions

关闭其他用户的connections

add_vhost 添加一个虚拟机如:rabbitmqctl add_vhost myvhost

注:虚拟机的个字符不要为 “ / “,在用方式建立连接时要是指定虚机要用 /vhostName的方式指 定,容易引起误解,如果虚机名为/myvhost 则使用时就会变成//myvhost。

delete_vhost 删除一个虚拟机

list_vhosts [ ...] 打印出虚拟机列表

set_permissions [-p ] 为user设置进入虚拟机的权限,如果不指定虚 拟主机则默认为/

注:在执行该命令时,在windows下 四个参数都不要加引号,如:

rabbitmqctl set_permissions -p myvhost userName . . . 不能写成

clear_permissions [-p ] 删除指定用户进入指定虚拟机的权限,默认虚拟主机为 /

list_permissions [-p ] 列出具有进入指定虚拟主机权限的用户列表,

list_user_permissions 列出指定用户所具有的进入虚拟主机权限的虚拟主机的列表 ,

列表格式为:vhostName conf write read

(3)、其他常用命令

list_queues [-p ] [ ...] 打印消息队列列表

list_exchanges [-p ] [ ...] 打印交换机列表

list_bindings [-p ] [ ...] 打印绑定器列表

list_channels [ ...]打印消费者列表

面试官:如何保证RocketMQ/RabbitMQ消息数据不丢失

-q 为安静输出模式;

在分布式系统的网络中,保证消息的可靠性?阿里技术分享了一篇文章:RocketMQ如何保证消息的可靠性?在文中详情介绍了RocketMQ是如何限度的保证消息不丢失的呢?分析的思路就是一条消息从产生到最终消费的整个过程,在三个关键的阶段去控制消息的可靠性。

一个Topic的多个partitions,被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写作;此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性。

下面分享证RabbitMQ如何保证消息的可靠性,对比去看,一定会有收获~

这3个步骤中的每一步都有可能导致消息丢失,消息丢失不可怕,可怕的是丢失了我们还不知道,所以要有一些措施来保证系统的可靠性。这里的可靠并不是一定就不丢失了,磁盘损坏,机房爆炸等等都能导致数据丢失,当然这种都是极小概率发生,能做到99.999999%消息不丢失,就是可靠的了。下面来具体分析一下问题以及解决方案。

生产端可靠性投递,即生产端要确保将消息正确投递到RabbitMQ中。生产端投递的消息丢失的原因有很多,比如消息在网络传输的过程中发生网络故障消息丢失,或者消息投递到RabbitMQ时RabbitMQ挂了,那消息也可能丢失,而我们根本不知道发生了什么。针对以上情况,RabbitMQ本身提供了一些机制。

事务消息机制由于会降低性能,所以一般不采用这种方法,我就不介绍了,而采用另一种轻量级的解决方案——confirm消息确认机制。

什么是confirm消息确认机制?顾名思义,就是生产端投递的消息一旦投递到RabbitMQ后,RabbitMQ就会发送一个确认消息给生产端,让生产端知道我已经收到消息了,否则这条消息就可能已经丢失了,需要生产端重新发送消息了。

通过下面这句代码来开启确认模式:

然后异步确认和未确认的消息:

这样就可以让生产端感知到消息是否投递到RabbitMQ中了,当然这样还不够,稍后我会说一下极端情况。

那消息持久化呢?我们知道,RabbitMQ收到消息后将这个消息暂时存在了内存中,那这就会有个问题,如果RabbitMQ挂了,那重启后数据就丢失了,所以相关的数据应该持久化到硬盘中,这样就算RabbitMQ重启后也可以到硬盘中取数据恢复。那如何持久化呢?

message消息到达RabbitMQ后先是到exchange交换机中,然后路由给queue队列,发送给消费端。

所有需要给exchange、queue和message都进行持久化:

exchange持久化:

queue持久化:

这样,如果RabbitMQ收到消息后挂了,重启后会自行恢复消息。

所以除了RabbitMQ提供的一些机制外,我们自己也要做一些消RabbitMQ 是实现 AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。 RabbitMQ 主要是为了实现系统之间的双向解耦而实现的。当生产者大量产生数据时,消费者无法快速消费,那么需要一个中间层。保存这个数据。息补偿机制,以应对一些极端情况。接下来我就介绍其中的一种解决方案——消息入库。

消息入库 消息入库,顾名思义就是将要发送的消息保存到数据库中。

首先发送消息前先将消息保存到数据库中,有一个状态字段status=0,表示生产端将消息发送给了RabbitMQ但还没收到确认;在生产端收到确认后将status设为1,表示RabbitMQ已收到消息。这里有可能会出现上面说的两种情况,所以生产端这边开一个定时器,定时检索消息表,将status=0并且超过固定时间后(可能消息刚发出去还没来得及确认这边定时器刚好检索到这条status=0的消息,所以给个时间)还没收到确认的消息取出重发(第二种情况下这里会造成消息重复,消费者端要做幂等性),可能重发还会失败,所以可以做一个重发次数,超过就做另外的处理。

这样消息就可以可靠性投递到RabbitMQ中了,而生产端也可以感知到了。

既然已经可以让生产端可靠性投递到RabbitMQ了,那接下来就改看看消费端的了,如何让消费端不丢失消息。

默认情况下,以下3种情况会导致消息丢失:

其实,上述3中情况导致消息丢失归根结底是因为RabbitMQ的自动ack机制,即默认RabbitMQ在消息发出后就立即将这条消息删除,而不管消费端是否接收到,是否处理完,导致消费端消息丢失时RabbitMQ自己又没有这条消息了。

所以就需要将自动ack机制改为手动ack机制。

消费端手动确认消息:

这样,当autoAck参数置为false,对于RabbitMQ服务端而言,队列中的消息分成了两个部分:一部分是等待投递给消费端的消息;一部分是已经投递给消费端,但是还没有收到消费端确认信号的消息。如果RabbitMQ一直没有收到消费端的确认信号,并且消费此消息的消费端已经断开连接或宕机(RabbitMQ会自己感知到),则RabbitMQ会安排该消息重新进入队列(放在队列头部),等待投递给下一个消费者,当然也有能还是原来的那个消费端,当然消费端也需要确保幂等性。

由于个人水平有限,有些地方可能理解错了或理解不到位的,请大家多多指出!Thanks

以上 RabbitMQ 原文链接 :htts://

分享一个梳理的消息中间件的思维导图,和面试题。

如需高清思维导图和面试题,关注私信获取。

rabbitmq在web页面中如何查看json数据

如果所有的consumer都具有相同的group,这种情况和queue模式很像;消息将会在consumers之间负载均衡。

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在,这样能大大平台解耦能力,将每一个功能都具体到模块化作

好了,到此从生产端到RabbitMQ再到消费端的全链路,就可以保证数据的不丢失。

大致如图

1.3、消息队列大致术PTP模式下,特定生产者向特定queue发送消息,消费者特定的queue完成指定消息的接收。语

Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。

Queue:消息的载体,每个消息都会被投到一个或多个队列。

Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来.

Routing Key:路由关键字,exchange根据这个关键字进行消息投递。

vhost:虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。

异常宕机,导致RabbitMQ启动失败

正在学RabbitMQ,特此记录一下,这里就不讲RabbitMQ基础了,直接进入主题。我们都知道,消息从生产端到消费端消费要经过3个步骤:

问题原因: 由于异常宕机导致RabbitMQ挂掉,恢复之后尝试启动MQ发现启动失败。报错信息如下

列表格式为:userName conf write read

查看状态:

报错如下:

解决:

系统日志如下:

删除/var/lib/rabbitmq/mnesia 目录下的rabbit@iZbp128yw4rvtfbytgv4y7Z.pid、rabbit@iZbp128yw4rvtfbytgv4y7Z、rabbit@iZbp128yw4rvtfbytgv4y7Z-plugins-expand后,再使用 ctl start rabbitmq-server 启动,成功启动MQ。

注Broker的概念来自与Apache ActiveMQ,通俗的讲就是MQ的。意 : 文件中包含交换机队列及用户等信息,删除等于重置MQ(队列会被清空),请谨慎作

消息队列原理及选型

exactly once: kafka中并没有严格的去实现(基于2阶段提交,事务),我们认为这种策略在kafka中是没有必要的。

消息队列(Message Queue)是一种进程间通信或同一进程的不同线程间的通信方式。

对于同步方式(producer.type=sync)?Kafka Producer 消息发送有三种确认方式(配置参数 acks):

Broker(消息)

Producer(生产者)

业务的发起方,负责生产消息传输给broker

Consumer(消费者)

业务的处理方,负责从broker获取消息并进行业务逻辑处理

Topic(主题)

发布模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ分发到不同的 者,实现消息的广播

Queue(队列)

Message(消息体)

根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输

点对点模型用于消息生产者和消息消费者之间点到点的通信。

每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,可以放在内存 中也可以持久化,直到他们被消费或超时。

特点:

发布模型包含三个角色:

多个发布者将消息发送到Topic,系统将这些消息传递给多个者。

特点:

AMQP即Aanced Message Queuing Protocol,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/)、可靠性、安全。

优点:可靠、通用

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。

优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统

STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互作的连接格式,允许客户端与任意STOMP消息(Broker)进行交互。

优点:命令模式(非topicqueue模式)

XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于之间的准即时作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其作系统和浏览器不同。

优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

RabbitMQ 是一个开源的 AMQP 实现,端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Ja、JMS、C、PHP、ActionScript、XMPP、STOMP 等,支持 AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

Channel(通道)

道是两个管理器之间的一种单向点对点的的通信连接,如果需要双向交流,可以建立一对通道。

Exchange(消息交换机)

Exchange类似于数据通信网络中的交换机,提供消息路由策略。

RabbitMq中,producer不是通过信道直接将消息发送给queue,而是先发送给Exchange。一个Exchange可以和多个Queue进行绑定,producer在传递消息的时候,会传递一个ROUTING_KEY,Exchange会根据这个ROUTING_KEY按照特定的路由算法,将消息路由给指定的queue。和Queue一样,Exchange也可设置为持久化,临时或者自动删除。

Exchange有4种类型:direct(默认),fanout, topic, 和headers。

不同类型的Exchange转发消息的策略有所区别:

Binding(绑定)

所谓绑定就是将一个特定的 Exchange 和一个特定的 Queue 绑定起来。Exchange 和Queue的绑定可以是多对多的关系。

Routing Key(路由关键字)

exchange根据这个关键字进行消息投递。

vhost(虚拟主机)

在RabbitMq server上可以创建多个虚拟的message broker,又叫做virtual hosts (vhosts)。每一个vhost本质上是一个mini-rabbitmq server,分别管理各自的exchange,和bindings。vhost相当于物理的server,可以为不同app提供边界隔离,使得应用安全的运行在不同的vhost实例上,相互之间不会干扰。producer和consumer连接rabbit server需要指定一个vhost。

设P1和C1注册了相同的Broker,Exchange和Queue。P1发送的消息最终会被C1消费。

基本的通信流程大概如下所示:

Consumer收到消息时需要显式的向rabbit broker发送basic。ack消息或者consumer消息时设置auto_ack参数为true。

在通信过程中,队列对ACK的处理有以下几种情况:

消息的收发处理支持事务,例如:在任务中心场景中,一次处理可能涉及多个消息的接收、处理,这应该处于同一个事务范围内,如果一个消息处理失败,事务回滚,消息重新回到队列中。

消息的持久化,对于一些关键的核心业务来说是非常重要的,启用消息持久化后,消息队列宕机重启后,消息可以从持久化存储恢复,消息不丢失,可以继续消费处理。

fanout 模式

模式特点:

direct 模式

任何发送到Direct Exchange的消息都会被转发到routing_key中指定的Queue。

如果一个exchange 声明为direct,并且bind中指定了routing_key,那么发送消息时需要同时指明该exchange和routing_key。

简而言之就是:生产者生成消息发送给Exchange, Exchange根据Exchange类型和basic_publish中的routing_key进行消息发送 消费者:Exchange并根据Exchange类型和binding key(bindings 中的routing key) ,如果生产者和者的routing_key相同,Exchange就会路由到那个队列。

topic 模式

前面讲到direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。

topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同。

它约定:

以上图中的配置为例,routingKey=”quick.orange.rabbit”的消息会同时路由到Q1与Q2,routingKey=”lazy.orange.fox”的消息会路由到Q1,routingKey=”lazy.brown.fox”的消息会路由到Q2,routingKey=”lazy.pink.rabbit”的消息会路由到Q2(只会投递给Q2一次,虽然这个routingKey与Q2的两个bindingKey都匹配);routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息将会被丢弃,因为它们没有匹配任何bindingKey。

RabbitMQ,部署分三种模式:单机模式,普通集群模式,镜像集群模式。

多台机器部署,每个机器放一个rabbitmq实例,但是创建的queue只会放在一个rabbitmq实例上,每个实例同步queue的元数据。

如果消费时连的是其他实例,那个实例会从queue所在实例拉取数据。这就会导致拉取数据的开销,如果那个放queue的实例宕机了,那么其他实例就无法从那个实例拉取,即便开启了消息持久化,让rabbitmq落地存储消息的话,消息不一定会丢,但得等这个实例恢复了,然后才可以继续从这个queue拉取数据, 这就没什么高可用可言,主要是提供吞吐量 ,让集群中多个来服务某个queue的读写作。

镜像集群模式

queue的元数据和消息都会存放在多个实例,每次写消息就自动同步到多个queue实例里。这样任何一个机器宕机,其他机器都可以顶上,但是性能开销太大,消息同步导致网络带宽压力和消耗很重,另外,没有扩展性可言,如果queue负载很重,加机器,新增的机器也包含了这个queue的所有数据,并没有办法线性扩展你的queue。此时,需要开启镜像集群模式,在rabbitmq管理控制台新增一个策略,将数据同步到指定数量的,然后你再次创建queue的时候,应用这个策略,就会自动将数据同步到其他的上去了。

Kafka 是 Apache 的子项目,是一个高性能跨语言的分布式发布/消息队列系统(没有严格实现 JMS 规范的点对点模型,但可以实现其效果),在企业开发中有广泛的应用。高性能是其优势,劣势是消息的可靠性(丢失或重复),这个劣势是为了换取高性能,开发者可以以稍降低性能,来换取消息的可靠性。

一个Topic可以认为是一类消息,每个topic将被分成多个partition(区),每个partition在存储层面是append log文件。任何发布到此partition的消息都会被直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它是标记一条消息。它的标记一条消息。kafka并没有提供其他额外的索引机制来存储offset,因为在kafka中几乎不允许对消息进行“随机读写”。

Kafka和JMS(Ja Message Serv)实现(activeMQ)不同的是:即使消息被消费,消息仍然不会被立即删除。日志文件将会根据broker中的配置要求,保留一定的时间之后删除;比如log文件保留2天,那么两天后,文件会被清除,无论其中的消息是否被消费。kafka通过这种简单的手段,来释放磁盘空间,以及减少消息消费之后对文件内容改动的磁盘IO开支。

对于consumer而言,它需要保存消费消息的offset,对于offset的保存和使用,有consumer来控制;当consumer正常消费消息时,offset将会"线性"的向前驱动,即消息将依次顺序被消费。事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值。(offset将会保存在zookeeper中,参见下文)

kafka集群几乎不需要维护任何consumer和producer状态信息,这些信息有zookeeper保存;因此producer和consumer的客户端实现非常轻量级,它们可以随意离开,而不会对集群造成额外的影响。

partitions的设计目的有多个。最根本原因是kafka基于文件存储。通过分区,可以将日志内容分散到多个server上,来避免文件尺寸达到单机磁盘的上限,每个partiton都会被当前server(kafka实例)保存;可以将一个topic切分多任意多个partitions,来消息保存/消费的效率。此外越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力。(具体原理参见下文)。

基于replicated方案,那么就意味着需要对多个备份进行调度;每个partition都有一个server为"leader";leader负责所有的读写作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可。由此可见作为leader的server承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定。

Producers

Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息归属于哪个partition;比如基于"round-robin"方式或者通过其他的一些算法等。

Consumers

本质上kafka只支持Topic。每个consumer属于一个consumer group;反过来说,每个group中可以有多个consumer。发送到Topic的消息,只会被此Topic的每个group中的一个consumer消费。

如果所有的consumer都具有不同的group,那这就是"发布-";消息将会广播给所有的消费者。

在kafka中,一个partition中的消息只会被group中的一个consumer消费;每个group中consumer消息消费互相;我们可以认为一个group是一个""者,一个Topic中的每个partions,只会被一个"者"中的一个consumer消费,不过一个consumer可以消费多个partitions中的消息。kafka只能保证一个partition中的消息被某个consumer消费时,消息是顺序的。事实上,从Topic角度来说,消息仍不是有序的。

Kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息。

Guarantees

Kafka就比较适合高吞吐量并且允许少量数据丢失的场景,如果非要保证“消息可靠传输”,可以使用JMS。

Kafka Producer 消息发送有两种方式(配置参数 producer.type):

kafka的设计初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息,并需要能够支撑较大的数据量,且具备良好的容错能力。

持久性

kafka使用文件存储消息,这就直接决定kafka在性能上依赖文件系统的本身特性。且无论任何OS下,对文件系统本身的优化几乎没有可能。文件缓存/直接内存映射等是常用的手段。因为kafka是对日志文件进行append作,因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO调用的次数。

性能

需要考虑的影响性能点很多,除磁盘IO之外,我们还需要考虑网络IO,这直接关系到kafka的吞吐量问题。kafka并没有提供太多高超的技巧;对于producer端,可以将消息buffer起来,当消息的条数达到一定阀值时,批量发送给broker;对于consumer端也是一样,批量fetch多条消息。不过消息量的大小可以通过配置文件来指定。对于kafka broker端,似乎有个sendfile系统调用可以潜在的提升网络IO的性能:将文件的数据映射到系统内存中,socket直接读取相应的内存区域即可,而无需进程再次copy和交换。 其实对于producer/consumer/broker三者而言,CPU的开支应该都不大,因此启用消息压缩机制是一个良好的策略;压缩需要消耗少量的CPU资源,不过对于kafka而言,网络IO更应该需要考虑。可以将任何在网络上传输的消息都经过压缩。kafka支持gzip/snappy等多种压缩方式。

生产者

负载均衡: producer将会和Topic下所有partition leader保持socket连接;消息由producer直接通过socket发送到broker,中间不会经过任何“路由层“。事实上,消息被路由到哪个partition上,有producer客户端决定。比如可以采用“random““key-hash““轮询“等,如果一个topic中有多个partitions,那么在producer端实现“消息均衡分发“是必要的。

其中partition leader的位置(host:port)注册在zookeeper中,producer作为zookeeper client,已经注册了watch用来partition leader的变更。

异步发送:将多条消息暂且在客户端buffer起来,并将他们批量的发送到broker,小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率。不过这也有一定的隐患,比如说当producer失效时,那些尚未发送的消息将会丢失。

消费者

consumer端向broker发送“fetch”请求,并告知其获取消息的offset;此后consumer将会获得一定条数的消息;consumer端也可以重置offset来重新消费消息。

在JMS实现中,Topic模型基于push方式,即broker将消息推送给consumer端。不过在kafka中,采用了pull方式,即consumer在和broker建立连接之后,主动去pull(或者说fetch)消息;这中模式有些优点,首先consumer端可以根据自己的消费能力适时的去fetch消息并处理,且可以控制消息消费的进度(offset);此外,消费者可以良好的控制消息消费的数量,batch fetch。

其他JMS实现,消息消费的位置是有prodiver保留,以便避免重复发送消息或者将没有消费成功的消息重发等,同时还要控制消息的状态。这就要求JMS broker需要太多额外的工作。在kafka中,partition中的消息只有一个consumer在消费,且不存在消息状态的控制,也没有复杂的消息确认机制,可见kafka broker端是相当轻量级的。当消息被consumer接收之后,consumer可以在本地保存消息的offset,并间歇性的向zookeeper注册offset。由此可见,consumer客户端也很轻量级。

对于JMS实现,消息传输担保非常直接:有且只有一次(exactly once)。

在kafka中稍有不同:

at most once: 消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理。那么此后"未处理"的消息将不能被fetch到,这就是"at most once"。

at least once: 消费者fetch消息,然后处理消息,然后保存offset。如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是"at least once",原因offset没有及时的提交给zookeeper,zookeeper恢复正常还是之前offset状态。

通常情况下“at-least-once”是我们。(相比at most once而言,重复接收数据总比丢失数据要好)。

kafka高可用由多个broker组成,每个broker是一个;

kafka是一个分布式消息队列,就是说一个topic的数据,是分散放在不同的机器上,每个机器就放一部分数据。

在0.8版本以前,是没有HA机制的,就是任何一个broker宕机了,那个broker上的partition就废了,没法写也没法读,没有什么高可用性可言。

0.8版本以后,才提供了HA机制,也就是就是replica副本机制。每个partition的数据都会同步到其他的机器上,形成自己的多个replica副本。然后所有replica会选举一个leader出来,那么生产和消费都跟这个leader打交道,然后其他replica就是follower。

写的时候,leader会负责把数据同各个字段的含义将在下篇文章中介绍步到所有follower上去,读的时候就直接读leader上数据即可。

kafka会均匀的将一个partition的所有replica分布在不同的机器上,从而提高容错性。

如果某个broker宕机了也没事,它上面的partition在其他机器上都有副本的,如果这上面有某个partition的leader,那么此时会重新选举一个新的leader出来,大家继续读写那个新的leader即可。这就有所谓的高可用性了。

写数据的时候,生产者就写leader,然后leader将数据落地写本地磁盘,接着其他follower自己主动从leader来pull数据。一旦所有follower同步好数据了,就会发送ack给leader,leader收到所有follower的ack之后,就会返回写成功的消息给生产者。

RabbitMQ

Kafka

大体和RabbitMQ相同。

Rabbitmq

需要保证顺序的消息投递到同一个queue中,这个queue只能有一个consumer,如果需要提升性能,可以用内存队列做排队,然后分发给底层不同的worker来处理。

Kafka

写入一个partition中的数据一定是有序的。生产者在写的时候 ,可以指定一个key,比如指定订单id作为key,这个订单相关数据一定会被分发到一个partition中去。消费者从partition中取出数据的时候也一定是有序的,把每个数据放入对应的一个内存队列,一个partition中有几条相关数据就用几个内存队列,消费者开启多个线程,每个线程处理一个内存队列。

如何查看RabbitMQ日志

点对点模式包含三个角色:(1)、关于user的一些命令( 2)、虚拟机和权限