day04kafka

一. 复习

kafka使用分布式公平架构,主节点:kafka controllere (负责存储和管理) 从节点:kafka broker(负责存储)如果主节点挂掉,会依赖zk重新选举。
kafka的数据安全是依赖副本机制
leader和follwer是topic下的part的主节点和从节点,而controller和broker是集群的
在这里插入图片描述

二.topic管理:创建与列举、

/export/server/kafka_2.12-2.4.1/bin

  1. 创建:kafka-topics.sh --create --topic bigdata01 --partitions 3 --replication-factor 2 --bootstrap-server node1:9092,node2:9092,node3:9092(–topic topic名称, --partitions分区个数,–replication-factor副本,–bootstrap-server node1:9092,node2:9092,node3:9092 服务端地址进程端口9092)
  2. 列举:–list:kafka-topics.sh --list --bootstrap-server node1:9092,node2:9092,node3:9092
  3. 查看:–describe :kafka-topics.sh --describe --topic bigdata01 --bootstrap-server node1:9092,node2:9092,node3:9092
    在这里插入图片描述
  4. 删除:delete:kafka-topics.sh --delete --topic bigdata02 --bootstrap-server node1:9092,node2:9092,node3:9092
  5. 修改topic:–alter:kafka-topics.sh --alter --topic bigdata02 分区/副本/属性 --bootstrap-server node1:9092,node2:9092,node3:9092

三.生产者及消费者测试

  1. 命令行生产者: kafka-console-producer.sh --topic bigdata01 --broker-list node1:9092,node2:9092,node3:9092
  2. 命令行消费者: kafka-console-consumer.sh --topic bigdata01 --bootstrap-server node1:9092,node2:9092,node3:9092
    从头开始消费:kafka-console-consumer.sh --topic bigdata01 --bootstrap-server node1:9092,node2:9092,node3:9092 --from-beginning(默认从最新的位置开始消费,–from-beginning从最早的位置开始消费)
  3. 只要生产者不断生产,消费者就能实时的消费到topic中的数据

四.kafka集群压力测试

  1. 创建topic:bigdata :kafka-topics.sh --create --topic bigdata --partitions 2 --replication-factor 2 --bootstrap-server node1:9092,node2:9092,node3:9092

  2. 生产测试: kafka-producer-perf-test.sh --topic bigdata --num-records 100000 --throughput -1 --record-size 1000 --producer-props bootstrap.servers=node1:9092,node2:9092,node3:9092 acks=1

  3. 消费测试: kafka-consumer-perf-test.sh --topic bigdata --broker-list node1:9092,node2:9092,node3:9092 --fetch-size 1048576 --messages 100000

五.kafka API

  1. API分类
    1.1high level API:高级API,基于simpleAPI做了封装,让用户开发更加方便,但是由于封装了底层的API有很多东西不可控,无法控制数据安全;offset 自动存储zookeeper中,不需要自己管理。
    1.2simpleAPI:简单API。自定义控制所有的消费和生产,保障数据安全。
  2. 生产者API:生产数据到kafka
    2.1导入maven依赖:
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/
</url>
</repository>
</repositories>
<dependencies>
<!-- Kafka的依赖 -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.4.1</version>
</dependency>
</dependencies>

2.2 代码

package bigdata.hlzq.com.kafka.produce;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;

//生产者数据到kafka
public class KafkaProducerTestClient {
    public static void main(String[] args) {
        //构建连接
        //构建一个配置对象
        Properties props = new Properties();
        props.put("bootstrap.servers", "node1:9092,node2:9092,node3:9092");//服务端地址
        props.put("acks","all");//生产者写入网络部丢失的原因ack+重试机制:写入一条到kafka分区,kafka会返回一个ack确认,如果没有返回重新发送ack的值: 0不用等待 1:等待写入到lead就返回 all:等待所有副本
        //定义写入kafka的类型
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        //构建连接对象加载配置
        KafkaProducer<String,String> producer = new KafkaProducer<>(props);
        //实现操作
        for (int i=1;i<=100;i++){
            //调用连接对象的方法,指定topic key决定分区规则
            producer.send(new ProducerRecord("bigdata01",i+"",i+"itc"));
            //不给key在同一个分区
            producer.send(new ProducerRecord("bigdata01",i+"hh"));
            //指定分区
            producer.send(new ProducerRecord("bigdata01", 1,i+"",i+"itc"));
        }
        //释放连接
        producer.close();
    }
}
  1. 消费者
    代码:
import java.util.Properties;
import java.util.function.Consumer;

public class KafkaCons {
    public static void main(String[] args) {
        // 构建消费者连接
        //构建配置对象
        Properties props = new Properties();
        props.setProperty("bootstrap.servers", "node1:9092,node2:9092,node3:9092");
        props.setProperty("group.id", "test");
        props.setProperty("enable.auto.commit", "true");
        props.setProperty("auto.commit.interval.ms","1000");
        props.setProperty("key.deserializer" , "org.apache.kafka.common.serialization.StringDeserializer");
        props.setProperty("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
        KafkaConsumer <String ,String >consumer = new KafkaConsumer(props);
        // 订阅消费处理
        consumer.subscribe(Arrays.asList("bigdata01"));
        //消费者是不停的
        while (true){
            ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
            for (ConsumerRecord<String,String>record:records){
                System.out.println("offset:"+record.offset()+"   "+"topic:"+record.topic()+"  "+"part:"+record.partition()+"  "+"value:"+record.value());

            }
        }
    }
}

六. 生产分区规则

