kafka

310 阅读9分钟

一.kafka定义

  1. Kafka 是一个分布式消息系统:kafka构建集群

  2. Kafka就是一种发布-订阅模式:在发布-订阅消息系统中,消息被持久化到一个topic中,消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,数据被消费后不会立马删除。

与之对应的是点对点模式:在点对点消息系统中,消息持久化到一个队列中。此时,将有一个或多个消费者消费队列中的数据。但是一条消息只能被消费一次。当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除。该模式即使有多个消费者同时消费数据,也能保证数据处理的顺序。kafka采取了发布订阅模式

  1. kafka是依赖于zookeeper的. zookeeper中保存的集群的相关信息,同时也保存这消费者的消费位置信息,所以消费者挂了之后重新启动后,依旧可以在原来的位置上继续消费。

  2. 消费模式:拉模式 和推模式 kafka采用的是消费者拉模式。拉模式的缺点就是要一直维持一个长轮询,去询问队列中是否有新消息。

  3. kafka通过brokerId区分集群中的不同节点

kafka 结构

消费者组存在的意义是提高消费的能力 假如consumerA 所属于groupx 并且groupx目前只有者一个消费者,如果消费者A订阅了某个topic ,这个topic中假如有100条消息,需要消费者A处理100次,但是如果在同一个消费者组里面 还有consumerB,那么就会共同消费这个topic ,因为topic是分区的 ,所以同一个组的消费者会消费不同分区,并发执行,增强消费能力。因为一个partion只能被同一个消费者组的一个消费者实例消费

kafka中的基本概念

a.Topic(主题): Kafka 中可将消息分类,每一类的消息称为一个 Topic

b.Broker: :每个 Broker 即一个 Kafka 服务实例,多个 Broker 构成一个 Kafka 集群,生产者发布的消息将保存在 Broker 中,消费者将从 Broker 中拉取消息进行消费

c.Partition(分区): Partition 是 Kafka 中比较特色的部分,一个 Topic 可以分为多个 Partition,每个 Partition是一个有序的队列,Partition中的每条消息都存在一个有序的偏移量(Offest) ,同一个 Consumer Group 中,只有一个 Consumer 实例可消费某个 Partition 的消息

备份高可用性。消息以partition为单位分配到多个server,并以partition为单位进行备份。备份策略为:1个leader和N个followers,leader接受读写请求,followers被动复制leader。leader和followers会在集群中打散,保证partition高可用

d. leader : 每个partition有多个副本,其中有且仅有一个作为Leader,Leader是当前负责数据的读写的partition。

e.Follower: Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。如果Leader失效,则从Follower中选举出一个新的Leader

一个主题topic 可以有多个分区partion ,并且每个partion可以存在多个副本

f.消费者组 :多个消费者可以组成一个消费者组consumer group。一个partion只能被同一个消费者组的一个消费者实例消费。也就是说一个partion不能被同一个消费者组的多个实例消费。一个partion可以被不同的消费者组的消费者消费

kafka副本集:

我们的partion一般会分布在不同的broker上 针对每一个partion可以单独的设置副本集

leader 是在partition层面上的 因为一个partition会有多个副本集 但是只有一个是leader ,leader用于处理消息,follower主要用于备份。leader和follower为了数据安全就不会在同一个节点上

kafka拓扑结构

kafka ISR (in-sync replica)

上图topic名称:jiangzh-topic-cluster

该topic 只设置了一个partition

同时这个partition有三个副本因子,这三个副本有一个leader。

kafka集群也是每个broker单独启动的,kafka并没有提供启动整个集群的脚本 ,很明显在kafka的配置中我们并没有配置类似slave的节点,kafka启动的时候并知道集群的其他节点。 所以如果集群节点非常多,需要自己写启动脚本,shell脚本。

一个简单的shell脚本命令:启动hadoop102,hadoop103,hadoop104的kafka

常用命令 了解即可

1.查看所有topic: 因为集群相关信息都存在zookeeper上,所以要指定zookeeperer的地址

命令: bin/kafka-topics.sh --list --zookeeper 192.168.171.128:2181

2.创建topic

命令:bin/kafka-topics.sh --create --zookeeper 192.168.171.128:2181 --topic sunyjtopic --partitions 2 --replication-factor 2

创建topic同时指定分区数和副本因子

3.删除topic:

命令:bin/kafka-topics.sh --delete --zookeeper 192.168.171.128:2181 --topic sunyjtopic

4.topic详细信息:

命令:bin/kafka-topics.sh --describe --zookeeper 192.168.171.128:2181 --topic sunyjtopic

注意:创建副本数时不要超过集群的broker个数,否则报错,因为超过集群数必然会在某一个broker上有重复的,那么同一个broker上有相同的partition是没有意义的。

5.生产消息producer

命令:bin/kafka-console-producer.sh --broker-list 192.168.171.128:9092 --topic demo

6.消费消息 从头消费from beginning

命令:bin/kafka-console-consumer.sh --bootstrap-server 192.168.171.128:9092 --from-beginning --topic demo

kafka工作流程

生产者分区原则

kafka offset

kafka ISR

kafka ACK机制

kafka数据一致性保证 HW和LEO

kafka集群搭建

版本:kafka_2.11-0.11.0.0.tgz

步骤:修改配置文件:server.properties

cd /opt/install/kafka_2.11-0.11.0.0/config
vim server.properties
     
     ##The id of the broker. This must be set to a unique integer for each broker.
        broker.id=0

     ## Switch to enable topic deletion or not, default value is false 
        delete.topic.enable=true
        
      # A comma seperated list of directories under which to store log files
      log.dirs=/opt/install/kafka_2.11-0.11.0.0/data
      
      # The minimum age of a log file to be eligible for deletion due to age
     log.retention.hours=168
     
     # Zookeeper connection string (see zookeeper docs for details).
