同步操作将从 Java精选/Ebooks 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
交换器(Exchange)
消息代理服务器中用于把消息路由到队列的组件。
队列(Queue)
用来存储消息的数据结构,位于硬盘或内存中。
绑定(Binding)
一套规则,告知交换器消息应该将消息投递给哪个队列。
在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id值,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列。
在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,比如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。
针对此类问题,列举处理消息的业务场景:
1、用户获取到消息执行数据库insert插入操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
2、用户获取到消息执行redis缓存set插入操作,不需要解决重复,因为无论set几次结果都是一样的,set操作本来幂等操作。
3、如果上面两种情况还不行,可以考虑使用记录消费。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以Key-Value的形式写入到redis中。当消费者开始消费消息时,首选获取redis中有没消费过该记录。
Zookeeper是一个开放源码的、高性能的协调服务,它用于Kafka的分布式应用。
Zookeeper主要用于在集群中不同节点之间进行通信。
在Kafka中,它被用于提交偏移量,因此如果节点在任何情况下都失败了,它都可以从之前提交的偏移量中获取。
除此之外,它还执行其他活动,如:leader检测、分布式同步、配置管理、识别新节点何时离开或连接、集群、节点实时状态等等。
ISR是一组与leaders完全同步的消息副本,也就是说ISR中包含了所有提交的消息。
ISR应该总是包含所有的副本,直到出现真正的故障。
如果一个副本从leader中脱离出来,将会从ISR中删除。
broker是指一个或多个erlang node的逻辑分组,且node上运行着RabbitMQ应用程序。
cluster是在broker的基础之上,增加了node之间共享元数据的约束。
RabbitMQ 消费类型也就是交换器(Exchange)类型有以下四种:
direct:轮询方式。
headers:轮询方式,允许使用header而非路由键匹配消息,性能差,几乎不用。
fanout:广播方式,发送给所有订阅者。
topic:匹配模式,允许使用正则表达式匹配消息。
RabbitMQ默认的是direct方式。
direct(默认方式):最基础最简单的模式,发送方把消息发送给订阅方,如果有多个订阅者,默认采取轮询的方式进行消息发送。
headers:与direct类似,只是性能很差,此类型几乎用不到。
fanout:分发模式,把消费分发给所有订阅者。
topic:匹配订阅模式,使用正则匹配到消息队列,能匹配到的都能接收到。
Kafka只对“已提交”的消息(committed message)做有限度的持久化保证。所以说,Kafka不能够完全保证数据不丢失,需要做出一些权衡策略。
什么是已提交的消息?
当Kafka的若干个Broker成功地接收到一条消息并写入到日志文件后,它们会告诉生产者程序这条消息已成功提交。此时,这条消息在Kafka看来就正式变为已提交消息了。所以说无论是ack=all,还是ack=1,不论哪种情况,Kafka只对已提交的消息做持久化保证这件事情是不变的。
有限度的持久化保证消息不丢失,也就是说Kafka不可能保证在任何情况下都做到不丢失消息。必须保证Kafka的Broker是可用的,换句话说,假如消息保存在N个Kafka Broker上,那么这个前提条件就是这N个Broker中至少有 1个存活。只要这个条件成立,Kafka就能保证你的这条消息永远不会丢失。
总结的说就是Kafka是能做到不丢失消息的,只不过这些消息必须是已提交的消息,而且还要满足一定的条件。
将auto.commit.offset设为false,然后在处理一批消息后commitSync()或者异步提交commitAsync()即:
ConsumerRecords<> records = consumer.poll();
for(ConsumerRecord<> record : records){
try{
consumer.commitSync();
}
}
Kafka的主题是分区有序的,如果一个主题有多个分区,那么Kafka会按照key将其发送到对应的分区中,所以,对于给定的key与其对应的record在分区内是有序的。
Kafka可以保证同一个分区里的消息是有序的,即生产者按照一定的顺序发送消息,Broker就会按照这个顺序将他们写入对应的分区中,同理,消费者也会按照这个顺序来消费他们。
在一些场景下,消息的顺序是非常重要的。比如,先存钱再取钱与先取钱再存钱是截然不同的两种结果。
上面的问题中提到一个参数max.in.flight.requests.per.connections=1,该参数的作用是在重试次数大于等于1时,保证数据写入的顺序。如果该参数不为1,那么当第一个批次写入失败时,第二个批次写入成功,Broker会重试写入第一个批次,如果此时第一个批次重试写入成功,那么这两个批次消息的顺序就反过来了。
一般来说,如果对消息的顺序有要求,那么在为了保障数据不丢失,需要先设置发送重试次数retries>0,同时需要把max.in.flight.requests.per.connections参数设为1,这样在生产者尝试发送第一批消息时,就不会有其他的消息发送给broker,虽然会影响吞吐量,但是可以保证消息的顺序。
除此之外,还可以使用单分区的Topic,但是会严重影响吞吐量。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。