欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

kafka与rabbitmq消息中间件

程序员文章站 2024-01-30 16:18:16
...

kafka与rabbitmq

XMind 思维导图
axure 原型设计

一:rabbitmq集群:
1.1普通集群
Rabbitmq 每个节点上有一个broker,每个broker负责本机上队列的维护,并且borker之间可以互相通信。集群中有两个队列A和B,每个队列都分为master queue和mirror queue(备份)
一个主多个备,只有主做接受和发送,备就是一个镜像,不承担压力,用在失败后成为主(为什么备不承担压力,应该是为了数据一致性吧)
例子:
机器1 队列A,队列B b-master a-mirrow(在此消费A队列,需要从机器2上读取到机器1,在给消费者)
机器2 对列A 对列B a-mster b-mirrow

1.2镜像集群
可以指定某个队列在多个节点上 存储,而不需要在拉取的时候在多个节点上传递数据

二:kafka集群 只有lead partition 才提供读写
kafka 多个master 也就是多个partition,并且这多个partitionr之间的数据没有交集(rabbit的主也没有交集)
一个队列有多个主partition,每个主partition又有若干副partition做备份,同步机制类似于RabbitMQ。

1个partition只能被同组的一个consumer消费,同组的consumer则起到均衡效果

Rabbitmq每个队列只能有一个master,即master queue单节点
kafka一个队列可以有多个master(partition)(并发高原因),也就是说同一个队列可以发往任何一个partition,多个partition没有交集
每个分区的offset是有序的,多个分区之间无序

顺序性:
多个消费者 不能保证顺序,一个会保证的,kafka由于partition机制,一个partition可以一直对应一个客户端,根据消息发送的key生产者可以固定partition
如果消费者是多线程的话,可以放到一个全局队列里面
一个topic 可以有多个partition,一个消费组里可以有多个消费者,一个消费组内的消费组不能收到重复的topic,负载均衡,
一个消费者只能在一个partition上消费,即如果消费者大于partition数量的话,有一个消费者是空闲的
一个消费组有一个offset
kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序。
消费者从哪个分区上取数据是固定的,(如果不改变分区数和消费者数的话)

在多个消费者,或者单个消费多个线程的时候,都不保证顺序的
最终要让消息有序,就要保证消费者唯一。
Rabbitmq :一个队列对应一个消费者
kafka:同一个key,发到到同一个partition

RabbitMQ本身是基于Erlang编写的,Erlang天生支持分布式(通过同步Erlang集群各节点的cookie来实现),因此不需要像Kafka那样通过ZooKeeper来实现分布式集群(维护生产者和消费者转台)

可靠性: 效率最高是发完啥也不管了,都有同步和异步的。
rabbit
生产者:通过事务(channel.txSelect)或者生产者confirm模(实际也是ack),有同步和异步的confirm,异步(监听)性能高 channel.addConfirmListener
消费者:ack,broker收到后立刻删除(效率低一个原因)
broker:持久化
先是内存,满了磁盘
kafka
生产者:kafka的ack机制 request.required.acks
=0 直接返回。
=1 leader确认消息存后再返回,保证至少一次语义
=all leader和ISR中所有replica都确认消息再返回,保证至少一次语义

消费者:	1.读取消息 -> 提交offset -> 处理消息   	2.读取消息 -> 处理消息 -> 提交offset 。 commit offset 和业务操作弄成一个事务
broker:返回ack的时机 request.required.acks=0 直接返回  =1 leader确认消息存下来了,再返回,保证至少一次语义 =all leader和ISR中所有replica都确认消息存下来了,再返回,保证至少一次语义

一直是磁盘

提交offset:
自动
通过auto.commit.interval.ms指定时间间隔,可能会丢数据,因为自动提交了,
但是客户端处理失败了,就会丢失,解决办法是客户端如果失败的话在catch 里保存信息,通过一个定时任务重试,直到成功。
手动 分同步和异步,同步会重试,异步不会重试

databus mysql通过binlog,实现缓存等等。

消费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;
而kafka是通过客户端更新offset来实现的。可以自动实现,也可以客户端通过代码实现

Kafka的consumer的offset存储:
一种是存放在broker的日志目录中,另一种方式是存放在zookeeper中。两种存放方式和你使用kafka-console-consumer命令使用的选项有关。如果使用的是bootstrap-server,那么就存放在broker;如果使用的是–zookeeper那么就存放在zookeeper。

消息被处理的状态是在consumer端维护 注意是维护 不是存储

offset是代表某个分区被某个组目前消费的位置,
比如 p1 group1 10
比如说,p1里面有来了一些数据,那p1的数据位置 15
消费者用 p1 group1 10和 15一比较,就可以得到 10~15的数据

一个topic可以给多个分区消息,多个分区不会重复数据
一个broke上可以有多个分区,多个分区有一个lead
同一个消费组内的消费者要小于分区数,不然会有消费者永远 收不到数据

基于replicated方案,那么就意味着需要对多个备份进行调度;每个partition都有一个server为"leader";leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可…由此可见作为leader的server承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定.
 
    Producers
    Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息归属于哪个partition;比如基于"round-robin"方式或者通过其他的一些算法等.
key指定

redis 分片集群 主写从读,只在从配置就好(从拉取的方式),通过rdb发送给从快照,需要哨兵
集群不同的分片上不同key。redis 3.0以后才有分片集群
缺点 多个key的操作不支持