  1. 数据存储在那个分区的规则,
 //调用连接对象的方法,指定topic key决定分区规则
            producer.send(new ProducerRecord("bigdata01",i+"",i+"itc"));
            //不给key在同一个分区
            producer.send(new ProducerRecord("bigdata01",i+"hh"));
            //指定分区
            producer.send(new ProducerRecord("bigdata01", 1,i+"",i+"itc"));

在这里插入图片描述默认分区器defaultpartitioner
在这里插入图片描述如果指定了key:按照key的hash取余分区的个数,来写入对应的分区:只要key一样就会进入同一个分区,容易导致数据倾斜
黏性分区器:实现少批次多数据:一个批次的数据都存放在一个分区。(判断缓存中是否有这个topic的分区连接,如果有直接使用,没有随机写入一个分区,并放入缓存)
轮循分区:数据分配相对均衡,批次多,每个批次数据量少,性能差。(不用)

  1. 分区规则:先判断有没有指定分区,指定分区就写入指定的分区,调用分区器在判断有没有指定key如果有key按照key类似于hash取余的方式计算分区,没有的话使用黏性分区
  2. 自定义开发生产分区器
package bigdata.hlzq.com.kafka.userpart;

import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;

import java.util.Map;
import java.util.Random;

//自定义分区器
public class UserPartition implements Partitioner {
  /**
   * topic:topic名称
   * key:key
   * keybytes:key
   * value:value
   * valuebytes:value
   * cluster:集群配置对象
   * @renturn 分区编号
   * */
    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
       //获取topic的分区个数
        Integer integer = cluster.partitionCountForTopic(topic);
        //构建随机分区随机值
        Random random = new Random();
        int i = random.nextInt(integer);
        return i;
    }

    @Override
    public void close() {
    //释放资源连接
    }

    @Override
    public void configure(Map<String, ?> configs) {
     //获取配置
    }
}
在生产者代码中指定分区配置
 props.put("partitioner.class", "bigdata.hlzq.com.kafka.userpart.UserPartition");

七.消费者消费安全问题

  1. 第一次消费规则:有属性决定
    auto.offset.reset =latest | earliest |none
    latest:默认的值,从topic每个分区的最新的位置开始消费
    earliest:从最早的位置开始消费,每个分区的offset为0开始消费
    none:如果是第一次消费,这个属性为none,kafka会抛出异常,如果不是第一次消费这 不起作用
  2. 第二次消费:根据上一次消费的offset位置+1继续进行消费
  3. 消费者怎么知道上一次消费的位置:
    在自己内存中记录offset的值,下次直接请求上一次消费的位置;
    consumer offset:表示当前消费者组已经消费到的位置
    commit offset:表示下一次要消费的位置,=consumer offset+1
  4. 只有一个消费者,消费者故障,原来内存的offset没了,消费者怎么知道上一次的消费位置:
    数据重复和丢失,offset只放在内存,内存数据丢失offset丢失。
    将offset持久化并且共享。
    kafka将每个消费者消费的commit offset主动记录在一个topic中:_ _consumer_offsets,如果下次消费者没有给定请求的offset,kafka根据自己记录的offset来提供消费的位置。
    在这里插入图片描述
    在这里插入图片描述
  5. 自动提交的问题 :消费成功并处理成功提交,如果消费或者处理失败不提交
  6. 手动提交topic的offset:在这里插入图片描述offset是分区级别的,提交是按照topic级别的。按分区提交:
    消费级别:consumer.seek(offset)自定义数据的消费、consumer.subcribe(topic)普通的发布订阅、consumer.assign(parition)限制每个消费者消费分区
  7. 消费分配策略:一个消费者组消费的过程中,一个分区的数据只能有某一个消费者消费;一个消费者可以消费多个分区的数据。
    消费策略:范围分配:rangeassignor默认的分配策略 partition.assignment.strategy=org.apache.kafka.clients.consumer.RangeAssignor
    轮询分配:2.0之前 RoundRobinAssignor
    黏性分配:StickyAssignor2.0之后
    7.1默认分配rangeassignor:每个消费者消费一定的分区,尽量实现分区均分给不同的消费者,如果不能均分,优先分配给编号小的消费者(负载不均衡)
    在这里插入图片描述
    7.2 轮询分配:2.0之前 RoundRobinAssignor:按照topic的名称和分区编号排序,轮训分配给每个消费者
    在这里插入图片描述 轮训不均衡,以及上面的没有考虑消费者故障
    7.3 黏性分配:StickyAssignor2.0之后:类似于轮训分配,尽量的将分区均衡分配给消费者,如果某个消费者故障,尽量的避免网络传输
    在这里插入图片描述在这里插入图片描述如果消费者故障:其他的消费者重新分配所有分区
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
Kafka的rebalance是指在消费者组中发生变化时,重新分配分区给消费者的过程。当有新的消费者加入消费者组、有消费者离开消费者组、或者有消费者崩溃时,都会触发rebalance过程。 在rebalance过程中,消费者组协调器会根据一定的算法重新分配分区给消费者,以确保每个消费者都能平均分担分区的负载。通常情况下,rebalance过程会在一定的时间内完成。 然而,有一些情况可能导致rebalance失败或延迟。比如,如果消费者出现心跳超时,即消费者没有及时向协调器发送心跳信号,那么协调器可能会将该消费者标记为崩溃,并触发rebalance过程。同样,如果某个消费者的处理时间过长,也可能导致rebalance。 总的来说,kafka的rebalance是为了保证消费者组内的负载平衡,使每个消费者都能按照一定的规则获取到分区并进行消费。当消费者组发生变化时,rebalance过程会重新分配分区给消费者。但是在rebalance过程中,如果存在消费者崩溃或其他问题,可能会导致rebalance失败或延迟。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [kafka的rebalance](https://blog.csdn.net/day_ue/article/details/120982352)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值