分布式消息队列差异化总结,太全了!

死信队列+重试机制:消息队列可靠性面试全解析 消息队列是分布式系统异步解耦的核心组件,但消息从生产到消费的链路中,任何一个环节的失败都可能导致数据不一致。为了保证消息不丢、最终被处理,消费端可靠性设计成为关键:重试机制让系统在瞬时故障中自愈,而死信队列则作为兜底方案,为反复失败的消息提供隔离、排查与人工补偿的窗口。不同消息中间件实现差异显著:RabbitMQ通过TTL与死信交换机组合构建延迟重试,RocketMQ内置重试队列与DLQ,Kafka则需要自建死信约定。理解这三者的差异,并在业务中合理配置重试次数、异常分类和幂等控制,是构建高可靠消息链路的核 阅读详情

本文将对Kafka、RabbitMQ、ZeroMQ、RocketMQ、ActiveMQ从17 个方面综合对比作为消息队列使用时的差异。

一、资料文档

  • Kafka:资料数量中等。有Kafka作者自己写的书,网上资料也有一些。
  • RabbitMQ:资料数量多。有一些不错的书,网上资料多。
  • ZeroMQ:资料数量少。专门写ZeroMQ的书较少,网上的资料多是一些代码的实现和简单介绍。
  • RocketMQ:资料数量少。专门写RocketMQ的书目前有了两本;网上的资料良莠不齐,官方文档很简洁,但是对技术细节没有过多的描述。
  • ActiveMQ:资料数量多。没有专门写ActiveMQ的书,网上资料多。

二、开发语言

  • Kafka:Scala
  • RabbitMQ:Erlang
  • ZeroMQ:C
  • RocketMQ:Java
  • ActiveMQ:Java

三、支持的协议

  • Kafka:自己定义的一套…(基于TCP)
  • RabbitMQ:AMQP
  • ZeroMQ:TCP、UDP
  • RocketMQ:自己定义的一套…
  • ActiveMQ:OpenWire、STOMP、REST、XMPP、AMQP

四、消息存储

1、Kafka

内存、磁盘、数据库。支持大量堆积。

Kafka的最小存储单元是分区,一个topic包含多个分区,Kafka创建主题时,这些分区会被分配在多个服务器上,通常一个broker一台服务器。

分区首领会均匀地分布在不同的服务器上,分区副本也会均匀的分布在不同的服务器上,确保负载均衡和高可用性,当新的broker加入集群的时候,部分副本会被移动到新的broker上。

根据配置文件中的目录清单,Kafka会把新的分区分配给目录清单里分区数最少的目录。

默认情况下,分区器使用轮询算法把消息均衡地分布在同一个主题的不同分区中,对于发送时指定了key的情况,会根据key的hashcode取模后的值存到对应的分区中。

2、RabbitMQ

内存、磁盘。支持少量堆积。

RabbitMQ的消息分为持久化的消息和非持久化消息,不管是持久化的消息还是非持久化的消息都可以写入到磁盘。

持久化的消息在到达队列时就写入到磁盘,并且如果可以,持久化的消息也会在内存中保存一份备份,这样可以提高一定的性能,当内存吃紧的时候会从内存中清除。

非持久化的消息一般只存在于内存中,在内存吃紧的时候会被换入到磁盘中,以节省内存。

引入镜像队列机制,可将重要队列“复制”到集群中的其他broker上,保证这些队列的消息不会丢失。

配置镜像的队列,都包含一个主节点master和多个从节点slave,如果master失效,加入时间最长的slave会被提升为新的master,除发送消息外的所有动作都向master发送,然后由master将命令执行结果广播给各个slave,RabbitMQ会让master均匀地分布在不同的服务器上,而同一个队列的slave也会均匀地分布在不同的服务器上,保证负载均衡和高可用性。

3、ZeroMQ

消息发送端的内存或者磁盘中。不支持持久化。

4、RocketMQ

磁盘。支持大量堆积。

commitLog文件存放实际的消息数据,每个commitLog上限是1G,满了之后会自动新建一个commitLog文件保存数据。

ConsumeQueue队列只存放offset、size、tagcode,非常小,分布在多个broker上。

ConsumeQueue相当于CommitLog的索引文件,消费者消费时会从consumeQueue中查找消息在commitLog中的offset,再去commitLog中查找元数据。

ConsumeQueue存储格式的特性,保证了写过程的顺序写盘(写CommitLog文件),大量数据IO都在顺序写同一个commitLog,满1G了再写新的。

加上RocketMQ是累计4K才强制从PageCache中刷到磁盘(缓存),所以高并发写性能突出。

5、ActiveMQ

内存、磁盘、数据库。支持少量堆积。

