2024年最新《Apache Kafka实战》笔记_apache kafka实战 下载(3),2024年最新讲的真详细

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

消息

Kafka的消息格式由很多字段组成,下面以V1版本消息格式为例,消息头部包括CRC码、消息版本号、属性、时间戳、键长度和消息体长度等信息。CRC循环冗余校验码、版本号比较常见,下面介绍一下其他字段:

  • 属性:8bit(1B即1byte,1B=8bit)的属性用于保存消息的压缩类型,压缩类型只用到了最低的三位,目前支持的4种压缩类型:0(无压缩),1(GZIP),2(Snappy)和3(LZ4)。
  • 时间戳(TimeStamp):消息发送时间戳,用于流式处理及其他依赖时间的处理语义,默认当前时间。
  • Key:消息键,对消息做partition时使用,即决定消息被保存在某topic下的哪个partition。
  • Value:消息体,保存实际的消息数据。

Kafka使用紧凑的二进制字节数组来保存上面的字段,如果要使用Java对象保存上面的消息格式,则如下,

public class Message {
    //循环冗余校验码
    private CRC32 crc;
    //版本号
    private short version;
    //编码类开关
    private boolean codecEnabled;
    //编码类序数
    private short codecClassOrdinal;
    //消息键,对消息做partition时使用,即决定消息被保存在某topic下的哪个partition
    private String key;
    //消息体,保存实际的消息数据
    private String value;
}

看CRC32源码中的crc是int类型占用4个字节,short类型占用2个字节,boolean类型占用1个字节(占用1个字节和占用4个字节取决于JVM),String看具体字符串内容,所以一个Message类的实例大概需要消耗40个字节左右,其中7字节只是为了补齐(原因是对象由8字节markword + 8字节或4字节classPointer+instance data+padding补充8的倍数字节)。并且,Java的操作系统通常默认开启了页缓存机制,也就是说保存的对象很有可能在页缓存中还保留一份,这造成了极大的资源浪费。因此Kafka在消息设计时避开了繁重的Java堆上内存分配,直接使用紧凑的二进制字节数组ByteBuffer而不是独立的对象,因此至少能够访问多一倍的可用内存。除此之外,当出现kafka broker进程崩溃时,页缓存的数据不会像堆内存上的数据消失。

基本概念

主题(topic):逻辑概念,代表一类消息,也可以认为是消息被发送到的地方。通常用topic区分实际业务,不同业务使用不同的topic。

分区(partition):kafka采用topic-partition-message的三级结构来分散负载,每个Kafka tpic都由若干个partition组成。

位移(offset):topic partition下的每条消息都被分配一个位移值。每条消息在某个partition的位移是固定的,但消息该partition的消费者的位移会随着消费进度不断前移。

副本(replica):partition是有序消息日志,分布式系统要实现高可靠性就的备份日志(replica)防止数据丢失。副本分两类:领导者副本(leader replica)和追随者副本(follower replica)。follower replica不负责响应客户端发来的消息写入和消费请求,它只是被动地向leader replica获取数据,而一旦leader replica所在的broker宕机,Kafka会从剩余的replica中选举出新的leader继续提供服务。

领导者(leader)和追随者(follower):与传统主备系统(Master-Slave,如Mysql)不同的是,Leader-Follower系统中通常只有leader对外提供服务,follower只是被动地追随leader的状态,保持与leader的同步。

ISR(in-sync replica):与leader replica保持同步的replica集合。Kafka为partition动态维护一个replica集合,该集合中的所有replica(含leader replica)保存的消息日志都与leader replica保持同步状态。只有这个集合中的replica才能被选举为leader,也只有该集合中所有replica都收到了同一条消息,Kafka才会将该消息置于“已提交”状态,即认为这条消息发送成功。Kafka对于没有提交成功的消息不做任何交付保证,它只保证在ISR存活的情况下”已提交“的消息不会丢失。

Kafka使用场景

  • 消息传输:替代传统的消息总线(message bus)或消息代理(message broker),解耦生产者和消费者以及批量处理消息。
  • 网站行为日志追踪:收集并分析用户的点击流数据。
  • 审计数据收集:对关键的操作和运维进行监控和审计。
  • 日志收集:对企业产生的服务日志进行全量收集,并集中送往下游的分布式存储中(比如HDFS(Hadoop Distributed File System)等)。
  • Event Sourcing:它是领域驱动设计(Domain-Driven Design,DDD)的名词,使用事件序列来表示状态变更。
  • 流式处理:比如Kafka社区推出的流式处理组件Kafka Streams。

