Kafka简介和操作

Kafka简介和操作

消息引擎

消息引擎(消息中间件、消息队列):在消息传输过程中存储消息的容器
A —> 消息引擎 <---- B

消息引擎的好处

  • 解耦
  • 异步
  • 削峰填谷

消息引擎的设计

  • 消息协议

  • 消息模型

    • 点对点 A发送的消息只能是B获取

      kafka中点对点的实现:一个分区只能被消费者组中的一个消费者消费

    • 发布订阅 A发送的消息可以被多个用户获取

      kafka中发布订阅的实现:kafka的主题/分区可以 被多个消费者消费

为什么不使用flume作为消息引 擎

1、channel中的数据一旦被sink,数据就没有了。不能指定存储周期。
2、flume增加消费者(sink)很麻烦,增加sink就需要增加channel,修改配置文件。
3、flume不能指定数据消费位置
flume的职责就非常简单了,仅仅就是做数据采集。

Kafka简介

官网地址:http://kafka.apache.org/
kafka是一个分布式的消息引擎和流平台。Kafka主要应用在实时流中。

kafka的相关概念(非常重要)

  • broker:kafka集群中的每一个节点就是broker

    每个broker都有自己唯一的id号

  • controller: kafka集群也是主从结构的。主节点就是 controller。只是kafka的主节点不是配置的,而是选举的。

  • producer:生产者。就是往kafka分区写数据的

  • topic:主题。逻辑概念,就是对消息分类。

  • partition:分区。物理概念,数据存在磁盘上是按照 分区存储的。分区在磁盘上就是目录。目录的格式: topic-分区号;分区号从0开始的

  • replica:副本。kafka中的副本是在分区上的。

    leader副本:只能有一个,数据的读写经过leader

    follower副本:可以多个,同步leader副本的数据

    leader副本挂掉,follower副本可以成为leader副本

  • offset:分区偏移量。生产者往分区中写入的每一条 信息都有一个索引编号(从0开始)对应。这个索引编号就是分区偏移量。分区偏移量是一串值。

  • consumer:消费者。从kafka分区中获取数据。

  • cunsumer offset:消费者偏移量。消费者偏移量是 一个值,是一个动态值。 消费者偏移量 = 消费的最 后一条数据的分区偏移量 + 1;

  • consumer group:消费者组。kafka的消费是以消费者组为单位的。

    消费者偏移量是存在消费者组上的。

    一个分区只能被消费者组中的一个消费者消费

    一个消费者组中的消费者可以消费多个分区

  • group id:消费者组唯一id号。

在这里插入图片描述

Prodcucer的ACK应答机制

  • ack=0

    producer生产数据不需要等待leader和follower的确认。

    此时速度快,安全性低

    此时配置重试无效

    at most once

  • ack=1

    这将意味着leader将把记录写入本地日志,但将在不等待所有follower的完全确认的情况下进行响应。

    在这种情况下,如果leader在确认记录后立即失败,但follower还没有复制记录,那么记录就会丢失

    at most once

  • ack=-1/all

    这意味着leader将等待完整的同步副本来确认记录。

    这保证了只要至少有一个同步副本仍然存在,记录就不会丢失。

    这是最强有力的保证。这相当于acks=-1设置。

    at least once

producer的exactly once

要实现exactly once,应该生产端和消费端同时保证。生产者如何做到exactly once??
exactly once = at least once + 幂等性
kafka从0.11开始新增加了生产者的幂等性配置。
exactly once:

  • ack=-1

  • enable.idempotence = true

    以上的exactly once只能是单分区,单会话的精确一次。

已提交消息

消费者只能消费已提交的消息。
已提交:指的是生产者得到对应的ack成功应答的消息。

ISR

in sync replica

ISR是一个动态列表。leader天生就在ISR中。只有在ISR中的副本才有资格参与leader副本选举。

当follower副本同步leader副本数据时,落后了(replica.lag.time.max.ms =10000),follower副本就被踢出ISR。

无丢失消息的配置

1、不要使用 producer.send(msg),而要使用producer.send(msg, callback)。记住,一定要使用带有回调通知的 send 方法。
2、设置 acks = all。acks 是 Producer 的一个参数,代表了你对“已提交”消息的定义。如果设置成all,则表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。这是最高等级的“已提交”定义。
3、设置 retries 为一个较大的值。这里的retries 同样是 Producer 的参数,对应前面提到的 Producer 自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了 retries > 0 的Producer 能够自动重试消息发送,避免消息丢失。
4、设置 unclean.leader.election.enable =false。这是 Broker 端的参数,它控制的是哪些Broker 有资格竞选分区的Leader。如果一个Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。故一般都要将该参数设置成 false,即不允许这种情况的发生。
5、设置 replication.factor >= 3。这也是Broker 端的参数。其实这里想表述的是,最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余。
6、设置 min.insync.replicas > 1。这依然是Broker 端参数,控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于1 可以提升消息持久性。在实际环境中千万不要使用默认值 1。
7、确保 replication.factor >min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成replication.factor = min.insync.replicas+ 1。
8、确保消息消费完成再提交。Consumer 端有个参数enable.auto.commit,最好把它设置成 false,并采用手动提交位移的方式。

