分布式消息队列Kafka,收藏这篇文章就够了

分布式消息队列Kafka,收藏这篇文章就够了

一、kafka是什么?

MQ是一个消息中间件,可以在服务器之间进行通信。

常见的消息队列模式

  • 点对点Queue:一个消息只能被一个消费者接收
  • 发布与订阅Topic:一个消息可以被订阅了该主题的多个消费者接收

常见的消息队列产品

  • activeMQ,activeMQ可以做到事务的支持,为了数据的严谨性,业务系统一般选择activeMQ
  • rabbitMQ
  • zeroMQ
  • rocketMQ
  • kafka 只有订阅与发布

kafka是一个分布式消息队列中间件,跟传统的MQ相比,其具有高吞吐量,内部批处理的特点,主要作用是作为缓冲,来异构、结构系统。

为什么使用kafka

  • 缓存作用
  • 异步提供高吞吐
  • 解耦
  • 消息是可持久化的

kafka结构:

  • 生产者:发送消息到kafka
  • kafka集群:储存消息
  • 消费者:订阅主题,接收消息

在这里插入图片描述

二、分片与副本机制

分片机制:主要解决了单台服务器存储容量有限的问题

  • 当数据量非常大的时候,一个服务器存放不了,就将数据分成两个或者多个部分,存放在多台服务器上。每个服务器上的数据,叫做一个分片。

副本备份机制解决了数据存储的高可用问题

  • 当数据只保存一份的时候,有丢失的风险。为了更好的容错和容灾,将数据拷贝几份,保存到不同的机器上。

三、消息不丢失机制

1、生产者端消息不丢失

1) ack消息确认分为三个状态

  • 0:生产者只负责发送数据
  • 1:某个partition的leader收到数据给出响应
  • -1:某个partition的所有副本都收到数据后给出响应

2) 在同步模式下

  • ​ 生产者等待10S,如果broker没有给出ack响应,就认为失败。
  • 生产者重试3次,如果还没有响应,就报错。

3) 在异步模式下

  • 先将数据保存在生产者端的buffer中。Buffer大小是2万条。
  • 满足数据阈值或者数量阈值其中的一个条件就可以发送数据。
  • 发送一批数据的大小是500条。

如果broker迟迟不给ack,而buffer又满了。

开发者可以设置是否直接清空buffer中的数据。

2、broker

broker端的消息不丢失,其实就是用partition副本机制来保证。

Producer ack -1(all). 能够保证所有的副本都同步好了数据。其中一台机器挂了,并不影像数据的完整性。

3、消费者

消费者,有偏移量记录消费到哪里

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiY2D1nU-1634546421787)(F:\YoudaoNote\weicai2014@163.com\68bf98c0b70345dd9720261b016d9fb1\1544795493081.png)]

只要记录offset值,消费者端不会存在消息不丢失的可能。只会重复消费。

当Kafka中的偏移量与zookeeper中的偏移量不一致就会重复消费

四、文件存储与查询机制

文件存储机制:

在这里插入图片描述

segment段中有两个核心的文件一个是log,一个是index。 当log文件等于1G时,新的会写入到下一个segment中。

通过下图中的数据,可以看到一个segment段差不多会存储70万条数据
在这里插入图片描述

查询机制如下图:

  1. 查找segment file
  2. 通过segment file查找message

在这里插入图片描述

五、分发策略

分发就是消息发到哪里,哪个分片

kafka数据流向

Producer —> leader partition  —> follower partition(半数以上)  —> consumer
  1. 如果是用户指定了partition,生产就不会调用DefaultPartitioner.partition()方法

​ 数据分发策略的时候,可以指定数据发往哪个partition。

​ 当ProducerRecord 的构造参数中有partition的时候,就可以发送到对应partition上

public ProducerRecord(String topic, Integer partition, K key, V value) {
    this(topic, partition, null, key, value, null);
}
  1. 当用户指定key,使用hash算法,找出分片。

  2. 当用既没有指定partition也没有key。

    使用轮询的方式发送数据。

六、负载均衡

生产者生产消息太快了,一个消费者消费不了

点对点消费

消费者组里,消费者<=分片数

在这里插入图片描述

七、如何保证数据消费顺序一致性

首先需要明确的是:Kafka的主题是分区有序的,如果一个主题有多个分区,那么Kafka会按照key将其发送到对应的分区中,所以,对于给定的key,与其对应的record在分区内是有序的。

Kafka可以保证同一个分区里的消息是有序的,即生产者按照一定的顺序发送消息,Broker就会按照这个顺序将他们写入对应的分区中,同理,消费者也会按照这个顺序来消费他们。