五、消息事务

  • Kafka:支持
  • RabbitMQ:支持。
    客户端将信道设置为事务模式,只有当消息被RabbitMQ接收,事务才能提交成功,否则在捕获异常后进行回滚。使用事务会使得性能有所下降
  • ZeroMQ:不支持
  • RocketMQ:支持
  • ActiveMQ:支持

六、负载均衡

1、Kafka

支持负载均衡。

1)一个broker通常就是一台服务器节点。

对于同一个Topic的不同分区,Kafka会尽力将这些分区分布到不同的Broker服务器上,zookeeper保存了broker、主题和分区的元数据信息。

分区首领会处理来自客户端的生产请求,Kafka分区首领会被分配到不同的broker服务器上,让不同的broker服务器共同分担任务。

每一个broker都缓存了元数据信息,客户端可以从任意一个broker获取元数据信息并缓存起来,根据元数据信息知道要往哪里发送请求。

2)Kafka的消费者组订阅同一个topic,会尽可能地使得每一个消费者分配到相同数量的分区,分摊负载。

3)当消费者加入或者退出消费者组的时候,还会触发再均衡,为每一个消费者重新分配分区,分摊负载。

Kafka的负载均衡大部分是自动完成的,分区的创建也是Kafka完成的,隐藏了很多细节,避免了繁琐的配置和人为疏忽造成的负载问题。

4)发送端由topic和key来决定消息发往哪个分区,如果key为null,那么会使用轮询算法将消息均衡地发送到同一个topic的不同分区中。如果key不为null,那么会根据key的hashcode取模计算出要发往的分区。

2、RabbitMQ

对负载均衡的支持不好。

1)消息被投递到哪个队列是由交换器和key决定的,交换器、路由键、队列都需要手动创建。

RabbitMQ客户端发送消息要和broker建立连接,需要事先知道broker上有哪些交换器,有哪些队列。

通常要声明要发送的目标队列,如果没有目标队列,会在broker上创建一个队列,如果有,就什么都不处理,接着往这个队列发送消息。假设大部分繁重任务的队列都创建在同一个broker上,那么这个broker的负载就会过大。

可以在上线前预先创建队列,无需声明要发送的队列,但是发送时不会尝试创建队列,可能出现找不到队列的问题,RabbitMQ的备份交换器会把找不到队列的消息保存到一个专门的队列中,以便以后查询使用。

使用镜像队列机制建立RabbitMQ集群可以解决这个问题,形成master-slave的架构,master节点会均匀分布在不同的服务器上,让每一台服务器分摊负载。slave节点只是负责转发,在master失效时会选择加入时间最长的slave成为master。

当新节点加入镜像队列的时候,队列中的消息不会同步到新的slave中,除非调用同步命令,但是调用命令后,队列会阻塞,不能在生产环境中调用同步命令。

2)当RabbitMQ队列拥有多个消费者的时候,队列收到的消息将以轮询的分发方式发送给消费者。每条消息只会发送给订阅列表里的一个消费者,不会重复。

这种方式非常适合扩展,而且是专门为并发程序设计的。

如果某些消费者的任务比较繁重,那么可以设置basicQos限制信道上消费者能保持的最大未确认消息的数量,在达到上限时,RabbitMQ不再向这个消费者发送任何消息。

3)对于RabbitMQ而言,客户端与集群建立的TCP连接不是与集群中所有的节点建立连接,而是挑选其中一个节点建立连接。

但是RabbitMQ集群可以借助HAProxy、LVS技术,或者在客户端使用算法实现负载均衡,引入负载均衡之后,各个客户端的连接可以分摊到集群的各个节点之中。

客户端均衡算法:

  • 轮询法:按顺序返回下一个服务器的连接地址。
  • 加权轮询法:给配置高、负载低的机器配置更高的权重,让其处理更多的请求;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载。
  • 随机法:随机选取一个服务器的连接地址。
  • 加权随机法:按照概率随机选取连接地址。
  • 源地址哈希法:通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算。
  • 最小连接数法:动态选择当前连接数最少的一台服务器的连接地址。

3、ZeroMQ

去中心化,不支持负载均衡。本身只是一个多线程网络库。

4、RocketMQ

支持负载均衡。

一个broker通常是一个服务器节点,broker分为master和slave,master和slave存储的数据一样,slave从master同步数据。

1)nameserver与每个集群成员保持心跳,保存着Topic-Broker路由信息,同一个topic的队列会分布在不同的服务器上。

2)发送消息通过轮询队列的方式发送,每个队列接收平均的消息量。发送消息指定topic、tags、keys,无法指定投递到哪个队列(没有意义,集群消费和广播消费跟消息存放在哪个队列没有关系)。