Producer的流程

在这里插入图片描述

删除Topic流程

在这里插入图片描述

kafka高吞吐量的原因

  1. 顺写磁盘
  2. 使用操作系统的pagecahce
  3. 使用了操作系统(sendfile)零拷贝技术(zerocopy)

在这里插入图片描述

在这里插入图片描述

kafka集群容量的规划

假设每天kafka的数据量是1亿条(每条数据大小2kb),现在需要设计多大的集群容量呢?
考虑因素:

  • 单条数据大小
  • 数据量大小
  • 副本数
  • 保存周期
  • 压缩

2 * 100000000 = 200000000KB

一天的数据大小:200GB ;需要预留10-20%的空间给索引文件

200G + 40G = 240G

kafka会对数据进行压缩的,压缩比75%左右

240G * 75% = 180G

3个副本的数据:180G

7天的总和 :180G * 7 = 1260G

3个副本: 1260G * 3 = 3780G

kafka副本同步

HW和LEO

在这里插入图片描述

HW和LEO的更新时机

在这里插入图片描述

副本正常同步过程

在这里插入图片描述

注意:副本同步可能会出现问题,当leader向follower发送hw时,如果follower挂了,follower的hw还是为0,重启follower后,leader又挂了,这时leader再重启就会成为follower,会向此时的leader同步数据,数据就会出现问题,因为hw会从1又变回0.

在这里插入图片描述

kafka将数据和日志分开

只需要将log.dirs的目录名不要写成logs,在server.properties配置文件里设置

kafka输出日志的目录就是固定logs

log.dirs=/home/hadoop/apps/kafka/logs

kafka的相关操作

启动kafka

kafka没有提供群启命令。需要自己写群启脚本

[hadoop@hadoop101 bin]$ kafka-server-start.sh
USAGE: /home/hadoop/apps/kafka/bin/kafkaserver-start.sh [-daemon] server.properties 
[--overrideproperty=value]*
[hadoop@hadoop101 bin]$ kafka-server-start.sh -daemon ../config/server.properties

kafka集群群启动(关闭)脚本

kafka.sh

#! /bin/bash
# kafka集群群启动(关闭)脚本

##获取当前的用户名
USERNAME=$(whoami)

case $1 in
"start"){
        for HOST in `cat /home/hadoop/script/nodes`
        do
                echo "Starting kafka on $HOST ..." 
				ssh $USERNAME@$HOST "source /etc/profile;/home/hadoop/apps/kafka/bin/kafka-server-start.sh -daemon /home/hadoop/apps/kafka/config/server.properties"
        done
};;
"stop"){
        for HOST in `cat /home/hadoop/script/nodes`
        do
                echo "Shutdown kafka on $HOST ..." 
				ssh $USERNAME@$HOST "source /etc/profile;/home/hadoop/apps/kafka/bin/kafka-server-stop.sh"
        done
};;
esac

创建topic

[hadoop@hadoop101 bin]$ kafka-topics.sh
Create, delete, describe, or change a topic.
[hadoop@hadoop101 bin]$ kafka-topics.sh --create --topic goods --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka --partitions 2 --replicationfactor 3 

Created topic "goods".

删除topic

[hadoop@hadoop101 config]$ kafka-topics.sh --delete --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka --topic goods

查看topic描述信息

[hadoop@hadoop101 config]$ kafka-topics.sh --zookeeper hadoop101:2181,hadoop102:2181/kafka --topic goods 
--describe

更改topic的分区数

[hadoop@hadoop101 logs]$ kafka-topics.sh --zookeeper hadoop101:2181,hadoop102:2181/kafka --topic goods 
--alter --partitions 3

生产数据

kafka提供了生产者的模拟客户端。

[hadoop@hadoop101 bin]$ kafka-console-producer.sh --topic goods --broker-list hadoop101:9092,hadoop102:9092,hadoop103:9092

消费数据

kafka提供了消费者的模拟客户端。

[hadoop@hadoop102 goods-1]$ kafka-console-consumer.sh --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka --topic goods --from-beginning
[hadoop@hadoop102 goods-1]$ kafka-console-consumer.sh --bootstrap-server hadoop101:9092,hadoop102:9092,hadoop103:9092 --topic goods

##__consumer_offsets-分区号:50个分区 将offset偏移量存储在kafka自身
## 使用消费者gid.hashCode % 50 得到的就是__consumer_offsets主题的分区号

注意:
offset存储在zk的好处和弊端:

  1. 好处:方便监控
  2. 弊端:zk不适合大批量的频繁写入数据

