kafka集群环境的安装
netstat -anp | grep 2181
注意:kafka集群依赖于zk集群,一定要保证zk集群的可用
验证zk集群是否可用:bin/zkServer.sh status 一定要保证出现一个leader,其他的都是follower即可
kafka集群环境搭建总结:
下载软件安装包并上传服务器
解压安装包然后修改配置文件
将安装包发送到其他服务器,并且修改其他服务器的配置文件
启动服务
Kafka集群操作
创建topic
bin/kafka-topics.sh --create --partitions 3 --replication-factor 2 --topic test --zookeeper node01:2181,node02:2181,node03:2181
查看topic
bin/kafka-topics.sh --list --zookeeper node01:2181,node02:2181,node03:2181
生产数据
bin/kafka-console-producer.sh --broker-list node01:9092,node02:9092,node03:9092 --topic test
消费数据
bin/kafka-console-consumer.sh --from-beginning --topic test --zookeeper node01:2181,node02:2181,node03:2181
查看topic的一些信息
bin/kafka-topics.sh --describe --topic test --zookeeper node01:2181
修改topic的配置属性
bin/kafka-topics.sh --zookeeper node01:2181 --alter --topic test --config flush.messages=1
删除topic
bin/kafka-topics.sh --zookeeper node01:2181 --delete --topic test
kafka集群当中JavaAPI操作
kafka集群当中ProducerAPI
public class MyProducer {
/**
* 实现生产数据到kafka test这个topic里面去
* @param args
*/
public static void main(String[] args) {
Properties props = new Properties();
props.put("bootstrap.servers", "node01:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("batch.size", 16384);
props.put("linger.ms", 1);
props.put("buffer.memory", 33554432);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
//获取kafakProducer这个类
KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(props);
//使用循环发送消息
for(int i =0;i<100;i++){
kafkaProducer.send(new ProducerRecord<String, String>("test","mymessage" + i));
}
//关闭生产者
kafkaProducer.close();
}
}
kafka集群当中的consumerAPI
消息的消费分为两种方式:
offset:offset记录了每个分区里面的消息消费到了哪一条,下一次来的时候,我们继续从上一次的记录接着消费
自动提交offset:
手动提交offset:
kafka的streamAPI
注意:如果程序启动的时候抛出异常,找不到文件夹的路径,需要我们手动的去创建文件夹的路径
kafkaAPI开发:
生产者API
消费者API:自动提交offset,手动提交offset。offset记录了我们数据的对应的long类型的数字
streamAPI:实现从一个topic里面获取数据,转换成为大写,写入到另外一个topic里面去
kafka的底层原理
生产者原理以及分区策略
生产者原理:主要就是研究如何将数据写入到kafka集群里面去,写入到某一个topic里面去之后,如何确定数据写入到哪一个分区里面去
一个topic里面有好多个分区,数据究竟写入到哪一个分区里面去???
生产数据三个必要的条件:
#1、地址
bootstrap.servers=node01:9092
#2、序列化 key.serializer=org.apache.kafka.common.serialization.StringSerializer value.serializer=org.apache.kafka.common.serialization.StringSerializer
#3、主题(topic) 需要制定具体的某个topic(order)即可。
默认的分区规则:
/**
* The default partitioning strategy:
* <ul>
* <li>If a partition is specified in the record, use it
* <li>If no partition is specified but a key is present choose a partition based on a hash of the key
* <li>If no partition or key is present choose a partition in a round-robin fashion
*/
总结:如果指定了数据的分区号,那么数据直接生产到对应的分区里面去
如果没有指定分区好,出现了数据key,通过key取hashCode来计算数据究竟该落在哪一个分区里面
如果既没有指定分区号,也没有指定数据的key,使用round-robin轮询 的这种机制来是实现
创建topic 3 个分区,两个副本
bin/kafka-topics.sh --create --partitions 3 --replication-factor 2 --topic mypartition --zookeeper node01:2181,node02:2181,node03:2181
kafka当中四种分区策略
//分区策略第一种,如果既没有指定分区号,也没有指定数据key,那么就会使用轮询的方式将数据均匀的发送到不同的分区里面去
//ProducerRecord<String, String> producerRecord1 = new ProducerRecord<>("mypartition", "mymessage" + i);
//kafkaProducer.send(producerRecord1);
//第二种分区策略 如果没有指定分区号,指定了数据key,通过key.hashCode % numPartitions来计算数据究竟会保存在哪一个分区里面
//注意:如果数据key,没有变化 key.hashCode % numPartitions = 固定值 所有的数据都会写入到某一个分区里面去
//ProducerRecord<String, String> producerRecord2 = new ProducerRecord<>("mypartition", "mykey", "mymessage" + i);
//kafkaProducer.send(producerRecord2);
//第三种分区策略:如果指定了分区号,那么就会将数据直接写入到对应的分区里面去
// ProducerRecord<String, String> producerRecord3 = new ProducerRecord<>("mypartition", 0, "mykey", "mymessage" + i);
// kafkaProducer.send(producerRecord3);
//第四种分区策略:自动以分区策略.如果不自定义分区规则,那么会将数据使用轮询的方式均匀的发送到各个分区里面去
//配置我们自定义分区类
props.put("partitioner.class","cn.itcast.kafka.partition.MyPartitioner");
kafkaProducer.send(new ProducerRecord<String, String>("mypartition","mymessage"+i));
消费者底层原理以及各种消费的过程
自动提交offset
手动提交offset
处理完每个分区里面的数据之后,然后就进行一次提交offset
手动指定某些分区里面的数据进行消费:例如:有一个topic mypartition,里面有三个分区 ,需求:只需要消费其中两个分区里面的数据
消费者API总结:自动提交offset,手动提交offset,处理完每个分区里面的数据就进行提交offset,通过指定消费topic当中某些分区的数据
kafka当中数据丢失以及数据重复消费
kafka当中数据消费模型:
eactly once:消费且仅仅消费一次,可以在事务里面执行kafka的操作
at most once:至多消费一次,数据丢失的问题
at least once :至少消费一次,数据重复消费的问题
kafka的消费模式:决定了offset值保存在哪里
kafka的highLevel API进行消费:将offset保存在zk当中,每次更新offset的时候,都需要连接zk
以及kafka的lowLevelAP进行消费:保存了消费的状态,其实就是保存了offset,将offset保存在kafka的一个默认的topic里面。kafka会自动的创建一个topic,保存所有其他topic里面的offset在哪里
kafka将数据全部都以文件的方式保存到了文件里面去了。
kafka的数据保存形式
kafka里面一个topic有多个partition组成,每一个partition里面有多个segment组成,每个segment都由两部分组成,分别是.log文件和.index文件 。一旦.log文件达到1GB的时候,就会生成一个新的segment
.log文件:顺序的保存了我们的写入的数据
.index文件:索引文件,使用索引文件,加快kafka数据的查找速度
总结:查找数据的过程
第一步:通过offset确定数据保存在哪一个segment里面了,
第二部:查找对应的segment里面的index文件 。index文件都是key/value对的。key表示数据在log文件里面的顺序是第几条。value记录了这一条数据在全局的标号。如果能够直接找到对应的offset直接去获取对应的数据即可
如果index文件里面没有存储offset,就会查找offset最近的那一个offset,例如查找offset为7的数据找不到,那么就会去查找offset为6对应的数据,找到之后,再取下一条数据就是offset为7的数据
kafka如何保证数据不丢失
生产者:使用ack机制
broker:使用partition的副本机制
消费者:使用offset来进行记录
主分区与副本分区之间的数据同步:
两个指标,一个是副本分区与主分区之间的心跳间隔,超过10S就认为副本分区已经宕机,会将副本分区从ISR当中移除
主分区与副本分区之间的数据同步延迟,默认数据差值是4000条
例如主分区有10000条数据,副本分区同步了3000条,差值是7000 > 4000条,也会将这个副本分区从ISR列表里面移除掉