tags选填,类似于 Gmail 为每封邮件设置的标签,方便服务器过滤使用。目前只支 持每个消息设置一个 tag,所以也可以类比为 Notify 的 MessageType 概念。
keys选填,代表这条消息的业务关键词,服务器会根据 keys 创建哈希索引,设置后, 可以在 Console 系统根据 Topic、Keys 来查询消息,由于是哈希索引,请尽可能 保证 key 唯一,例如订单号,商品 Id 等。

3)RocketMQ的负载均衡策略规定:

Consumer数量应该小于等于Queue数量,如果Consumer超过Queue数量,那么多余的Consumer 将不能消费消息。

这一点和Kafka是一致的,RocketMQ会尽可能地为每一个Consumer分配相同数量的队列,分摊负载。

5、ActiveMQ

支持负载均衡。可以基于zookeeper实现负载均衡。

七、集群方式

1、Kafka

天然的‘Leader-Slave’无状态集群,每台服务器既是Master也是Slave。

分区首领均匀地分布在不同的Kafka服务器上,分区副本也均匀地分布在不同的Kafka服务器上,所以每一台Kafka服务器既含有分区首领,同时又含有分区副本。

每一台Kafka服务器是某一台Kafka服务器的Slave,同时也是某一台Kafka服务器的leader。

Kafka的集群依赖于zookeeper,zookeeper支持热扩展,所有的broker、消费者、分区都可以动态加入移除,而无需关闭服务,与不依靠zookeeper集群的mq相比,这是最大的优势。

2、RabbitMQ

支持简单集群,'复制’模式,对高级集群模式支持不好。

RabbitMQ的每一个节点,不管是单一节点系统或者是集群中的一部分,要么是内存节点,要么是磁盘节点,集群中至少要有一个是磁盘节点。

在RabbitMQ集群中创建队列,集群只会在单个节点创建队列进程和完整的队列信息(元数据、状态、内容),而不是在所有节点上创建。

引入镜像队列,可以避免单点故障,确保服务的可用性,但是需要人为地为某些重要的队列配置镜像。

3、ZeroMQ

去中心化,不支持集群。

4、RocketMQ

常用 多对’Master-Slave’ 模式,开源版本需手动切换Slave变成Master。

Name Server是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。

Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master。

Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。

Master也可以部署多个。每个Broker与Name Server集群中的所有节点建立长连接,定时注册Topic信息到所有Name Server。

Producer与Name Server集群中的其中一个节点(随机选择)建立长连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。

Consumer与Name Server集群中的其中一个节点(随机选择)建立长连接,定期从Name Server取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。

Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。

客户端先找到NameServer, 然后通过NameServer再找到 Broker。

一个topic有多个队列,这些队列会均匀地分布在不同的broker服务器上。RocketMQ队列的概念和Kafka的分区概念是基本一致的,Kafka同一个topic的分区尽可能地分布在不同的broker上,分区副本也会分布在不同的broker上。

RocketMQ集群的slave会从master拉取数据备份,master分布在不同的broker上。

5、ActiveMQ

支持简单集群模式,比如’主-备’,对高级集群模式支持不好。

八、管理界面

  • Kafka:一般
  • RabbitMQ:好
  • ZeroMQ:无
  • RocketMQ:有管理后台, 但不是项目里自带, 需要自己启动一个单独的管理后台实例
  • ActiveMQ:一般

九、可用性

  • Kafka:非常高(分布式)
  • RabbitMQ:高(主从)
  • ZeroMQ:高
  • RocketMQ:非常高(分布式)
  • ActiveMQ:高(主从)

十、消息重复

  • Kafka:支持at least once、at most once
  • RabbitMQ:支持at least once、at most once
  • ZeroMQ:只有重传机制,但是没有持久化,消息丢了重传也没有用。既不是at least once、也不是at most once、更不是exactly only once
  • RocketMQ:支持at least once
  • ActiveMQ:支持at least once

十一、吞吐量TPS

  • Kafka:极大
    Kafka按批次发送消息和消费消息。发送端将多个小消息合并,批量发向Broker,消费端每次取出一个批次的消息批量处理。
  • RabbitMQ:比较大
  • ZeroMQ:极大
  • RocketMQ:大
    RocketMQ接收端可以批量消费消息,可以配置每次消费的消息数,但是发送端不是批量发送。
  • ActiveMQ:比较大

十二、订阅形式和消息分发

1、Kafka

基于topic以及按照topic进行正则匹配的发布订阅模式。

1)发送

发送端由topic和key来决定消息发往哪个分区,如果key为null,那么会使用轮询算法将消息均衡地发送到同一个topic的不同分区中。如果key不为null,那么会根据key的hashcode取模计算出要发往的分区。