在一些场景下,消息的顺序是非常重要的。比如,先存钱再取钱与先取钱再存钱是截然不同的两种结果。

参数max.in.flight.requests.per.connections,该参数的作用是在重试次数大于等于1时,保证数据写入的顺序。如果该参数不为1,那么当第一个批次写入失败时,第二个批次写入成功,Broker会重试写入第一个批次,如果此时第一个批次重试写入成功,那么这两个批次消息的顺序就反过来了。

一般来说,如果对消息的顺序有要求,那么在为了保障数据不丢失,需要先设置发送重试次数retries>0,同时需要把max.in.flight.requests.per.connections参数设为1,这样在生产者尝试发送第一批消息时,就不会有其他的消息发送给broker,虽然会影响吞吐量,但是可以保证消息的顺序。

除此之外,还可以使用单分区的Topic,但是会严重影响吞吐量。

八、Kafka的使用

常用命令

## 启动
bin/kafka-server-start.sh config/server.properties &

## 停止 
./kafka-server-stop.sh 

## 查看所有的topic
./kafka-topics.sh --list --zookeeper localhost:9092

## 查看所有topic的详细信息
./kafka-topics.sh --zookeeper localhost:2181 --describe

## 列出指定topic的详细信息
./kafka-topics.sh --zookeeper localhost:2181 --describe  --topic demo

## 删除一个topic
./kafka-topics.sh --zookeeper localhost:2181 --delete  --topic test

## 创建一个叫test的topic,有两个分区,每个分区3个副本
./kafka-topics.sh --zookeeper localhost:2181 --create --topic test --replication-factor 3 --partitions 2


## 测试kafka发送和接收消息(启动两个终端)
#发送消息(注意端口号为配置文件里面的端口号)
./kafka-console-producer.sh --broker-list localhost:9092 --topic test
#消费消息(可能端口号与配置文件保持一致,或与发送端口保持一致)
./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning   #加了--from-beginning 重头消费所有的消息
./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test         #不加--from-beginning 从最新的一条消息开始消费


## 查看某个topic对应的消息数量
./kafka-run-class.sh  kafka.tools.GetOffsetShell --broker-list localhost:9092 --topic test --time -1

## 显示所有消费者
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list

## 获取正在消费的topic(console-consumer-63307)的group的offset
./kafka-consumer-groups.sh --describe --group console-consumer-63307 --bootstrap-server localhost:9092

## 显示消费者
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list

## 为topic增加副本
./kafka-reassign-partitions.sh -zookeeper127.0.0.1:2181-reassignment-json-file json/partitions-to-move.json -execute
 
## 为topic增加partition
./bin/kafka-topics.sh –zookeeper127.0.0.1:2181–alter –partitions20–topic testaa

如何重平衡Kafka集群

在下面情况发生时,需要重平衡集群:

  • 主题分区在整个集群里的不均衡分布造成了集群负载的不均衡。
  • broker离线造成分区不同步。
  • 新加入的broker 需要从集群里获得负载。

使用kafka-reassign-partitions.sh命令进行重平衡

如何查看消费者组是否存在滞后消费

我们可以使用kafka-consumer-groups.sh命令进行查看,比如

$ bin/kafka-consumer-groups.sh --bootstrap-server cdh02:9092 --describe --group my-group
## 会显示下面的一些指标信息
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET   LAG          CONSUMER-ID HOST CLIENT-ID
主题   分区       当前offset      LEO           滞后消息数       消费者id     主机   客户端id

一般情况下,如果运行良好,CURRENT-OFFSET的值会与LOG-END-OFFSET的值非常接近。通过这个命令可以查 看哪个分区的消费出现了滞后。

九、其他面试题

1、如何确定Kafka主题的分区数量

选择合适的分区数量可以达到高度并行读写和负载均衡的目的,在分区上达到均衡负载是实现吞吐量的关键。需要根据每个分区的生产者和消费者的期望吞吐量进行估计。

一个简单的计算公式为:分区数 = max(生产者数量,消费者数量)

  • 生产者数量=整体生产吞吐量/每个生产者对单个分区的最大生产吞吐量
  • 消费者数量=整体消费吞吐量/每个消费者从单个分区消费的最大吞吐量

2、如何调整生产环境中Kafka主题的分区数量

当我们增加主题的分区数量时,会违背同一个key进行同一个分区的事实。我们可以创建一个新的主题,使得该主题有更多的分区数,然后暂停生产者,将旧的主题中的数据复制到新的主题中,然后将消费者和生产者切换到新的主题,操作起来会非常棘手。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大数据_苡~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值