kafka 基础知识
kafka不仅仅是消息中间件,还是个流式计算框架。
要点
- 简单介绍
- 基本概念
- 分区
- 避免消息丢失
- 拦截器
- rebalance
1.基本介绍
kafka主要有两大应用:
1)构造实时流数据管道,它可以在系统或应用之间可靠地获取数据。 (相当于message queue)
2)构建实时流式应用程序,对这些流数据进行转换或者影响。 (就是流处理,通过kafka stream topic和topic之间内部进行变化)
Kafka作为一个集群,运行在一台或者多台服务器上;Kafka 通过 topic 对存储的流数据进行分类。
每条记录中包含一个key,一个value和一个timestamp(时间戳)。
Kafka有四个核心的API:
- The Producer API 允许一个应用程序发布一串流式的数据到一个或者多个Kafka topic。
- The Consumer API 允许一个应用程序订阅一个或多个 topic ,并且对发布给他们的流式数据进行处理。
- The Streams API 允许一个应用程序作为一个流处理器,消费一个或者多个topic产生的输入流,然后生产一个输出流到一个或多个topic中去,在输入输出流中进行有效的转换。
- The Connector API 允许构建并运行可重用的生产者或者消费者,将Kafka topics连接到已存在的应用程序或者数据系统。比如,连接到一个关系型数据库,捕捉表(table)的所有变更内容。
2. 基本概念
- Record:消息,指Kafka处理对象
- Topic:主题,用来承载消息的容器
- Partition:分区,一个有序不变的消息队列,一个主题下可以有多个分区
- Offset:消息位移,表示分区中每条信息的位置,是一个单调递增不变的值
- Replica,副本,数据冗余。
-- 领导者副本:对外提供服务,与客户端进行交互
-- 追随者副本:不能与外界进行交互,只是被动地追随领导者副本 - Producer:生产者,向主题发布新消息的应用程序
- Consumer:消费者,向主题订阅新消息的应用程序
- Consumer Offset:消费者位移,表示消费者消费进度
- Consumer Group:消费者组,多个消费者实例共同组成的一个组,同时消费多个分区来实现高吞吐。
- Rebalance:重平衡,消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。它是Kafka消费者端实现高可用的重要手段
3.分区
主题-->分区-->消息
生产者将消息发送到主题,消费者订阅主题,而主题下是有不同分区了,消息是挂在不同的分区之下的。一个分区只能有一个消费者,不能出现多个消费者同时订阅一个分区。
其实分区的作用就是提供负载均衡的能力,或者说对数据进行分区的的主要原因,就是为了实现系统的伸缩性。不同的分区放在不同的节点上,数据的读写针对分区这个粒度进行的。这样可以通过增加新节点实现增加系统的吞吐量。
消息分区策略:
分区策略:轮询策略(默认)、随即策略、按消息键保序策略、其他策略(如:基于地理位置进行分区)
如何实现因果关系消息的顺序行:基于个别字段进行分区
4.避免消息丢失
-
消息丢失:
Kafka只对已提交的消息做持久化工作保存
提交不成功:网络抖动,消息不合格kafka拒绝接受
总之,职责在于producer,不要使用 producer.send(msg),用producer.send(msg, callback) api -
Consumer消费消息丢失:
1)维持先消费消息(阅读),再更新位移(书签)的顺序
2)如果是多线程异步处理消费消息,Consumer 程序不要开启自动提交位移,而是要应用程序手动提交位移
解决方案:
- 不要使用 producer.send(msg),而要使用 producer.send(msg, callback)
- 设置acks=all。acks是producer的一个参数,设置成all代表所有的broker都接收到信息,才算是已提交消息
- 设置retries位一个较大值,代表重试次数(网络抖动)
- 设置unclean.leader.election.enable=false。Broker参数,如果一个落后的borker变成leader,必然会造成消息丢失
- 设置replication.factor >= 3。Broker参数,备份数,数据冗余避免丢失
- 设置 min.insync.replicas > 1。Broker参数,这只消息至少呗写入多少个副本才算是已提交
- 确保replication.factor > min.insync.repicas 。如果两个相等只要有一个副本机挂了,整个分区将无法正常工作
- 设置enable.auto.commit=false。consumer的参数,确保消费完再提交
5.拦截器
Kafka 拦截器分为生产者拦截器和消费者拦截器,都支持链。
生产者拦截器要实现org.apache.kafka.clients.producer.ProducerInterceptor
消费者拦截器:org.apache.kafka.clients.consumer.ConsumerInterceptor
6.幂等性和事务
消息投递语义:
- 最多一次:消息可能丢失,但绝对不会重复
- 至少一次:消息不会丢失,但可能会重复
- 精确一次:消息不会丢失,也不会重复
Kafka:默认至少一次,那么Kafka如何做到精确一次?
幂等性和事务!!!
- 幂等性producer:
很简单 就设置enable.idempotence=ture
注意:
1)只能保证单分片的幂等性
2)会话幂等性,不能实现跨会话幂等性 - 事务型producer:
1)首先开启幂等性:enable.idempotence=ture
2)其次设置 Producer 端参数 transctional.id
Consumer需要设置隔离级别:
solation.level
1)read_uncommitted:默认读未提交
2)read_committed:读已提交
7.rebalance
- Rebalance发生的时机有三个
1)组成员数据量发生变化
2)订阅主题数量发生变化
3)订阅主题的分区数发生变化
其中第一个最常见,后面两个通常是运维的主动操作,无法避免。主要还是针对组成员数量减少的情况。增加一般也是人为主动的。
那么避免因为参数或逻辑不合理而导致的成员退出,与之相关的主要参数
1)session.timeout.ms,推荐设置6s
2)heartbeat.interval.ms,推荐设置2s
3)max.poll.interval.ms,推荐设置比你的业务逻辑处理要长
4)GC参数,避免频繁的FULL GC
重平衡过程是如何通知到其他消费者实例的?
靠消费者端的心跳线程(Heartbeat Thread)
消费者定期的发生心跳请求到Broker端的协调者,以表明他还活着。当协调者决定开启新一轮平衡后,他会将“rebalance_in_progress”封装进心跳请求的响应中,返还给消费者实例。当消费者实例发现心跳响应中包含了“rebanlance_in_progress”,就能立马知道冲平生又开始了。
heartbeat.interval.ms控制重平衡通知的频率