kafka与rabbitmq消息中间件
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的操作不支持
上一篇: php图片按比较生成缩略图片代码