Kafka Producer

Kafka生产者在经过几个版本的重写后,降低了系统的维护成本,它的整体工作流程如下图,它将用户待发送的信息封装成一个ProducerRecord对象,然后使用KafkaPrducer.send方法进行发送。KafkaProducer拿到消息后先对其进行序列化,然后结合本地缓存的元数据信息确立目标分区,最后写入内存缓冲区。

Producer的几个特点:

  • 发送过程被划分到两个不同的线程:用户主线程和Sender I/O线程,逻辑更易把控。
  • 完全是异步发送消息,并提供回调机制(callback)用于判断发送是否成功。
  • 分批机制(batching),每个批次中包括多个发送请求,提升整体吞吐量。
  • 合理的分区策略:对于没有指定key的消息旧版本的Producer策略是默认一段时间内将消息发送到固定分区,这容易造成消息倾斜(skewed)。新版本的Producer策略是采用轮询方式,消息发送更均匀化。
  • 底层使用基于Java Selector的网络客户端,结合Java的Future实现更加健壮和优化的声明周期管理。

Kafka Consumer

在旧版本的Consumer中,消费位移(offset)的保存与管理都是依托于Zookeeper来完成的,当数据量很大且消费频繁时,Zookeeper的读/写性能往往容易成为系统瓶颈。新版本的Zookeeper位移的管理和保存不再依赖Zookeeper。

Kafka Consumer的实现依赖中,比较重要的是KafkaConsumer.poll方法,它是实现消息消费的主要逻辑入口方法。新版本的Consumer摒弃旧版本多线程消费不同分区的思想,采用类似于Linux epoll的轮询机制,使得Consumer只使用一个线程就可以管理不同broker的多个Socket,既减少了线程间的开销成本,又简化了系统设计。

Consumer的几个特点:

  • 单线程设计——单个consumer线程可以管理多个分区的消费Socket连接,极大地简化了实现。
  • 位移提交与保存交由Kafka来处理——位移不再保存在Zookeeper中,而是单独保存在Kafka的内部topic中。
  • 消费者组的集中式管理——新版本的Consumer使用集中式协调者(coordinator)角色去管理整个消费者组(consumer group)的成员。

Kafka部署

kafka环境部署我们需要考虑多种因素,如操作系统、磁盘规划、容量规划、内存规划、带宽规划等。

操作系统选型

目前部署Kafka最多的3类操作系统分别是Linux、OS X 和 Windows,其中部署在Linux上的最多,Linux系统更加适合部署Kafka,主要是由于两个原因:I/O模型的使用和数据网络传输效率。

I/O模型主要的5种:阻塞I/O、非阻塞I/O、I/O多路复用、信号驱动I/O和异步I/O。如Socket的阻塞模式和非阻塞模式就是前面两种模型,Linux的select函数就属于I/O多路服用模型,Linux的epoll模型(使用回调机制替代轮询)则兼具第三第四种模型特性,Windows的IOCP(I/O Completion Port)属于第五种模型。

Kafka新版本clients在设计底层网络库时采用Java的Selector机制,其在Linux上的实现就是epoll模型;但在Windows平台上,Java NIO的Selector底层是使用select模型而非IOCP。所以在I/O模型上Linux部署Kafka要比Windows上部署Kafka更高效。

在数据网络传输效率上,Linux也更具优势。Kafka应用必然需要大量地通过网络与磁盘进行数据传输,大部分操作都是通过Java的FileChannel.transferTo方法实现。在Linux平台底层会调用sendfile系统调用,采用了Linux提供的零拷贝(Zero Copy)技术。

磁盘规划

确定磁盘时,是选择机械硬盘(HDD,Hard Disk Drive)还是固态硬盘(SSD,Solid State Drive)不那么重要,因为Kafka是顺序写磁盘,性能一点不弱,机械硬盘完全可以胜任。

部署搭建是选择简单驱动捆绑的磁盘(JBOD,Just Bunch Of Disks)还是使用专属的独立磁盘冗余阵列(RAID,Redundant Arrays Of Independent Disks)。虽然RAID优势更多,比如能提供冗余的数据存储空间、天然提供负载均衡,但其成本较高。JBOD方案成本较低,Kafka的开发鼻祖LinkedIn公司就准备计划将整个Kafka集群从RAID 10迁移到JBOD上,不过需要解决当前Kafka的一些固有缺陷,比如:

  • 任意磁盘损坏都会导致broker宕机——普通磁盘损坏概率大,社区改进为broker配置多块状态良好磁盘。
  • JBOD的管理需要更加细粒度化——Kafka未提供脚本或工具用于磁盘间分区。
  • JBOD需要提供类似于负载均衡的功能——目前依赖轮询的方式为新副本数据选择磁盘。