2)接收

  • consumer向群组协调器broker发送心跳来维持他们和群组的从属关系以及他们对分区的所有权关系,所有权关系一旦被分配就不会改变除非发生再均衡(比如有一个consumer加入或者离开consumer group),consumer只会从对应的分区读取消息。
  • Kafka限制consumer个数要少于分区个数,每个消息只会被同一个 Consumer Group的一个consumer消费(非广播)。
  • Kafka的 Consumer Group订阅同一个topic,会尽可能地使得每一个consumer分配到相同数量的分区,不同 Consumer Group订阅同一个主题相互独立,同一个消息会被不同的 Consumer Group处理。

2、RabbitMQ

提供了4种:direct、topic、Headers和fanout。

1)发送

先要声明一个队列,这个队列会被创建或者已经被创建,队列是基本存储单元。

  • 由exchange和key决定消息存储在哪个队列。
  • direct>发送到和bindingKey完全匹配的队列。
  • topic>路由key是含有"."的字符串,会发送到含有“*”、“#”进行模糊匹配的bingKey对应的队列。
  • fanout>与key无关,会发送到所有和exchange绑定的队列
  • headers>与key无关,消息内容的headers属性(一个键值对)和绑定键值对完全匹配时,会发送到此队列。此方式性能低一般不用

2)接收

RabbitMQ的队列是基本存储单元,不再被分区或者分片,对于我们已经创建了的队列,消费端要指定从哪一个队列接收消息。

当RabbitMQ队列拥有多个消费者的时候,队列收到的消息将以轮询的分发方式发送给消费者。每条消息只会发送给订阅列表里的一个消费者,不会重复。

这种方式非常适合扩展,而且是专门为并发程序设计的。

如果某些消费者的任务比较繁重,那么可以设置basicQos限制信道上消费者能保持的最大未确认消息的数量,在达到上限时,RabbitMQ不再向这个消费者发送任何消息。

3、ZeroMQ

点对点(p2p)。

4、RocketMQ

基于topic/messageTag以及按照消息类型、属性进行正则匹配的发布订阅模式。

1)发送

发送消息通过轮询队列的方式发送,每个队列接收平均的消息量。发送消息指定topic、tags、keys,无法指定投递到哪个队列(没有意义,集群消费和广播消费跟消息存放在哪个队列没有关系)。

  • tags选填,类似于 Gmail 为每封邮件设置的标签,方便服务器过滤使用。目前只支 持每个消息设置一个 tag,所以也可以类比为 Notify 的 MessageType 概念。
  • keys选填,代表这条消息的业务关键词,服务器会根据 keys 创建哈希索引,设置后, 可以在 Console 系统根据 Topic、Keys 来查询消息,由于是哈希索引,请尽可能 保证 key 唯一,例如订单号,商品 Id 等。

2)接收

  • 广播消费。一条消息被多个Consumer消费,即使Consumer属于同一个ConsumerGroup,消息也会被ConsumerGroup中的每个Consumer都消费一次。
  • 集群消费。一个 Consumer Group中的Consumer实例平均分摊消费消息。例如某个Topic有 9 条消息,其中一个Consumer Group有3个实例,那么每个实例只消费其中的 3 条消息。即每一个队列都把消息轮流分发给每个consumer。

5、ActiveMQ

点对点(p2p)、广播(发布-订阅)

  • 点对点模式,每个消息只有1个消费者;
  • 发布/订阅模式,每个消息可以有多个消费者。

1)发送

  • 点对点模式:先要指定一个队列,这个队列会被创建或者已经被创建。
  • 发布/订阅模式:先要指定一个topic,这个topic会被创建或者已经被创建。

2)接收

  • 点对点模式:对于已经创建了的队列,消费端要指定从哪一个队列接收消息。
  • 发布/订阅模式:对于已经创建了的topic,消费端要指定订阅哪一个topic的消息。

十三、顺序消息

  • Kafka:支持。
    设置生产者的max.in.flight.requests.per.connection为1,可以保证消息是按照发送顺序写入服务器的,即使发生了重试。
    Kafka保证同一个分区里的消息是有序的,但是这种有序分两种情况:
    ①key为null,消息逐个被写入不同主机的分区中,但是对于每个分区依然是有序的
    ②key不为null , 消息被写入到同一个分区,这个分区的消息都是有序。
  • RabbitMQ:不支持
  • ZeroMQ:不支持
  • RocketMQ:支持
  • ActiveMQ:不支持

十四、消息确认

1、Kafka

支持。

1)发送方确认机制

  • ack=0,不管消息是否成功写入分区
  • ack=1,消息成功写入首领分区后,返回成功
  • ack=all,消息成功写入所有分区后,返回成功。

2)接收方确认机制

自动或者手动提交分区偏移量,早期版本的Kafka偏移量是提交给Zookeeper的,这样使得zookeeper的压力比较大,更新版本的Kafka的偏移量是提交给Kafka服务器的,不再依赖于zookeeper群组,集群的性能更加稳定。

