kafka保证发送不重复:方法一.幂等性(<pid+partitionid+seqNumber>)+at least once(ack=-1);方法二.开启事务(事务管理器)
kafka单分区有序性生产条件:broker上会基于seqnumber升序来ack,如果不连续会缓存后重新排序
Kafka 为分区(Partition)引入了多副本(Replica)机制。分区(Partition)中的多个
副本之间会有一个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到
leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。生产者和消费者只与 leader 副本交互。
稀疏索引如果单纯增加consumer数来提升消费并发度,则会受限于broker的partition数,partition过大,可以考虑采用如下消费模型:
4、如何保证消息不被重复消费?
首先,比如 RabbitMQ、RocketMQ、Kafka,都有可能会出现消息重复消费的问题,正
常。因为这问题通常不是 MQ 自己保证的,是由我们开发来保证的。
Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset,代表消息的
序号,然后 consumer 消费了数据之后,每隔一段时间(定时定期),会把自己消费过的消
息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次
消费到的 offset 来继续消费吧”。
但是凡事总有意外,比如我们之前生产经常遇到的,就是你有时候重启系统,看你怎么重
启了,如果碰到点着急的,直接 kill 进程了,再重启。这会导致 consumer 有些消息处理
了,但是没来得及提交 offset,尴尬了。重启之后,少数消息会再次消费一次。
其实重复消费不可怕,可怕的是你没考虑到重复消费之后,怎么保证幂等性。一条数据重
复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性。
幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据
是不会改变的,不能出错。
其实还是得结合业务来思考:
比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,
update 一下好吧。
比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。
比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,
里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据
这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个
id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。
比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复
数据插入只会报错,不会导致数据库中出现脏数据。
Kafka
消费端弄丢了数据
唯一可能导致消费者弄丢数据的情况,就是说,你消费到了这个消息,然后消费者那边自动提交了 offset,让 Kafka 以为你已经消费好了这个消息,但其实你才刚准备处理这个消息,你还没处理,你自己就挂了,此时这条消息就丢咯。
Kafka 弄丢了数据
Kafka 的 leader 机器宕机了,将 follower 切换为 leader 之后,就会发现说这个数据就丢了。
所以此时一般是要求起码设置如下 4 个参数:
给 topic 设置 replication.factor 参数:这个值必须大于 1,要求每个 partition 必须有至
少 2 个副本。
在 Kafka 服务端设置 min.insync.replicas 参数:这个值必须大于 1,这个是要求一个
leader 至少感知到有至少一个 follower 还跟自己保持联系,没掉队,这样才能确保
leader 挂了还有一个 follower 吧。
在 producer 端设置 acks=all:这个是要求每条数据,必须是写入所有 replica 之后,才
能认为是写成功了。
126
在 producer 端设置 retries=MAX(很大很大很大的一个值,无限次重试的意思):这个
是要求一旦写入失败,就无限重试,卡在这里了。
时延分析
回归问题的本质,DMS Kafka队列的时延到底是怎么产生的?可控的端到端时延具体分为哪些?Mr. Peng给出了如下的计算公式:
总时延 = 入队时延 + 发送时延 + 写入时延 + 复制时延 + 拉取时延
让我们来依次了解一下,公式中的每一项都是指什么。
入队时延: 消息进入Kafka sdk后,先进入到要发送分区的队列,完成消息打包后再发送,这一过程所用的时间。
发送时延:消息从生产者发送到服务端的时间。
写入时延:消息写入到Kafka Leader的时间。
复制时延:消费者只可以消费到高水位以下的消息(即被多个副本都保存的消息),所以消息从写入到Kafka Leader,到所有副本都写入该消息直到上涨至高水位这段时间就是消息复制的时延。
拉取时延:消费者采用pull模式拉取数据,拉取过程所用的时间。
kafka到底会不会丢消息?答案是:会!
Kafka可能会在三个阶段丢失消息:
(1)生产者发送数据;
(2)Kafka Broker 存储数据;
(3)消费者消费数据;
在生产环境中严格做到exactly once其实是难的,同时也会牺牲效率和吞吐量,最佳实践是业务侧做好补偿机制,万一出现消息丢失可以兜底。分区不是越多越好
1、客户端/服务端所需要的内存就越多
由于Kafka支持批量消息发送,它会为每个分区缓存消息,当消息的大小达到batch.size后,就会将消息打包发送,如果分区数量很大,就会占用producer服务器一部分内存,consumer端由于分区数量很多,就会创建很多线程去消费分区消息,频繁的线程切换也会降低消费者服务器性能。
2、文件句柄的开销
每个分区消息在broker底层文件系统是由base_offset.log和batch_offset.index存储,如果分区数量越来越多所保持打开状态的文件句柄数就会越来越多,最终有可能突破操作系统限制,影响服务器性能。
3、降低可用性
Kafka通过多副本机制保证高可用,如果leader分区挂掉,那么所需要选举的时间就会越长,在选举的时候是不可用状态。
4、影响再均衡效率
消费组消费的增减都会出现再均衡,当分区数量越多,再均衡耗时就会越长,同样也是影响Kafka的消费性能
如何确定合理的分区数量呢
根据业务经验估算出来想要到达的目标吞吐量Tt,那么partition=Tt/max(Tp,Tc)
Tp:producer的吞吐量
Tc:consumer的吞吐量
kafka为什么这么快,主要是得益于以下几点
顺序写磁盘(写)
稀疏索引
【kafka】浅谈Kafka的多线程消费的设计
https://blog.csdn.net/qq_21383435/article/details/123245379
网友评论