磁盘容量规划

根据不同的业务场景去规划磁盘大小。假设clients每天产生1亿条消息,每条消息大小为1KB,每条消息保存两份并保留一周。那么一天产生的消息占用磁盘空间=\frac{100000000\times 1KB\times 2}{1024\times 1024}\approx 190.7GB。最好再预留10%的磁盘空间用于其他数据文件(比如索引文件)的存储,这样大概在210GB左右。保存一周需要大概1.5TB的磁盘容量。若clients启用了消息压缩,那么整体磁盘容量大约在0.75TB(磁盘压缩比=0.5)。

因此磁盘容量的规划需要考虑的因素如下:

  • 新增消息数
  • 消息留存时间
  • 平均消息大小
  • 副本数
  • 是否启用压缩

内存规划

内存规划建议如下:

  • 尽量分配更多的内存给操作系统的页缓存(Page Cache)。
  • 不要为broker设置过大的堆内存,最好不超过6GB。
  • 页缓存大小至少要大于一个日志段的大小。

CPU规划

CPU规划建议如下:

  • 使用多核系统,CPU核数最好大于8。
  • 若使用Kafka 0.10.0.0之前的版本或clients端与broker端消息版本不一致(若无显式配置,通常是因为clients和broker版本不一致造成),则考虑多配置一些资源防止消息解压缩操作消耗过多CPU。

带宽规划

对于Kafka这种在网络间传输大量数据的分布式数据管道而言,带宽资源至关重要。在目前主流的网络环境下,带宽主要有千兆位网络(1Gb/s)和万兆位网络(10Gb/s)。无论哪种对于Kafka集群都足矣。

假设用户网络环境的带宽是1Gb/s,用户的业务目标是每天用1小时处理1TB的业务消息,这种情况下Kafka需要多少台机器?

考虑到机器上还有其他进程使用网络且网卡通常不能打满,超过一定阈值可能会出现网络丢包的情况,因此70%的设定是较合理的。Kafka单台broker的带宽就是1Gb/s\times 0.7\approx 710Mb/s,但但这是Kafka所使用的最高带宽,如果遇到突发流量很容易把网卡“打满”,所以还需要再截取\frac{1}{3},即大概240Mb/s。如果要1小时处理1TB的业务消息,即每秒处理\frac{1024\times1024MB}{3600s}=\frac{1024\times1024\times8Mb}{3600s}\approx 2330Mb/s的数据,那么至少需要接近10台broker,若副本数是2,则需要20台broker机器。

综上所述,对于网络带宽的规划建议是:

  • 尽量使用高速网络。
  • 根据自身网络条件和带宽来评估Kafka集群机器数量。
  • 避免使用跨机房网络。

Kafka实践

环境部署

  1. 安装Java。
  2. 安装zookeeper,在https://downloads.apache.org/zookeeper/stable/网站上下载并解压。修改好conf目录下配置文件zoo.cfg后,在bin目录下输入zkServer.sh start启动服务器,如下图表示启动成功。输入telnet localhost 2181命令连接zookeeper服务器,再使用srvr命令获取zookeeper服务器状态信息,如下图。zkServer.sh stop关闭服务器。
  3. 安装单节点Kafka集群。在http://kafka.apache.org/downloads下载kafka并解压。修改好config目录下的配置文件server.properties后,在kafka目录下输入bin/kafka-server-start.sh config/server.properties启动kafka broker(注意需要先启动zookeeper),如果想要在后台不挂断地运行,只需在命令前加上nohup(no hang up),如下图,显示started启动成功。

如果安装多节点Zookeeper集群,则最好使用奇数个服务器(2n+1),这样整个Zookeeper集群最多可以容忍n台服务器宕机而保证依然提供服务。如果使用偶数台服务器则通常会浪费一台服务器的资源。比如,使用5台Zookeeper服务器构建集群,如果2台服务器宕机,剩下的3台服务器占了半数以上,Zookeeper服务仍可以正常工作;假如使用4台服务器构建集群,若2台服务器宕机,剩下2台不满足“半数以上服务器存活”的条件,所以zookeeper不能正常工作。

创建kafka主题(topic)

首先弄清楚zookeeper服务器地址,我是用本机启动的zookeeper,所以本机地址即zookeeper服务器的地址,先看本机地址,如下,则zookeeper服务器地址为192.168.1.114。

