Kafka 是 Linkedin 使用Scala 编写具有高水平扩展和高吞吐量的分布式消息系统。
kafka 对消息保存时根据 Topic 进行归类,发送消息者为 Producer,消息接收为 Consumer,此外Kafka 集群由多个Kafka实例组成,每个实例(Server)称为broker。
无论是 Kafka 集群,还是producer 和 consumer 都依赖于 zookeeper 来保证系统的可用性(新版Kafka不需要zookeeper了),zookeeper主要保存一些元数据(meta) 信息。
Kafka 的定位:
- 消息中间件
- 消息引擎
- 分布式实时流处理平台
Kafka使用场景:
- 大数据领域:日志聚合、网站行为分析、应用监控、流水数据处理等。
- 数据集成:将消息导入MaxCompute、OSS、Hadoop、HBase、RDS等离线数据仓库。
- 流计算集成:与StreamCompute、Spark、Storm等流计算引擎集成。
kafka集群部署
1、zookeeper 集群安装
分布式协调服务
1、下载,解压,复制zoo.cfg,修改zoo.cfg
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logs
2、复制zoo.cfg到另外两个节点上
3、分别在三个节点的/data/zookeeper/data 目录下创建myid文件,内容为:
server.1=ip1:8880:7770
server.2=ip2:8880:7770
server.3=ip3:8880:7770
第一个节点为 1,第二个节点为 2,第三个节点为 3。
4、启动
./bin/zkServer.sh start
5、确定启动是否正常
./bin/zkServer.sh status
2、kafka集群的安装
1、下载,解压
2、修改 server.properties 文件
broker.id=0
listeners=PLAINTEXT://ip1:9092
log.dirs=/data/kafka/kafka-logs
zookeeper.connect=192.168.18.22:2181,192.168.18.24:2181,192.168.18.27:2181
broker.id=1
listeners=PLAINTEXT://ip2:9092
log.dirs=/data/kafka/kafka-logs
zookeeper.connect=192.168.18.22:2181,192.168.18.24:2181,192.168.18.27:2181
broker.id=2
listeners=PLAINTEXT://ip3:9092
log.dirs=/data/kafka/kafka-logs
zookeeper.connect=192.168.18.22:2181,192.168.18.24:2181,192.168.18.27:2181
3、启动
./bin/kafka-server-start.sh config/server.properties &
4、创建topic(默认需要手动创建,可以修改配置文件让kafka自动创建不存在的topic)
创建一个名称为 test topic ,指定 test topic有一个分区,一个副本。
./bin/kafka-topics.sh --create --topic test --bootstrap-server ip1:9092 --partitions 1 --replication-factor 1
查看topic信息
./bin/kafka-topics.sh --describe --topic test --bootstrap-server ip1:9092
5、发送消息
用kafka自带的命名模拟消息发送
./bin/kafka-console-producer.sh --bootstrap-server ip1:9092 --topic test
6、消费消息
用kafka自带的命名模拟消息消费
./bin/kafka-console-consumer.sh --bootstrap-server ip1:9092 --topic test --from-beginning
Kafka原理
1、主要对象
- Message(消息):传递的数据对象,主要由四部分构成:offset(偏移量)、key、value、timestamp(插入时间); 其中offset和timestamp在kafka集群中产生,key/value在producer发送数据的时候产生
- Broker(代理者):Kafka集群中的机器/服务被成为broker, 是一个物理概念。
- Producer(生产者):负责将数据发送到Kafka对应Topic的进程
- Consumer(消费者):负责从对应Topic获取数据的进程。
- Consumer Group(消费者组):Consumer group 是 kafka 提供的可扩展且具有容错性的消费者机制。既然是一个组,那么组内必然可以有多个消费者或消费者实例(Consumer instance),它们共享一个公共的ID,即group ID。组内的所有消费者协调在一起来消费订阅主题(subscribed topics)的所有分区(partition)。当然,每个分区只能由同一个消费组内的一个consumer来消费。
- Topic(主题):Topic,数据主题,用于数据记录发布,可以用来区分业务系统。Kafka 中的 Topic 总是多订阅者模式,一个Topic可以拥有一个或多个消费者来订阅它的数据。
- Partition(分区):具体维护Kafka上的消息数据的最小单位,一个Topic可以包含多个分区;一个 Partition 可以设置为对应多个
Replication
(副本),即备份数据,具有容灾功能。(在数据的产生和消费过程中,不需要关注数据具体存储的Partition在那个Broker上,只需要指定Topic即可,由Kafka负责将数据和对应的Partition关联上)。每个分区都有一个 Leader,0 或 N 个 Follower。Leader 处理此分区的所有读写请求,Follower 被动的复制数据。如果 Leader 宕机,其他的 Follower会被选举出新的 Leader。 - Segment:partition物理上由多个segment组成,一个segment包含了.index、.log、.timeindex三个文件。默认当log文件大小达到1G后(通过配置文件指定log.segment.bytes=1,073,741,824)、index文件到达10MB后(通过配置文件指定log.index.size.max.bytes=1,048,576),会再次创建一个segment,以此内推。
2、Kafka四个核心API
- Producer API:允许一个应用程序发布一串流式的数据到一个或多个Kafka topic。
- Consumer API:允许一个应用程序订阅一个或多个Topic,并且对发布给他们的流式数据进行处理(PULL模式)。
- Streams API:允许一个应用程序作为一个流处理器,消费一个或多个Topic产生的输入流,然后生产一个输出流到一个或多个Topic中,在输入输出中进行有效的转换。
- Connector API:允许构建并运行可重用的生成者或者消费者,将Kafka topics连接到已存在的应用程序或者数据系统。比如,连接到一个关系型数据库,捕捉表(table)的所有变更内容。
3、Kafka基本架构
4、Product发送消息
5、kafka索引检索过程
- 根据 offset 判断在那个 segment 中
- 在 segment 的 index 文件中,根据 offset 找到消息的位置(position)
- 根据 position 从 log文件中比较,找到最终消息。
6、Kafka消息清理策略
开关:log.cleaner.enable=true
策略:log.cleanup.policy=delete-删除 / compact-压缩
周期:log.retention.check.interval.ms=300000(毫秒)
过期delete-删除定义(时间或文件大小):
- 时间:
- log.retention.hours=168(小时)
- log.retention.minutes
- log.retention.ms
- 文件大小:
- log.retention.bytes=-1(不限制)
- log.segment.bytes
compact-压缩:
7、高可用架构之Leader选举
Kafka 通过 Controller 来完成 Leader 的选举。
Controller :Controller 其实就是一个 Kafka 系统的 Broker。它除了具有一般 Broker 的功能之外,还具有选举主题分区 Leader 节点的功能。在启动Kafka系统时,其中一个 Broker 会被选举为控制器,负责管理主题分区和副本状态,还会执行分区重新分配的管理任务。
如果在 Kafka 系统运行过程中,当前的控制器出现故障导致不可用,那么 Kafka 系统会通过 zookeeper(向/constroller目录下创建临时节点,如果创建成功,则当前broker为Controller) 从其他正常运行的 Broker 中重新选举出新的控制器。
选举范围
Kafka在 Zookeeper 中为每一个 partition 动态的维护了一个 ISR,默认选 ISR 列表中顺序查找第一个存活的副本,如果 ISR 为空,unclean.leader.election.enable=true(默认为false),会从OSR中进行选举。
AR = ISR + OSR