赞
踩
Apache kafka is a distributed streaming platform,即官方定义 kafka 是一个分布式流式计算平台。而在大部分企业开发人员中,都是把 kafka 当成消息系统使用,即它是一个分布式消息队列,kafka的架构运行图如下:
kafka的架构运行图
kafka关键的概念如下:
Broker:一个服务器实例
Topic:一条消息流
Partition:分区,每个topic可以按特定分区逻辑分区,类似mysql的分表
Producer:消息生产者
Consumer:消息消费者
Consumer group:消费者组,相同的groupid的consumer组成一个组(对于消息流在同一个消费组中分发,为了实现负载均衡)
Offset:一条消息在消息流中的偏移(就像mysql的自增id)
消费者端消费消息有两种方式:
1:读取到消息直接提交offset
优点:消费者读取消息就更新offset,kafka消息不会阻塞
缺点:业务代码处理报错,消息会丢失
2:业务代码全部处理完,在提交offset
优点:消费者读取消息并业务代码全部处理完在提交offset,消息不会丢失
缺点:业务代码处理报错,会一直重复消费这条休息,会造成kafka消息阻塞
Springboot通过配置实现
#offset enable.auto.commit=false为springboot手动提交,为true就是kafka默认提交
enable:
auto:
commit: true
基于方法2,进行优化的方法如下:
优化方法1:将springboot的手动提交,改成在代码finally里面提交,防止业务代码报错,kafka消息阻塞。丢失的消息只能在日志里面查出原因进行解决了。
具体实现如下:
@KafkaListener(topics = "${kafka.topic}")
public void consumer(ConsumerRecord<?, ?> record, Acknowledgment ack) {
try {
……
} catch (Exception e) {
log.info("kafka 消费异常:", e);
} finally {
// 手动提交offset,防止节点服务宕机而造成数据丢失
ack.acknowledge();
}
}
}
优化方法2:业务代码出现报错可能是网络抖动引起,可以进行重试机制,错误超过3次,提交offset。
retries: 3
注意:消费者端一定要加上事务,防止数据重复引起很多脏数据。
Kafka消费都是顺序性的,一类相同的消息是放在一个topic里面的不同partition里面的,但是我们知道kafka消费端是一个集群,不同的服务端消费,kafka的消息是不是会乱呢。为了
保证消费kafka消息的顺序性,需要做好如下几点:
针对多个消息体是有依赖关系,下一个消息的实现是依赖上个消息,由于每个消息处理的速度不同,可能相互依赖的消息出现混乱,造成业务代码报错。针对该场景kafka消费端多线程不要用。若是每个消息体没有业务依赖关系,可以用多线程加快消息处理速度。
设定partition或者key保证固定的服务端消费固定的partition
Kafka 分布式的单位是 partition,同一个 partition 用一个 write ahead log 组织,所以可以保证 FIFO 的顺序。不同 partition 之间不能保证顺序。但是绝大多数用 户都可以通过 message key 来定义,因为同一个 key 的 message 可以保证只发 送到同一个 partition。Kafka 中发送 1 条消息的时候,可以指定(topic, partition, key) 3 个参数。partiton 和 key 是可选的。如果你指定了 partition,那就是所有消息发往同 1个 partition,就是有序的。并且在消费端,Kafka 保证,1 个 partition 只能被 1 个 consumer 消费。或者你指定 key(比如 order id),具有同 1 个 key 的 所有消息,会发往同 1 个 partition。
不设定partition或者key
Kafka保证一类消息都发送到对应的partition里,需要确定的服务端比partition分区多,不然一个服务端消费多个分区,会造成同类消息的错乱。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。