Kafka生产者分区写入规则和副本机制

生产者分区写入规则

概述

生产者写入消息到topic,Kafka将依据不同的规则将数据分配到不同的分区中,如果指定了分区数据就会写到指定分区,如果没有指定分区,会按照下列若干规则进行指定分区:

分类

Hash分区(指定Key默认开启)
在这里插入图片描述

优点:相同的key会进去同一分区
缺点:由于相同key的Hash取余结果是相同的,会导致数据倾斜问题

轮询分区(没有指定Key时开启)

在这里插入图片描述

  • 默认的策略,也是使用最多的策略,可以最大限度保证所有消息平均分配到一个分区
  • 如果在生产消息时,key为null,则使用轮询算法均衡地分配分区

优点:数据分配更加均匀

缺点:相同key的数据进去不同的分区

  1. Kafka生产者写入数据之前:先将数据写入缓存中,与分区构建一个连接,发送一个批次的数据
  2. 第一条数据:先构建0分区的连接,第二条不是0分区的,所以直接构建一个批次,发送第一条
  3. 第二条数据:先构建1分区的连接,第三条不是1分区的,所以直接构建一个批次,发送第二条
  4. ……
  5. 每条数据需要构建一个批次,9条数据,9个批次,每个批次一条数据
  6. 批次多,每个批次数据量少,性能比较差
    优化缺点:增加每个批次的数据量,从而介绍批次数,这样性能较好,于是就有了黏性分区

在2.x之前:轮询分区,2.x之后:由于轮询分区性能太差,使用黏性分区

黏性分区(在2.X之后,数据没有key的默认分区规则)
设计:让数据尽量的更加均衡,实现少批次多数据
规则:

  1. 第一次:将所有数据随机选择一个分区,全部写入这个分区中,将这次的分区编号放入缓存中
  2. 第二次开始根据缓存中是否有上一次的编号

有:直接使用上一次的编号
如果没有:重新随机选择一个

随机分区(不用)

随机策略,每次都随机地将消息分配到每个分区。在较早的版本,默认的分区策略就是随机策略,也是为了将消息均衡地写入到每个分区。但后续轮询策略表现更佳,所以基本上很少会使用随机策略。

自定义分区
在这里插入图片描述
实现代码:
1.创建自定义分区器

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

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

/**
 * @ClassName UserPartition
 * @Description TODO 自定义分区器,实现随机分区
 * @Date 2021/3/31 9:21
 * @Create By     Frank
 */
public class UserPartition implements Partitioner {

    /**
     * 返回这条数据对应的分区编号
     * @param topic:Topic的名
     * @param key:key的值
     * @param keyBytes:key的字节
     * @param value:value的值
     * @param valueBytes:value的字节
     * @param cluster:集群对象
     * @return
     */
    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
        //获取Topic的分区数
        Integer count = cluster.partitionCountForTopic(topic);
        //构建一个随机对象
        Random random = new Random();
        //随机得到一个分区编号
        int part = random.nextInt(count);
        return part;
    }

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

    @Override
    public void configure(Map<String, ?> configs) {
        //获取配置
    }
}

2.在Kafka生产者配置中,自定使用自定义分区器的类名
props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, 类所在包路径.UserPartition.class);

副本机制(保证数据安全)

概述

副本就是给数据做备份,当Kafka集群中的某个broker的数据(分区)丢失或者宕机,在其他broker中的副本是可用的

  • 为了保证安全和写的性能:划分了副本角色
  • leader副本:对外提供读写数据
  • follower副本:与Leader同步数据,如果leader故障,选举一个新的leader

查看某个topic的副本情况
bin/kafka-topics.sh --zookeeper 主机名:2181 --describe --topic 主题名

Topic: test     PartitionCount: 1       ReplicationFactor: 1    Configs: 
        Topic: test     Partition: 0    Leader: 2       Replicas: 2     Isr: 2

Kafka分区副本概念:AR、ISR、OSR

  1. AR:All - Replicas
  • 所有副本:指的是一个分区在所有节点上的所有副本
0分区有1个副本在第三台机器上
Partition: 0    Leader: 2       Replicas: 2
  1. ISR:In - Sync - Replicas
  • 可用副本:Leader与所有正在与Leader同步的Follower副本
Partition: 0    Leader: 2       Replicas: 2     Isr: 2
  • 列表中:按照优先级排列【Controller根据副本同步状态以及Broker健康状态】,越靠前越会成为leader.
  1. Out - Sync - Replicas
  • 不可用副本:与Leader副本的同步差距很大,成为一个OSR列表的不可用副本
  • 原因:网路故障等外部环境因素,某个副本与Leader副本的数据差异性很大
  • 判断是否是一个OSR副本?

0.9之前:时间和数据差异
replica.lag.time.max.ms = 10000 可用副本的同步超时时间
replica.lag.max.messages = 4000 可用副本的同步记录差,该参数在0.9以后被删除
0.9以后:只按照时间来判断
replica.lag.time.max.ms = 10000 可用副本的同步超时时间

producer的ACKS参数

ACKS参数表示生产者生产消息,对写入副本的要求严格程度,不同的ACKS参数性能不同,安全性也不同

参数分类

acks配置为0:
在这里插入图片描述
acks=0:生产者不管kafka集群有没有收到,直接发送下一条消息
优缺点:

优点:性能好,就是快
缺点:容易导致数据丢失,概率比较高

acks配置为1:
在这里插入图片描述
acks=1:生产者将数据发送给Kafka,Kafka等待这个分区leader副本写入成功,返回ack确认,生产者发送下一条
优缺点:

优点:性能和安全上做了平衡
缺点:依旧存在数据丢失的概率,但概率比较小

acks配置为-1或者all
在这里插入图片描述
acks=all/-1:生产者将数据发送给Kafka,Kafka等待这个分区所有副本全部写入,返回ack确认,生产者发送下一条
优缺点:

优点:数据安全
缺点:慢

补充:如果Kafka没有返回acks怎么办?

  • 生产者会等待Kafka集群返回ACKS,所有会有一个等待时间,如果Kafka在规定的时候内没有返回ACKS,代表数据丢失
  • 生产者有重试机制,重新发送这条数据给Kafka

存在的问题:acks每次在Kafka集群数据写入成功时返回,如果在返回的过程中Kafka宕机,就会导致数据重复,如何解决?

点击链接了解Kafka如何解决这一问题

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据老人家i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值