kafka如何保证数据的消息不丢失(最简洁)
一、kafka 本身配置层面
1.1、replication.factor 默认值1
创建kafka的topic时候,每个分区设置的副本数, 根据broker数量酌情设置, 建议业界通常做法设置为3
1.2、min.insync.replicas 默认值1
消息至少要被写入到min.insync.replicas这么多副本才算成功时候,通常使用小于replication.factor,当request.required.acks = all时生效
二、kafka的生产者层面
2.1、设置副本确认
request.required.acks 有3个取值,分别是0,1,all
0:表示无需等待broker确认就认为写入成功,风险大,一般不使用
1:表示当leader确认写入成功就认为成功了,有数据丢失风险,不建议使用
all:leader和follower都确认写入成功,才能认为是写入成功了,推荐使用(-1在新版本已弃用)
2.2、设置重试次数
retries 默认值0,不重试。kafka返回写入消息失败,生产者进行重新发送,直到成功, 根据业务合理设置重试次数
2.3、消息补偿机制
虽设置了重试次数,但不可能一直重试,如重试3次后仍然失败,这时候可把失败消息放入本地消息表,用定时任务轮询消息表, 重新生产推送到kafka
三、kafka的消费者层面
3.1 关闭自动 offset
设置 enable.auto.commit = false , 默认值true,自动提交
3.2 手动提交offset
使用kafka的Consumer的类,用方法consumer.commitSync()提交
或者使用spring-kafka的 Acknowledgment类,用方法ack.acknowledge()提交(推荐使用
第二:如何确保消息成功地发送至 MQ?
1. 实现:提交事务。 channel.txSelect:用于将当前的信道设置成事务模式、channel.txCommit:用于提交事务、channel.txRollback:用于回滚事务
2. 实现: 发送方确认模式(publisher confirm)。(即信道设置成confirm模式): channel.confirmSelect();将信道设置成confirm模式。
一旦信道进入confirm模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从1开始),
一旦消息被投递到RabbitMQ服务器之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),
这就使得生产者知晓消息已经正确到达了目的地了。如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。
性能比较:
可以看出,事务机制最慢,使用事务机制会“吸干”RabbitMQ的性能。 普通confirm机制虽有提升但是不多,
批量confirm和异步confirm性能最好,大家可以根据自己喜好自行选择使用哪种机制,个人建议使用异步confirm机制。
第三:如何确保消息接收方消费了消息MQ?
消息确认模式有:
AcknowledgeMode.NONE:自动确认
AcknowledgeMode.AUTO:根据情况确认
AcknowledgeMode.MANUAL:手动确认
1.消息通过 ACK 确认是否被正确接收,每个 Message 都要被确认(acknowledged),可以手动去 ACK 或自动 ACK
2.自动确认会在消息发送给消费者后立即确认,但存在丢失消息的可能,如果消费端消费逻辑抛出异常,也就是消费端没有处理成功这条消息,那么就相当于丢失了消息。
3.如果消息已经被处理,但后续代码抛出异常,使用 Spring 进行管理的话消费端业务逻辑会进行回滚,这也同样造成了实际意义的消息丢失
4.如果手动确认则当消费者调用 ack、nack、reject 几种方法进行确认,手动确认可以在业务失败后进行一些操作,如果消息未被 ACK 则会发送到下一个消费者。
5.如果某个服务忘记 ACK 了,则 RabbitMQ 不会再发送数据给它,因为 RabbitMQ 认为该服务的处理能力有限。
第四:如何保证MQ消息的可靠传输?
以我们常用的RabbitMQ为例,
丢失又分为:生产者丢失消息、消息队列丢失消息、消费者丢失消息;
1. 生产者丢失消息:从生产者弄丢数据这个角度来看,RabbitMQ提供confirm模式来确保生产者不丢消息;
2. 消息队列RabbitMQ丢数据:消息持久化。就是消息写入之后会持久化到磁盘。
持久化可以跟生产者那边的 confirm 机制配合起来,只有消息被持久化到磁盘之后,
才会通知生产者 ack 了,所以哪怕是在持久化到磁盘之前,RabbitMQ 挂了,数据丢了,
生产者收不到 ack,你也是可以自己重发的。
3. 消费端弄丢了数据:关闭 RabbitMQ 的自动ack可以通过一个api来调用就行,每次代码里确保处理完的时候,再在程序里ack一把。
第五:如何避免消费者手动ack失败,导致该消息会阻塞在队列中,后续的消息也会被阻塞住导致消息无法消费?
针对:rabbitMQ
rabbitMQ提供配置参数来开启消费者重试机制,也能配置配置最大重试次数和重试间隔时间,
rabbitMQ对于消息消费失败达到一定次数后,就会放弃该消息,
我们可以手动实现,如果消费失败达到最大重试次数后,将数据转发到死信队列上,
由死信队列的消费者来实现消息的持久化到数据库或者日志文件中,一般重试次数我们设置为3此,间隔时间为5s。
第六:Kafka中如何实现死信队列&重试队列?
死信队列: 当一条消息初次消费失败,消息队列 MQ 会自动进行消息重试;达到最大重试次数后,若消费依然失败,
则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列 MQ 不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中,
这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。
回退队列: 与此对应的还有一个“回退队列”的概念,试想如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认(Ack),
进而发生回滚消息的操作之后消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环。为了解决这个问题,
可以为每个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障。实际情况下,回退队列的角色可以由死信队列和重试队列来扮演。
重试队列: 其实可以看成是一种回退队列,具体指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到Broker中。
与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。
Kafka不支持重试机制也就不支持消息重试,也不支持死信队列,
因此使用kafka做消息队列时,如果遇到了消息在业务处理时出现异常的场景时,需要额外实现消息重试的功能。
demo举例: https://artisan.blog.csdn.net/article/details/113846000
如果不想自己实现消息重试机制,建议使用RocketMQ作为消息队列,RocketMQ的消息重试机制相当完善,
详见: https://help.aliyun.com/document_detail/43490.html
第七:如何避免MQ消息重复投递或重复消费?
关键在于消息处理逻辑的幂等性,也就是说同一条消息无论被消费多少次,产生的结果和消息被消费一次是一样的.
(1)比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update一下好吧,(或者inSertIgnore有就更新,没有就插入)
(2)比如你是写redis,那没问题了,反正每次都是set,天然幂等性
(3)业务发送方带入唯一UUID,订单id做,消费方用唯一标示去查询,status作为标示是否处理过。
第八:如何保证消息的顺序性?
一个消费者对应一个队列,并且确保需要保证顺序的消息路由在同一个队列中。
kafka如何保证数据的消息不丢失(最简洁)的更多相关文章
- Kafka如何保证数据不丢失
Kafka如何保证数据不丢失 1.生产者数据的不丢失 kafka的ack机制:在kafka发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的能够被收到,其中状态有0,1,-1. 如果是 ...
- [转帖]kafka 如何保证数据不丢失
kafka 如何保证数据不丢失 https://www.cnblogs.com/MrRightZhao/p/11498952.html 一般我们在用到这种消息中件的时候,肯定会考虑要怎样才能保证数 ...
- Spark Streaming和Kafka整合保证数据零丢失
当我们正确地部署好Spark Streaming,我们就可以使用Spark Streaming提供的零数据丢失机制.为了体验这个关键的特性,你需要满足以下几个先决条件: 1.输入的数据来自可靠的数据源 ...
- kafka 如何保证数据不丢失
一般我们在用到这种消息中件的时候,肯定会考虑要怎样才能保证数据不丢失,在面试中也会问到相关的问题.但凡遇到这种问题,是指3个方面的数据不丢失,即:producer consumer 端数据不丢失 b ...
- kafka如何保证数据可靠性和数据一致性
数据可靠性 Kafka 作为一个商业级消息中间件,消息可靠性的重要性可想而知.本文从 Producter 往 Broker 发送消息.Topic 分区副本以及 Leader 选举几个角度介绍数据的可靠 ...
- 如何保证RabbitMQ的消息不丢失及其背后的原理
一.消息为什么丢失 RabbitMQ默认情况下的交换机和队列以及消息是非持久化的,也就是说在服务器重启或者宕机恢复后,之前创建的交换机和队列都将不复存在,之前未消费的消息也就消失不见了.原因在于每个队 ...
- Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?
1.kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的 ...
- Kafka如何保证消息不丢失不重复
首先需要思考下边几个问题: 消息丢失是什么造成的,从生产端和消费端两个角度来考虑 消息重复是什么造成的,从生产端和消费端两个角度来考虑 如何保证消息有序 如果保证消息不重不漏,损失的是什么 大概总结下 ...
- kafka保证数据不丢失机制
kafka如何保证数据的不丢失 1.生产者如何保证数据的不丢失:消息的确认机制,使用ack机制我们可以配置我们的消息不丢失机制为-1,保证我们的partition的leader与follower都保存 ...
- 大数据平台消息流系统Kafka
Kafka前世今生 随着大数据时代的到来,数据中蕴含的价值日益得到展现,仿佛一座待人挖掘的金矿,引来无数的掘金者.但随着数据量越来越大,如何实时准确地收集并分析如此大的数据成为摆在所有从业人员面前的难 ...
随机推荐
- 【Android】学习day05|简单登陆页面的实现|监听代码
实现效果如下图所示 实现代码[部分] MainActivity.java 1 package com.example.app02; 2 3 import androidx.appcompat.app. ...
- 一次显著的性能提升,从8s到0.7s
前言 最近我在公司优化了一些慢查询SQL,积累了一些SQL调优的实战经验. 我之前写过一些SQL优化相关的文章<聊聊SQL优化的15个小技巧>和<explain | 索引优化的这把绝 ...
- Kotlin协程系列(三)
1.前言 前面两节,我们运用了kotlin提供的简单协程去实现了一套更易用的复合协程,这些基本上是以官方协程框架为范本进行设计和实现的.虽然我们还没有直接接触kotlin官方协程框架,但对它的绝大多数 ...
- Azure - 机器学习企业级服务概述与介绍
Azure 机器学习 - 为端到端机器学习生命周期使用企业级 AI 服务. 关注TechLead,分享AI全维度知识.作者拥有10+年互联网服务架构.AI产品研发经验.团队管理经验,同济本复旦硕,复旦 ...
- UI自动化测试框架:数据驱动
一.UI自动化框架介绍 测试框架使用了Po设计模式(Page Object),每一个页面用一个类来对应,这个类里面要实现所有核心页面元素的获取方法,类里面提供操作页面元素的所有方法. 这个框架实现几点 ...
- SpringBoot整合阿里云OSS
1.创建一个service_ossspringboot项目 2.导入相关依赖 ...其他的依赖大家自行导入 <!-- 阿里云oss依赖 --> <dependency> < ...
- Volcano 原理、源码分析(一)
0. 总结前置 1. 概述 2. Volcano 核心概念 2.1 认识 Queue.PodGroup 和 VolcanoJob 2.2. Queue.PodGroup 和 VolcanoJob 的关 ...
- 神经网络优化篇:梯度检验应用的注意事项(Gradient Checking Implementation Notes)
梯度检验应用的注意事项 分享一些关于如何在神经网络实施梯度检验的实用技巧和注意事项. 首先,不要在训练中使用梯度检验,它只用于调试.意思是,计算所有\(i\)值的\(d\theta_{\text{ap ...
- Spring Boot 导出EXCEL模板以及导入EXCEL数据(阿里Easy Excel实战)
Spring Boot 导出EXCEL模板以及导入EXCEL数据(阿里Easy Excel实战) 导入pom依赖 编写导出模板 @ApiOperation("导出xxx模板") @ ...
- 2023-06-30:给你一个 rows * cols 大小的矩形披萨和一个整数 k, 矩形包含两种字符: ‘A‘ (表示苹果)和 ‘.‘ (表示空白格子), 你需要切披萨 k-1 次,得到 k 块披
2023-06-30:给你一个 rows * cols 大小的矩形披萨和一个整数 k, 矩形包含两种字符: 'A' (表示苹果)和 '.' (表示空白格子), 你需要切披萨 k-1 次,得到 k 块披 ...