2、RabbitMQ

支持。

1)发送方确认机制,消息被投递到所有匹配的队列后,返回成功。如果消息和队列是可持久化的,那么在写入磁盘后,返回成功。支持批量确认和异步确认。

2)接收方确认机制,设置autoAck为false,需要显式确认,设置autoAck为true,自动确认。

当autoAck为false的时候,RabbitMQ队列会分成两部分,一部分是等待投递给consumer的消息,一部分是已经投递但是没收到确认的消息。

如果一直没有收到确认信号,并且consumer已经断开连接,RabbitMQ会安排这个消息重新进入队列,投递给原来的消费者或者下一个消费者。

未确认的消息不会有过期时间,如果一直没有确认,并且没有断开连接,RabbitMQ会一直等待,RabbitMQ允许一条消息处理的时间可以很久很久。

3、ZeroMQ

支持。

4、RocketMQ

支持。

5、ActiveMQ

支持。

十五、消息回溯

  • Kafka:支持指定分区offset位置的回溯
  • RabbitMQ:不支持
  • ZeroMQ:不支持
  • RocketMQ:支持指定时间点的回溯
  • ActiveMQ:不支持

十六、消息重试

1、Kafka

不支持,但是可以实现。

Kafka支持指定分区offset位置的回溯,可以实现消息重试。

2、RabbitMQ

不支持,但是可以利用消息确认机制实现。

RabbitMQ接收方确认机制,设置autoAck为false。

当autoAck为false的时候,RabbitMQ队列会分成两部分,一部分是等待投递给consumer的消息,一部分是已经投递但是没收到确认的消息。

如果一直没有收到确认信号,并且consumer已经断开连接,RabbitMQ会安排这个消息重新进入队列,投递给原来的消费者或者下一个消费者。

3、ZeroMQ

不支持。

4、RocketMQ

支持。

消息消费失败的大部分场景下,立即重试99%都会失败,所以RocketMQ的策略是在消费失败时定时重试,每次时间间隔相同。

1)发送端的 send 方法本身支持内部重试,重试逻辑如下:

  • 至多重试3次;
  • 如果发送失败,则轮转到下一个broker;
  • 这个方法的总耗时不超过sendMsgTimeout 设置的值,默认 10s,超过时间不在重试。

2)接收端。

Consumer 消费消息失败后,要提供一种重试机制,令消息再消费一次。Consumer 消费消息失败通常可以分为以下两种情况:

由于消息本身的原因,例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。定时重试机制,比如过 10s 秒后再重试。
由于依赖的下游应用服务不可用,例如 db 连接不可用,外系统网络不可达等。即使跳过当前失败的消息,消费其他消息同样也会报错。这种情况可以 sleep 30s,再消费下一条消息,减轻 Broker 重试消息的压力。

5、ActiveMQ

不支持。

十七、并发度

1、Kafka

并发度高。

一个线程一个消费者,Kafka限制消费者的个数要小于等于分区数,如果要提高并行度,可以在消费者中再开启多线程,或者增加consumer实例数量。

2、RabbitMQ

并发度极高。本身是用Erlang语言写的,并发性能高。

可在消费者中开启多线程,最常用的做法是一个channel对应一个消费者,每一个线程把持一个channel,多个线程复用connection的tcp连接,减少性能开销。

当RabbitMQ队列拥有多个消费者的时候,队列收到的消息将以轮询的分发方式发送给消费者。每条消息只会发送给订阅列表里的一个消费者,不会重复。

这种方式非常适合扩展,而且是专门为并发程序设计的。

如果某些消费者的任务比较繁重,那么可以设置basicQos限制信道上消费者能保持的最大未确认消息的数量,在达到上限时,RabbitMQ不再向这个消费者发送任何消息。

3、ZeroMQ

并发度高。

4、RocketMQ

并发度高。

1)RocketMQ限制消费者的个数少于等于队列数,但是可以在消费者中再开启多线程,这一点和Kafka是一致的,提高并行度的方法相同。

修改消费并行度方法

  • 同一个 ConsumerGroup 下,通过增加 Consumer 实例数量来提高并行度,超过订阅队列数的 Consumer实例无效。
  • 提高单个 Consumer 的消费并行线程,通过修改参数consumeThreadMin、consumeThreadMax

2)同一个网络连接connection,客户端多个线程可以同时发送请求,连接会被复用,减少性能开销。

5、ActiveMQ

并发度高。

单个ActiveMQ的接收和消费消息的速度在1万笔/秒(持久化 一般为1-2万, 非持久化 2 万以上),在生产环境中部署10个ActiveMQ就能达到10万笔/秒以上的性能,部署越多的ActiveMQ broker 在MQ上latency也就越低,系统吞吐量也就越高。

Java_supermanNO1:专注于Java开发技术的研究与知识分享!