# This is a comma separated host:port pairs, each corresponding to a zk
# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
# You can also append an optional chroot string to the urls to specify the
# root directory for all kafka znodes.
  zookeeper.connect=sunyjhost:2181,sunyjhost2:2181,sunyjhost4:2181

分发配置:broker.id 不能重复 需要分发后重新修改

启动:注意kafka没有群起脚本,因为我们在配置文件中并没有发现 配置集群节点的配置,所以需要单独启动

./bin/kafka-server-start.sh -daemon config/server.properties 
使用jps查看启动状态

群启动脚本编写 chmod 777 kk.sh kk.sh start 启动

vim kk.sh


#!/bin/bash

case $1 in
"start"){

for i in sunyjhost sunyjhost2 sunyjhost4
do
   echo ***********$i*************
   ssh $i "/opt/install/kafka_2.11-0.11.0.0/bin/kafka-server-start.sh -daemon /opt/install/kafka_2.11-0.11.0.0/config/server.properties"
done
};;
"stop"){

for i in sunyjhost sunyjhost2 sunyjhost4
do
   echo ***********$i*************
   ssh $i "/opt/install/kafka_2.11-0.11.0.0/bin/kafka-server-stop.sh /opt/install/kafka_2.11-0.11.0.0/config/server.properties"
done
};;
esac

kafka 命令行操作 了解即可

主题相关

./bin/kafka-topics.sh --list --zookeeper sunyjhost:2181

创建topic的时候  指定的副本数 不能操作集群节点个数
./bin/kafka-topics.sh --create --zookeeper sunyjhost:2181 --topic sunyj --partitions 2 --replication-factor 2

./bin/kafka-topics.sh --delete --zookeeper sunyjhost:2181 --topic sunyj

生产者相关 ./bin/kafka-console-producer.sh --topic sunyj --broker-list sunyjhost:9092

消费者 ./bin/kafka-console-consumer.sh --bootstrap-server sunyjhost:9092 --topic sunyj

启动zk集群的脚本

kafka partion

分区主要是为了负载均衡,尽量的将消息轮询的发到不同的分区,

同时消费的时候,一起消费不同分区的消息,增加了消费的并发度

分区中的偏移量不是全局性的,只是分区内保证是有序的,也就是说分区0中有个22偏移量,分区1中也能有个22偏移量。但是在分区内部只能是一个22偏移量,偏移量可以理解为消息的id,

消费者保存的偏移量就是分区上数据的偏移量,记录消费的位置

官方文档原图

这个log文件就是存储数据的文件 kafka默认是 暂存7天 即168小时,同时这个文件如果超过了指定大小就会产生新的文件,大小应该是1个G

如上图,最终会有多个log文件,因为超过指定大小 就会产生新的log文件,每个log就叫segment

log只存数据 index存索引

查看index和log的命令

./bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files data/sunyj-1/00000000000000000000.index

./bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files data/sunyj-1/00000000000000000000.log

segment

LogSegment 可以减小日志文件的大小,进行日志删除的时候和数据查找的时候可以快速定位。同时,ActiveLogSegment 也就是活跃的日志分段拥有文件拥有写入权限,其余的 LogSegment 只有只读的权限。

.index叫偏移量索引文件

偏移量索引文件用于记录消息偏移量与物理地址之间的映射关系

Kafka 中的索引文件是以稀疏索引的方式构造消息的索引,他并不保证每一个消息在索引文件中都有对应的索引项。每当写入一定量的消息时,偏移量索引文件增加一个偏移量索引项,通过修改 log.index.interval.bytes 的值,改变索引项的密度

__consumer_offsets

在获取__consumer_offsets 信息之前需要设置consumer.properties中 exclude.internal.topics=false 因为__consumer_offsets 属于内置 topic , 当前消费者 每次消费过的数据不能在重复消费了,所以需要记录消费的偏移量,0.9版本之前消费的便宜量存在zk上,后面的新版本存在kafka集群内部

生产者分区策略

生产者发送消息的时候 可以直接指定分区号,将消息发送到指定分区,但是如果没有指定分区,因为我们的消息是kv格式的,如果指定了k,根据k的hash去模当前主题分区的个数,来决定这条消息发送到哪个分区 例如我们的主体有三个分区 那么和3取模 一定得到0,1,2 代表三个分区

保证数据不丢失ISR

ack

数据不丢失 Kafka的ack机制,指的是producer的消息发送确认机制,这直接影响到Kafka集群的吞吐量和消息可靠性。

而吞吐量和可靠性就像硬币的两面,两者不可兼得,只能平衡

HW LEO

exactly once

消费分区

一个消费者组有多个消费者,同时消费一个topic 并且这个topic含有多个分区 ,那势必会产生一个问题:这些分区如何分配给这些消费者

轮询策略 但是会吧所有的主体当成一个整体 再去轮询 而不是把一个主题中的所有分区轮询完,再去轮询另一个主题的分区

range策略

offset的维护

因为要记住消费的位置 group + topic +partition 来共同决定offset ,例如group a 的某个消费者消费的偏移量是10挂掉了,重新来一个消费者,这个消费者属于group a 那么他会从11接着消费,这样才能保障消费不重复,所以这个消费者要根据所属的组 查询到这个组已经消费这个partition的偏移量 ,拿到这个值后继续消费

kafka api

生产者API

异步发送