深入理解Kafka:核心设计与实践原理 pdf

深入理解Kafka:核心设计与实践原理

内容简介

本书从Kafka的基本概念入手,主要从生产端、消费端、服务端等3个方面进行全面的陈述,主要内容包括Kafka的基本使用方式、生产者客户端的使用、消费者客户端的使用、主题与分区、日志存储、深入原理解析、监控的设计、高级应用的扩展以及与Spark的集成等。虽然Kafka的内核使用Scala语言编写,但是本书基本以Java语言作为主要的示例语言,方便绝大多数读者的理解。本书虽然没有明确的界定,但是总体上可以隐性的划分为三个部分:基础篇、原理篇和扩展篇,以这种循序渐进的方式更能让读者容易接受。

作者简介

朱忠华 目前主要从事消息中间件相关的研发工作,对RabbitMQ、Kafka等有着自己独特的理解。

目录

第1章 初识Kafka
1.1 基本概念
1.2 安装与配置
1.3 生产与消费
1.4 服务端参数配置
1.5 总结
第2章 生产者
2.1 客户端开发
2.1.1 必要的参数配置
2.1.2 消息的发送
2.1.3 序列化
2.1.4 分区器
2.1.5 生产者拦截器
2.2 原理分析
2.2.1 整体架构
2.2.2 元数据的更新
2.3 重要的生产者参数
2.4 总结
第3章 消费者
3.1 消费者与消费组
3.2 客户端开发
3.2.1 必要的参数配置
3.2.2 订阅主题与分区
3.2.3 反序列化
3.2.4 消息消费
3.2.5 位移提交
3.2.6 控制或关闭消费
3.2.7 指定位移消费
3.2.8 再均衡
3.2.9 消费者拦截器
3.2.10 多线程实现
3.2.11 重要的消费者参数
3.3 总结
第4章 主题与分区
4.1 主题的管理
4.1.1 创建主题
4.1.2 分区副本的分配
4.1.3 查看主题
4.1.4 修改主题
4.1.5 配置管理
4.1.6 主题端参数
4.1.7 删除主题
4.2 初识KafkaAdminClient
4.2.1 基本使用
4.2.2 主题合法性验证
4.3 分区的管理
4.3.1 优先副本的选举
4.3.2 分区重分配
4.3.3 复制限流
4.3.4 修改副本因子
4.4 如何选择合适的分区数
4.4.1 性能测试工具
4.4.2 分区数越多吞吐量就越高吗
4.4.3 分区数的上限
4.4.4 考量因素
4.5 总结
第5章 日志存储
5.1 文件目录布局
5.2 日志格式的演变
5.2.1 v0版本
5.2.2 v1版本
5.2.3 消息压缩
5.2.4 变长字段
5.2.5 v2版本
5.3 日志索引
5.3.1 偏移量索引
5.3.2 时间戳索引
5.4 日志清理
5.4.1 日志删除
5.4.2 日志压缩
5.5 磁盘存储
5.5.1 页缓存
5.5.2 磁盘I/O流程
5.5.3 零拷贝
5.6 总结
第6章 深入服务端
6.1 协议设计
6.2 时间轮
6.3 延时操作
6.4 控制器
6.4.1 控制器的选举及异常恢复
6.4.2 优雅关闭
6.4.3 分区leader的选举
6.5 参数解密
6.5.1 broker.id
6.5.2 bootstrap.servers
6.5.3 服务端参数列表
6.6 总结
第7章 深入客户端
7.1 分区分配策略
7.1.1 RangeAssignor分配策略
7.1.2 RoundRobinAssignor分配策略
7.1.3 StickyAssignor分配策略
7.1.4 自定义分区分配策略
7.2 消费者协调器和组协调器
7.2.1 旧版消费者客户端的问题
7.2.2 再均衡的原理
7.3 __consumer_offsets剖析
7.4 事务
7.4.1 消息传输保障
7.4.2 幂等
7.4.3 事务
7.5 总结
第8章 可靠性探究
8.1 副本剖析
8.1.1 失效副本
8.1.2 ISR的伸缩
8.1.3 LEO与HW
8.1.4 Leader Epoch的介入
8.1.5 为什么不支持读写分离
8.2 日志同步机制
8.3 可靠性分析
8.4 总结
第9章 Kafka应用
9.1 命令行工具
9.1.1 消费组管理
9.1.2 消费位移管理
9.1.3 手动删除消息
9.2 Kafka Connect
9.2.1 独立模式
9.2.2 REST API
9.2.3 分布式模式
9.3 Kafka Mirror Maker
9.4 Kafka Streams
9.5 总结
第10章 Kafka监控
10.1 监控数据的来源
10.1.1 OneMinuteRate
10.1.2 获取监控指标
10.2 消费滞后
10.3 同步失效分区
10.4 监控指标说明
10.5 监控模块
10.6 总结
第11章 高级应用
11.1 过期时间(TTL)
11.2 延时队列
11.3 死信队列和重试队列
11.4 消息路由
11.5 消息轨迹
11.6 消息审计
11.7 消息代理
11.7.1 快速入门
11.7.2 REST API介绍及示例
11.7.3 服务端配置及部署
11.7.4 应用思考
11.8 消息中间件选型
11.8.1 各类消息中间件简述
11.8.2 选型要点概述
11.8.3 消息中间件选型误区探讨
11.9 总结
第12章 Kafka与Spark的集成
12.1 Spark的安装及简单应用
12.2 Spark编程模型
12.3 Spark的运行结构
12.4 Spark Streaming简介
12.5 Kafka与Spark Streaming的整合
12.6 Spark SQL
12.7 Structured Streaming
12.8 Kafka与Structured Streaming的整合
12.9 总结
附录A Kafka源码环境搭建