————END————

  • 点赞(编辑不易,感谢您的支持)

  • …

  • 转发(分享知识,传播快乐)

  • …

  • 关注(每天更新Java开发技术)

  • …

信创中间件全栈化:从基础支撑到云原生演进 本文深入探讨了信创中间件从基础支撑到云原生演进的全栈化发展路径。文章分析了在信创战略驱动下,国产中间件如何从传统“幕后英雄”转变为构建自主可控数字基座的“全栈基石”,并详细阐述了其在应对微服务、分布式架构挑战,以及实现容器化、服务网格等云原生转型过程中的关键技术内涵与实战经验。 阅读详情

相关推荐

日爬千万级数据封禁率低于1%!分布式协同爬虫:住宅代理+AI行为模拟规模化绕过全实战

住宅代理不是越多越好,而是越精越好:一开始买了2000个IP,乱轮询,结果钱花了,数据没爬多少;后来只用200个高健康度的IP,精细化管理,效果反而提升了10倍。会话隔离是底线,绝对不能突破:同一个会话内,IP、指纹、节点、Cookie池必须完全绑定,中途绝对不能换,一旦突破这个底线,被关联封禁只是时间问题。行为的差异化比伪装更重要:哪怕你单节点的伪装做的再好,所有节点行为都一样,反爬还是能一眼认出你是爬虫集群,差异化才是规模化绕过的核心。全局限流永远不能少。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1344

常用6种消息队列介绍和对比

消息队列是分布式应用间交换信息的重要组件,消息队列可驻留在内存或磁盘上, 队列可以存储消息直到它们被应用程序读走。 通过消息队列,应用程序可以在不知道彼此位置的情况下独立处理消息,或者在处理消息前不需要等待接收此消息。 所以消息队列可以解决应用解耦、异步消息、流量削锋等问题,是实现高性能、高可用、可伸缩和最终一致性架构中不可以或缺的一环。 现在比较常见的消息队列产品主要有ActiveMQ、R...

徐泗空的博客 2万+

把群晖NAS变成游戏开发服务器:Perforce与虚幻引擎深度整合的5个关键配置(含.p4ignore模板)

本文详细介绍了如何将群晖NAS配置为游戏开发服务器,重点讲解了Perforce与虚幻引擎的深度整合。通过五个关键配置节点,包括用户权限架构、Workspace策略、资产同步优化、仓库清洁度保障和编辑器深度集成,帮助小型团队打造高效开发环境。文章还提供了实用的.p4ignore模板和优化技巧,显著提升开发效率。

weixin_30430677的博客 319

分布式消息队列差异化总结

转载自:https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650778230&idx=1&sn=db305061375bf4fe39f75c4fb9c4fee6&chksm=f3f91fe3c48e96f536a3e7ad100b09730780be6258eaf0d7ff6c407cdd64b874943...

johnhuster的专栏 703

绝对旋转编码器学习笔记(基本原理,与PC通信等,不定期更新中)

前言 最近开始学习编码器相关内容,目的在于搞清楚编码器的原理,与上位机的联系等问题。笔记资料来源为网络,整理的同时也会有一些总结和感悟。由于研究方向需求,主要研究数字旋转编码器。 1.编码器的定义 编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。——摘自《百度百科》 通常来说,编码器可以将角度位移、直线位移、转速等物理量转换为电信号。这里的电信号根据不同原理的编码器输出脉冲、二进制数码等不同的类型,下面会提到。 2.编码器的分类 编.

黑化咸鱼的博客 1万+

wpf入门第五篇 WPF with ECharts

前言 本文是wpf入门系列第五篇,面向有winform或者web前端基础的、并且也有C#基础的同学。 ECharts是百度团队开发的开源免费的js图表控件库,非常强大,文档齐全。WPF中使用图表,除了可以选择devexpress或者oxyplot之类的专为wpf开发的图表控件之外,还可以考虑使用 WebBrowser+ECharts 来完成复杂的图表展示,其展示效果不亚于前者。 本文介绍了 WP...

wf824284257的博客 1万+

高并发架构系列:分布式之消息中间件的特点、选型、及应用场景详解

目录 什么是消息队列 为什么需要消息队列 消息队列的优点 消息队列的特点 消息队列的选型 消息队列的应用场景 消息队列使用总结 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。 当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴...

凡是过往,皆为序章 1206

加密算法:深度解析Ed25519原理

在 Solana 开发过程中,我一直对 Ed25519 加密算法 如何生成公钥、签名以及验证签名的机制感到困惑。为了弄清这一点,我查阅了大量相关资料,终于对其流程有了更清晰的理解。在此记录实现过程,方便日后查阅。

盹猫的博客 1万+

