目录
1.概述
为方便扩展,并提高吞吐量,一个topic分为多个partition;
配合分区的设计,提出消费组的概念,组内每个消费者并行消费;
为提高可用性,为每个partition增加若干副本;
zk中记录的是leader,2.8.0之后也可以配置不采用zk
2.入门
config下的Server.properties修改:
broker.id=唯一标识
log.dirs = /opt/module/kafka/datas
zookeeper.connect = xx.xx.xx.xx:2181,xx.xx.xx.xx:2181,xx.xx.xx.xx:2181/kafka
启动命令:./bin/kafka-server-start.sh config/server.properties(默认可以不指定)
2.1 测试消息的生产与消费
命令如下:
创建一个主题
bin/kafka-topic.sh --zookeeper localhost:2181 --create --topic chl --partitions 2 --replication-factor 1
# zookeeper 指定kafka所连接的zk服务器地址
# topic 指定要创建的主题名称
# partitions 指定了分区个数
# replication-factor 指定副本因子
# create 创建主题的命令
查看所有主题:
/bin/kafka-topic.sh --zookeeper localhost:2181 --list
/bin/kafka-start.sh --zookeeper localhost:2181 --describe --topic chl
启动消费端接受消息:
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic chl
# bootstrap-server 指定了连接kafka集群的地址
# topic 指定了消费端订阅的主题
生产端发送消息:
/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic chl
# broker-list 指定连接kafka集群的地址
# topic指定了发送消息的主题
查看linux centos7 防火墙是否关闭:firwwall -cmd --state
总结kafka服务端配置:
zookeeper.connect #指明zookeeper地址,如果zk是集群则以逗号分开;
listeners:监听列表,broker对外提供服务时绑定的ip和端口,多个以逗号隔开,如果监听器名称不是一个安全的协议,listener.security.protocol.map也必须设置,主机名称设置0.0.0.0绑定所有的接口,主机名称为空则绑定默认的接口。如:PLAINTEXT://myhost:9092,SSL://9091 CLIENT://0.0.0.0:9092 REPLICATION://localhost:9093
broker.id:broker的唯一标识符,如果不配置,则自动生成,建议配置
log.dir:日志数据存放目录
message.max.bytes:服务器接受单个消息的最大大小,默认976.6kb
3.生产者详解
3.1 kafka java客户端数据生产流程分析
3.2 发送类型
producer.send(record);
同步发送:
通过send()发送完消息后返回一个Future对象,然后调用Future对象的get()方法等待kafka
响应,如果kafka正常响应,返回一个RecordMetaData对象,该对象存储消息的偏移量
如果kafka发生错误,无法正常响应,就会抛出异常
异步发送:
producer.send(record,new Callback(){
public void onCompletion(RecordMetadata metadata,Excepton exception){
if(exception ==null){
System.put.prinltn(metadata.partition()+":"+metadata.offset());
}
}
});
3.3 序列化器
消息要到网络上传输,必须进行序列化,而序列化器的作用就是如此。
kafka提供了默认的字符串序列化器(StringSerializer),还有IntegerSerializer、字节数组ByteSerializer序列化器,这些序列化器都实现了接口
3.4 分区器
本身kafka有自己的分区策略的,如果未指定,就会默认的分区策略;
kafka根据传递消息的key来进行分区的分配,即hash(key)%numPartitions。如果key相同的话,就会分配到统一分区。
自定义分区器实现Partitioner
3.5 拦截器
Producer拦截器interceptor是个相当新的功能,它和consumer、interceptor是在kafka0.10版本被引入的,主要用于实现clients端的定制化控制逻辑。
生产者拦截器可以在消息发送前做一些准备工作。
使用场景:1.按照某个规则过滤掉不符合要求的消息。2.修改消息的内容。3.统计类需求
实现ProducerInterceptor接口
KafkaProducer对象是线程安全的,多个线程可以共享KafkaProducer对象。
3.6其他参数
acks:
这个参数用来指定分区中必须有多个副本收到这条消息,之后生产者才会认为这条消息写入成功。acks是生产者客户端中非常重要的一个参数,它涉及到消息的可靠性和吞吐量之间的权衡。
ack=0,生产者在成功写入消息之前不会等待任何来自服务器的响应。如果出现问题生产者是感知不到的,消息就丢失了。不过因为生产者不需要等待服务器响应,所以它可以以网络能够支撑的最大速度发送消息,从而达到很高的吞吐量。
ack=1,默认值1,只要集群的首领节点收到消息,生产者就会收到一个来自服务器的成功响应。如果消息无法达到首领节点(比如首领节点奔溃,新的首领还没有被选举出来),生产者会收到一个错误响应,为了避免数据丢失,生产者会重发消息。但是,这样有可能会导致数据丢失,如果收到写成功通知,此时首领节点没来得及同步数据到follow节点,首领节点奔溃,就会导致数据丢失。
ack=-1,只有当所有参与复制的节点都收到消息时,生产者会收到一个来自服务器的成功响应,这种模式是最安全的,它可以保证不止一个服务器收到消息。
acks参数是一个字符串类型,不是整数类型,如果配置成整数类型会抛出异常。
4.消费者
4.1 消息接受参数设置
序列化、设置消费组
4.2 订阅主题和分区
正在表达式订阅:
consumer.subscribe(Pattern.compile("chl*"));
指定订阅的分区:
comsumer.assign(Arrays.asList(new TopicPartition("topic0888"),0));
4.3 位移提交
对于kafka中的分区而言,它的每条消息都有唯一的offSet,用来表示消息在分区中的位置
调用poll()时,该方法会返回我们没有消费的消息,当消息从broker返回消费者时,broker并不跟踪这些消息是否被消费者接收到,kafak让消费者自身管理消费的位移,并向消费者提供更新位移的接口,这种更新位移方式称为提交。
会导致重复消费、消息丢失等情况;
默认自动提交offset;enable.auto.commit(true);
4.4 同步、异步提交
自动提交:
这种方式让消费者来管理位移,应用本身不需要显示操作。当enable.auto.commit设置为true,那么消费者会在poll方法调用后每隔5秒(由auto.commit.interval.ms指定)提交一次位移。和很多其他操作一样,自动提交也是由poll()方法来驱动的,在调用poll方法时,消费者判断是否达到提交时间,如果是则提交上一次poll返回的最大位移。需要注意到,这种方式可能会导致消息重复消费,假如,某个消费者poll消息后,应用正在处理消息,在3秒后kafka进行了重平衡,那么由于没有更新位移导致重平衡后部分消息重复消费。
4.5 指定位移消费
目前为止,我们知道消息的拉取是根据poll()方法中的逻辑处理的,但是这个方法对于普通开发人员来说就是个黑盒处理,无法精确掌握其消费的起始位置。
seek()方法正好提供了这个功能,让我们得以追踪以前的消费或者回溯消费
4.6再均衡监听器
再均衡是指分区的所处从一个消费者转移到另外一个消费者的行为,它为消费组具备了高可用性和伸缩性提供了保障,使得我们既方便有又安全地删除消费组内的消费者或者往消费者内添加消费者。不过再均衡发生期间,消费者是无法拉取消息的。
4.7 消费者拦截器
消费者拦截器主要是在消费到消息或在提交消费位移时进行的一些定制化的操作。
5.主题
topic元数据信息保存在zk中
创建副本时,副本数量不能大于总节点数量。
删除主图:
若delete.topic.enable=true,直接彻底删除topic;
若delete.topic.enable=false,如果当前Topic没有使用过即没有传输过消息,可以彻底删除;
如果当前Topic有使用过传输过消息,并没有真正删除Topic只是把这个topic标记为删除,重启Kafka server后删除。
5.1 增加分区
修改分区时,只能增加分区,不能减少分区,减少会报异常;
6.分区
kafka可以将主题划分为多个分区partition,会根据分区规则选择把消息存储到哪个分区中,只要如果分区规则设置的合理,那么所有的消息将会被均匀的分布到不同的分区中,这样就实现了负载均衡和水平扩展。另外,多个订阅者可以从一个或多个分区中同时消费数据,以支撑海量数据处理能力。
producer和consumer都只会与leader角色的分区副本相连。
Follower:
Follower跟随leader,所有写请求都通过leader路由,数据变更会广播给所有Follower,Follower与lead保持数据同步,如果Leader失效,则从Follower中选举出一个新的leader。当Follower与Leader挂掉、卡主或者同步太慢,leader会把这个Follower从ISR列表中删除,重新建一个Follower.
Zookeeper:负责维护和协调broker,当kafka系统中新增了broker或某个broker发生故障失效时,由zookeeper通知生产者和消费者,生产者和消费者依据zk的broker状态消息与broker协调数据的发布和订阅任务。
AR:分区中的所有副本;
ISR:所有与leader副本(包括Leader副本在内)保持一定程度的副本组成ISR;
OSR:与Leader副本同步滞后过多的副本;
HW:高水位,标识了一个特定的offset,消费者只能拉取到这个offset之前的消息;
LEO:日志末端位移,记录了该副本底层日志中下一条消息的位移值,注意是下一条消息
集群的时候 server.properties ,不用配置listener了,添加host.name,port
6.1 分区分配策略
按照kafka默认的消费逻辑设定,一个分区只能被同一个消费组内的一个消费者消费,
7.存储结构
每一个partition(文件夹)相当于一个巨型文件被平均分配到多个大小相等segment数据文件里;
但每一个段Segment file消息数量不一定相等,这样的特性方便old segment file 高速被删除。默认情况下每一个文件大小为1g。
每一个partition仅仅需要支持顺序读写即可。segment文件生命周期由服务端配置参数决定。
segment file组成:index file 和 data file,此2个文件,一一对应,成对出现后,后缀.index和.log
7.1 日志索引
kafka解决查询效率的手段之一就是将数据文件分段,比如有100条message,它们的offest是从0到99,假设数据文件分成5段,第一段0-19,第二段20-39,依次类推,每段放在一个单独的数据文件里面,数据文件以该段中最小的offset命名。
总结:
零拷贝技术只用将磁盘文件的数据复制到页面缓存中,然后将数据从页面缓存直接发送到网络中,避免了重复复制数据
8.稳定性
8.1 幂等性
接口的多次调用所产生的结果和调用一次是一致的,生产者在进行重试的时候有肯能会重复写入消息,而kafka的幂等性功能就可以避免这种情况。
幂等性条件:只能保证Producer在单个会话内不丢不重,如果producer出现意外挂掉再重启是无法保证的。
幂等性不能跨多个partition,只能保证单个partition内的幂等性,当涉及多个topic-partition时,这中间的状态并没有同步。
Producer只需要把enable.idempotence()设置为true即可。默认就为true。
8.2 事务
需要定义transactionId;
producer.initTransaction();
producer.beginTransaction();
producer.commitTransaction();提交
producer.abortTransaction();回滚
8.3 控制器
kafka集群中会有一个或多个broker,其中有一个broker会被选举为控制器,它负责管理整个集群中所有分区和副本的状态。集群中仅有一个控制器
具备控制器身份的broker需要比其他普通的broker多一份职责,具体:
1.监听partition相关的变化
2.监听topic的变化
3.监听broker的变化
8.4 可靠性保证
kafka的保证:
1.保证分区消息的顺序
如果使用同一个生产者往同一个分区写入消息,而且消息B在消息A之后写入,那么kafka可以保证消息B的偏移量比消息A的偏移量大,而且消费者会先读取消息A 再读取消息B
2.只有消息被写入分区的所有副本时,才被认为是已提交
3.只要有一个副本是活跃的,那么已提交的消息就不会丢失;
4.消费者只能读取已经提交的消息。
9.消费组
9.1. 命令行工具
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list
9.2 数据管道connect
10.spring boot 整合kafka
pom: spring-kafka
application.yml: spring.kafka.producer.bootstrap-servers=127.0.0.1:9092
KafkaTemplate;
消费者@KafkaListener(id="",topic="",group="")
@Transaction(rollback=RuntimeException.class) 也支持kafka事务回滚