输入命令sudo bin/kafka-topics.sh --create --zookeeper 192.168.1.114:2181 --replication-factor 1 --partitions 1 --topic test创建topic,其中192.168.1.114:2181是zookeeper服务器的IP+端口号(端口号在zookeeper服务器的conf目录下的zoo.cfg配置文件中配置的端口号)

输入命令bin/kafka-topics.sh -list -zookeeper 192.168.1.114:2181查看该zookeeper服务器下的topic。

参数说明:

replication-factor:用来设置主题的副本数。每个主题可以有多个副本,副本位于集群中不同的broker上,也就是说副本的数量不能超过broker的数量,否则创建主题时会失败。

partition:主题分区数。kafka通过分区策略,将不同的分区分配在一个集群中的broker上,一般会分散在不同的broker上,当只有一个broker时,所有的分区就只分配到该Broker上。

sudo:因为我的文件放在了系统的目录下,所以才需要以系统管理者的身份执行命令。

输入命令bin/kafka-topics.sh --zookeeper 192.168.1.114:2181 --describe --topic test查看该topic下的详细信息。

输入命令sudo bin/kafka-topics.sh --zookeeper 192.168.1.114:2181 --delete --topic test删除zookeeper上的topic,

删除topic下面会有条提示,如果不开启delete.topic.enable配置则topic不是真正意义上的删除,而是标志删除,也可以说是逻辑删除。

测试消息发送和消费

创建好了topic,我们可以使用Kafka默认提供的kafka-console-producer和kafka-console-consumer脚本来测试消息的发送和读取。打开两个终端,在第一个终端输入命令:

sudo bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test,其中的IP+端口号是broker服务器的IP地址和端口号,在启动kafka时可以在INFO信息里看到。输入上面的命令即创建好了发送者。

输入命令:sudo bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning创建好消费者,直接等待接收消息。

可以看到在生产者的终端输入信息后,消费者的终端就直接接收到了信息。这就完成了一个kafka的消息发送和接收测试。

参数配置

  • broker.id——Kafka broker的唯一标识,默认-1。
  • log.dirs——Kafka持久化消息目录(必须设置)。
  • zookeeper.connect——该参数可以是一个CSV(Comma-Separated Values)列表(必须设置)。比如zk1:2181,zk2:2181,zk3:2181。后面有chroot可选配置,不指定就是默认使用Zookeeper的根路径。
  • listeners——broker监听器的CSV列表,格式是[协议]😕/[主机名]:[端口],[协议]😕/[主机名]:[端口]。该参数用户客户端连接broker使用。
  • advertised.listeners——也是用于发布给clients的监听器,不过该参数主要用于IAAS环境,比如云上的机器通常都配有多块网卡(私有网卡和公有网卡)。
  • unclean.leader.election.enable——是否开启unclean leader选举。默认是false,即当leader宕机后,Kafka不允许从剩下存活的非ISR(In-Sync Replicas)副本中选择一个当leader。因为如果允许这样固然可以让Kafka继续提供服务给clients,但会造成消息数据的丢失。在一般业务场景下,数据不丢失是基本的业务需求,所以设置为false。
  • delete.topic.enable——是否允许Kafka删除topic,默认允许。前面也提到过,如果该标志不允许的话,删除topic就不是真实意义上的删除(marked for deletion)。
  • log.retention.{hours|minutes|ms}——这组参数控制了消息数据的留存时间。
  • log.retention.bytes——定义了空间维度上的留存策略。控制Kafka集群需要为每个消息日志保存多大的数据。
  • min.insync.replicas——该参数是与producer端的acks参数配合使用。acks=-1表示producer寻求最高等级的持久化保证,min.insync.replicas参数也只有acks=-1时才有意义。它指定了broker端必须成功响应clients消息发送的最少副本数。
  • num.network.threads——控制一个broker在后台用于处理网络请求的线程数,默认值是3。
  • num.io.thread——控制broker端实际处理网络请求的线程数,默认值是8。
  • message.max.bytes——Kafka broker能够接收的最大消息大小,默认是977KB。

还有其他的一些参数,broker端的参数有160+,上面只是一些比较重要的broker参数。真正使用时可能会遇到各种各样的问题,这里只是简单过一遍。

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

转存中…(img-pMLnvXD7-1715745371391)]
[外链图片转存中…(img-YaON9ba5-1715745371392)]
[外链图片转存中…(img-h6FiZoga-1715745371392)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值