消息中间件(RocketMQ、RabbitMQ、ActiveMQ、Redis、kafka、ZeroMQ)以及之间的区别

面向消息的系统(消息中间件)是在分布式系统中完成消息的发送和接收的基础软件。消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能;成为异步RPC的主要手段之一。......

m0_52165864的博客 1万+

40、5G NR射频要求解析

本文详细解析了5G NR射频相关要求,包括参考灵敏度与动态范围的定义、接收机对干扰信号的抗扰性要求(如阻塞、邻道选择性等)、辐射射频要求在FR1和FR2频段的差异,以及多标准无线电基站(MSR)的发展及其对射频要求的影响。内容涵盖测试模型、干扰场景、具体指标和实现挑战,为理解和应用5G NR射频规范提供了全面指导。

qsc901234的博客 246

Android一个APP里面最少有几个线程

Android应用启动时,默认会创建一个进程,该进程中最少包含负责处理用户交互、UI更新等核心操作,所有与界面相关的逻辑必须在此线程执行。若在此线程执行耗时操作(如网络请求),会导致界面卡顿甚至触发ANR(应用无响应)。当对象重写了finalize()方法时,该线程负责将这些对象放入队列并调用其finalize()方法,完成资源释放后再由GC回收。监控的执行效率。如果finalize()方法执行超时(默认10秒),此线程会触发虚拟机退出以防止应用长时间阻塞。

编程进化论 614

任务队列的Java实现

当前项目中遇到这样一个需求: 将需要审核的文本提交给人工智能模型接口审核,等待模型接口审核完毕以后拿到审核结果返回给前端展示给用户(另:模型处理数据所消耗的时间会随着用户提交数据的复杂度有所变化)。,如果有多个用户在同一时间提交了文本审核需求,且恰好此时此刻模型需要较长时间处理,这样的话,按照通常的代码写法,是无法满足任务需求的,那么应该如何满足这个需求呢?此时此刻,我们可以使用。上述就是任务队列的Java实现基本过程。

My52Hz 2261

YOLOv8改进策略【卷积层】| CVPR-2023 部分卷积 PConv 轻量化卷积,降低内存占用

本文记录的是利用优化的目标检测方法研究。深度可分离卷积可以减少FLOPs,但会导致更高的内存访问,引起延迟并减慢整体计算。部分卷积利用逐点卷积处理通道冗余,减少模型计算量和内存访问量。Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks及其改进的实现代码如下: 四、创新模块 4.1 改进点⭐ 模块改进方法:直接加入(第五节讲解添加步骤)。模块加入如下:模块改进方法:基于的(第五节讲解添加步骤)。第二种改进方法是对中的进行改进,并将

Limiiiing的博客 1017

activemq后台管理 看topic消息_分布式消息队列差异化总结,太全了!

本文将对Kafka、RabbitMQ、ZeroMQ、RocketMQ、ActiveMQ从17 个方面综合对比作为消息队列使用时的差异。一、资料文档Kafka:资料数量中等。有Kafka作者自己写的书,网上资料也有一些。RabbitMQ:资料数量多。有一些不错的书,网上资料多。ZeroMQ:资料数量少。专门写ZeroMQ的书较少,网上的资料多是一些代码的实现和简单介绍。RocketMQ:资...

weixin_39875842的博客 172

华为OD机试真题-国际移动用户识别码(IMSI)匹配

华为OD机试双机位C卷 国际移动用户识别码(IMSI)匹配 , 提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 国际移动用户识别码(IMSI)匹配

qq_45776114的博客 4928

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

@kafkalistener消费不到消息_案例精选 | 分布式消息队列差异化总结,太全了!

导读:本文将对Kafka、RabbitMQ、ZeroMQ、RocketMQ、ActiveMQ从17 个方面综合对比作为消息队列使用时的差异。资料文档Kafka:资料数量中等。有Kafka作者自己写的书,网上资料也有一些。RabbitMQ:资料数量多。有一些不错的书,网上资料多。ZeroMQ:资料数量少。专门写ZeroMQ的书较少,网上的资料多是一些代码的实现和简单介绍。RocketMQ:...

weixin_42315966的博客 376

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

队列管理器连接数设置_分布式消息队列差异化总结,太全了

本文将对Kafka、RabbitMQ、ZeroMQ、RocketMQ、ActiveMQ从17 个方面综合对比作为消息队列使用时的差异。一、资料文档Kafka:资料数量中等。有Kafka作者自己写的书,网上资料也有一些。RabbitMQ:资料数量多。有一些不错的书,网上资料多。ZeroMQ:资料数量少。专门写ZeroMQ的书较少,网上的资料多是一些代码的实现和简单介绍。RocketMQ:资料数量少。...

weixin_39624864的博客 147

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

多台手机同时控制,Open-AutoGLM分布式架构设计全解析