感悟与笔记

消费者与消费者组

消费者(Consumer)负责订阅Kafka中的主题(Topic),并且从订阅的主题上拉取(pull)消息。

    在Kafka的消费理念里面还有一层消费者组(Consumer Group)的概念。

    每个消费者对应一个消费者组,当消息发布到主题后,只会被投递给订阅他的每个消费者组中的一个消费者。

    一个主题可以被多个消费者组消费,多个消费者组之间互不影响。

    消费者的分区分配策略 可以通过消费者客户端参数partition.assignment.strategy 来设置。

    有关消费者分区分配的细节可以参考7.1节。

    消费者组是逻辑上的概念。每个消费组都会有固定的名称,消费者在消费前需要指定所属消费组的名称,
    
    可以通过消费者客户端参数 group.id 来配置,默认值为空宇符串。
    
    消费者不是逻辑上的概念,它是实际的应用实例,它可以是一个线程,也可以是一个进程。
    
    同一个消费组内的消费者既可以部署在同一台机器上,也可以部署在不同的机器上

客户端开发

一个正常的消费逻辑需要具备以下几个步骤:

         (1)配置消费者客户端参数 及 创建消费者实例

         (2)订阅主题

         (3)拉取消息并消费

         (4)提交消费位移

         (5)关闭消费者实例

消费者客户端代码示例

public class KafkaConsumerAnalysis {

         //配置之消费者客户端参数
         public static final String brokerList = "localhost:9092";
         public static final String topic = "topic-demo";
         public static final String groupid = "group.demo";
         public static final AtomicBoolean isRunning =new AtomicBoolean(true);
         
         public static Properties initConfig(){
             Properties props= new Properties();
             props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
             props.put(ConsumerConfig.VALUE DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
             props put(ConsumerConfig.GROUP_ID_CONFIG,groupid);
             props . put(ConsumerConfig.CLIENT_ID_CONFIG,"client.id.demo");
             return props;
         }


         public static void main (String [] args) {
             
             //获取配置
             Properties props =InitConfig()

             //创建消费者
             KafkaConsumer<String, String> consumer= new KafkaConsumer<>(props) ;
             
             //订阅主题
             consumer.subscribe(Arrays.asList(topic));

             try {

                 while(isRunning.get()){
                     //拉取消息
                     ConsumerRecords<String,String> records = consumer.poll(Duration.ofMillis (1000));
                     
                     for(ConsumerRecord<String, String> record : records) {
                         
                         System.out.println("topic = "+ record.topic() + " , partition =" + record. partition()
                                             + ",  offset =" + record . offset());
                         System.out.println(key = " + record.key()+ ", value =" + record.value ());
                         //实际开发中  根据需求 做对应逻辑操作 比如 消费消息 提交位移等等
                     }
                 }
             }catch (Exception e) {
                 log.error ("occur exception ", e);
             }finally {

                 //关闭消费者
                 consumer.close(); 
             }
         }
     }
Copyright © 2021-2022 知识猫. All Rights Reserved.