kafka存储offset是存在__consumer_offsets主题中的。kafka中分区的数据默认保留7天。所以offset可能出现过期,此时可以借助外部数据库存储offset,推荐使用redis。

offset在zk上的路径

/kafka/consumers/消费者组/offsets/主题/分区

查看log数据文件和index索引文件

[hadoop@hadoop101 infos-0]$ kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log
[hadoop@hadoop101 infos-0]$ kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.index
## 查看数据详细信息
[hadoop@hadoop102 goods-0]$ kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log --deep-iteration --print-data-log

## 索引项<相对偏移量,position>
## 索引项占据大小 8字节 ,相对偏移量占4字节(int),position占4个字节
## 但是 kafka中的offset是长整型long。long类型8字节
offset: 17 position: 5233
offset: 25 position: 9664
offset: 33 position: 14035
offset: 41 position: 18987
offset: 51 position: 23374
offset: 62 position: 27769

00000000000000000000.log – offset 0 – basicOffset-- 基准偏移量

00000000000000000000.index 相对偏移量 == offset - 基准偏移量

00000000000000000100.log – offset 100 --basicOffset – 基准偏移量

00000000000000000100.index offset: 17 position: 52330

Log数据分段的触发条件

  1. 分段日志的大小达到1G
  2. 索引文件达到10M
  3. 分段日志中消息的最大时间戳达到7天
  4. 当前消息的offset - 基准offset > Integer.MAX_VALUE

kafka的数据文件

在这里插入图片描述

kafka消息传递的三种语义

  • at least once(至少一次语义):消息至少消费一次,数据不丢失,但是数据可能重复
  • at most once(最多一次语义):消息最多消费一次,数据不重复,但是数据可能丢失
  • exactly once(精确一次语义):数据不重复不丢失。— 很难做到。

要实现exactly once,就需要实现幂等性( Idempotent ):无论执行多少次,最终结果 一样。

注意:at least once + 幂等性 可以实现精确一次,但只是保证单分区,多分区之间数据依然可能会重复。

如何根据offset查找信息

假如现在index文件的数据如下:

offset: 17 position: 5233
offset: 25 position: 9664
offset: 33 position: 14035
offset: 41 position: 18987
offset: 51 position: 23374
offset: 62 position: 27769

现在要查找offset=21的消息,如何查找??

1、根据offset的值是21,可以定位到索引文件是00000000000000000000.index

2、使用offset的值减去对应的基准偏移量(21- 0)

3、使用二分查找在00000000000000000000.index文件中找到小于21的最大值,这里就是17

4、根据17对应的物理位置5233,在00000000000000000000.log中定位都该数据,然后按照顺序向后查找到21对应的数据。

指定分区进行消费

[hadoop@hadoop102 ~]$ kafka-console-consumer.sh --bootstrap-server hadoop101:9092,hadoop102:9092,hadoop103:9092 --topic goods --partition 0

kafka的消息是分区内有序,全局是的顺序是kafka无法保证的。

指定offset消费数据

[hadoop@hadoop102 ~]$ kafka-console-consumer.sh --bootstrap-server hadoop101:9092,hadoop102:9092,hadoop103:9092 --topic goods --partition 0 --offset 3

消费者组

## 修改消费者组
[hadoop@hadoop102 config]$ vim consumer.properties
bootstrap.servers=hadoop102:9092
# consumer group id
group.id=test

## 使用消费者组,不能带上分区,kafka存储offset
[hadoop@hadoop103 config]$ kafka-console-consumer.sh --bootstrap-server hadoop101:9092,hadoop102:9092,hadoop103:9092 --topic goods --consumer.config consumer.properties

## 使用zk存储offset
[hadoop@hadoop103 config]$ kafka-console-consumer.sh --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka --topic goods --consumer.config consumer.properties

查看log数据

[hadoop@hadoop101 infos-0]$ kafka-runclass.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log --printdata-log --deep-iteration

查看offset

## 查看kafka自身的offset
[hadoop@hadoop101 bin]$ kafka-consumer-groups.sh --bootstrap-server hadoop101:9092,hadoop102:9092,hadoop103:9092 --group test --describe

## 查看zk上的offset
[hadoop@hadoop101 bin]$ kafka-consumer-groups.sh --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka --group test --describe

查看消费者组

## 查看kafka自身的消费者组
[hadoop@hadoop101 bin]$ kafka-consumer-groups.sh --bootstrap-server hadoop101:9092,hadoop102:9092,hadoop103:9092 --list

## 查看zk的消费者组
[hadoop@hadoop101 bin]$ kafka-consumer-groups.sh --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka --list

分区副本平衡

[hadoop@hadoop101 bin]$ kafka-preferred-replica-election.sh --zookeeper hadoop101:2181,hadoop102:2181,hadoop103:2181/kafka
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值