掌握多台手机同时控制的 Open-AutoGLM 部署方法,实现跨设备协同自动化。本文解析分布式架构设计原理,涵盖移动端适配、任务同步与低延迟通信机制,适用于智能办公、远程操控等场景,提升控制效率与系统稳定性,值得收藏。

PixelShoal的博客 851

并行分布式框架:Celery、rq、funboost

Celery是一个异步任务的调度工具,也可以叫做 "分布式任务队列(Distributed Task Queue)"。

freeking101的博客 5万+

RocketMQ - 存储引擎设计:与传统消息队列的差异

RocketMQ存储引擎采用CommitLog作为核心存储文件,所有消息顺序写入,同时为每个Topic/Queue维护ConsumeQueue索引以加速消息检索。相比Kafka的Log-Based存储和RabbitMQ的AMQP队列模型,RocketMQ通过分离消息存储与索引的设计,既保证了顺序写入的高性能,又支持高效的消息查询能力。其核心组件包括:CommitLog(消息主体)、ConsumeQueue(消费索引)、IndexFile(Key索引)等,这种独特架构使其在大规模消息处理场景下展现出卓越性能。

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

消息队列流量控制:从原理到高并发实战解决方案

消息队列作为分布式系统核心组件,通过异步解耦机制实现服务间可靠通信。其流量控制原理基于生产者-消费者模型,通过预取限制、速率限制和背压机制等技术手段,确保系统在高并发场景下的稳定性。在技术价值层面,流量控制能有效防止消费者被突发流量压垮,避免消息积压导致内存溢出,保证系统资源的合理利用。特别是在高并发消息处理场景中,合理的流量控制策略能够显著提升系统吞吐量和可靠性。本文基于RabbitMQ和Kafka等主流消息中间件,深入探讨流量控制在电商大促、资源受限等典型应用场景的实现方案,帮助开发者构建健壮的消息处理

weixin_33937499的博客 425

keploy竞争格局:测试自动化工具市场的差异化分析

测试自动化工具市场正经历前所未有的增长,据Gartner 2024年报告显示,全球企业在软件测试工具上的支出年增长率达18.7%,其中API测试工具细分市场占比已突破35%。随着DevOps实践的深入,开发者对测试工具的需求已从传统的QA团队主导转向开发者自助模式,这一转变催生了新型测试工具的崛起。 当前市场存在三大核心痛点: - **效率悖论**:传统工具平均需要27行代码才能生成1个有效测试...

gitblog_00426的博客 842

Kafka-King:企业级Kafka图形化管理工具提升分布式消息队列运维效率

Kafka-King是一款现代化的企业级Kafka图形化管理客户端,专为分布式消息队列运维团队设计,通过直观的可视化界面显著降低Kafka集群管理复杂度,提升运维效率。作为支持Kafka 0.8.0到3.8+全版本的企业级管理工具,Kafka-King基于Wails桌面框架和Naive UI构建,提供了从集群监控到消息生产消费的全生命周期管理能力。 ## 项目定位与价值主张 在当今微服务架构和

gitblog_00530的博客 323

本地缓存与分布式缓存的协同优化实践

缓存技术作为提升系统性能的核心手段,其本质是通过内存高速存取降低数据访问延迟。从实现原理看,本地缓存基于进程内存实现纳秒级响应,而分布式缓存则通过集群架构解决数据一致性与扩展性问题。在技术价值层面,多级缓存架构能显著降低系统延迟,美团实践显示平均响应时间从87ms优化至23ms。典型应用场景包括高频静态配置读取、热点数据副本存储等,其中Caffeine和Redis是常见解决方案。通过消息队列驱动或版本号控制可实现缓存一致性,而差异化过期时间和压缩算法能有效预防雪崩和内存问题。

weixin_31714129的博客 320

Java大厂面试实战:微服务、缓存、消息队列与AI集成

微服务架构和分布式系统是现代Java后端开发的核心技术领域,涉及服务拆分、通信协议、分布式事务等关键概念。其技术价值在于通过解耦和水平扩展提升系统弹性,在电商、金融等高并发场景广泛应用。缓存技术作为性能加速器,通过Redis等中间件实现数据高速访问,需要设计防击穿、雪崩的多层策略。消息队列如Kafka和RocketMQ解决系统解耦和流量削峰问题,在物联网、订单处理等场景表现突出。本文通过大厂面试真题,深入探讨了缓存一致性方案对比、消息队列选型考量等工程实践,并延伸至AI Agent与传统Java系统的融合挑

weixin_33423874的博客 305
上一篇: 面试官:你竟然不晓得Mybatis用了哪些设计模式?
下一篇: 面试官问你:MySQL事务和隔离级别,该如何回答
Java_supermanNO1
博客等级 码龄7年 1170粉丝 329原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值