2024年最新《Apache Kafka实战》笔记_apache kafka实战 下载(3),2024京东最新Golang面试真题解析

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

吞吐量/延时

Kafka的设计主要是根据吞吐量和延时考虑,吞吐量即每秒能够处理的消息数或者每秒能够处理的字节数,延时可以表示为客户端发起请求与服务器处理请求并发送响应给客户端之间的时间。kafka之所以能够做到高吞吐、低延时是由于它对磁盘的使用方法不同。Kafka持久化所有数据到磁盘本质上是每次写入操作都只是把数据写入到操作系统的页缓存(page cache)中,然后由操作系统自行决定什么时候把页缓存中的数据回写到磁盘上。这样做的优势主要是:

  • 操作系统页缓存是在内存中分配的,所以消息写入速度快。
  • Kafka不必直接与底层的文件系统打交道。所有繁琐的I/O操作都交由操作系统来处理。
  • Kafka写入操作采用追加写入(append)的方式,避免了磁盘随机写操作。

普通SAS随机读/写的吞吐量很慢,但是磁盘的顺序读/写其实非常快,它的速度甚至可以匹配内存的随机I/O速度。鉴于这一特点,Kafka在设计时采用追加写入的方式。

同样,Kafka读取消息时会首先尝试从OS的页缓存中读取,如果命中便把消息经页缓存直接发送到网络的Socket上。这个过程就是利用Linux平台的sendfile系统调用完成的,也叫零拷贝(Zero Copy)技术。

在零拷贝技术出现之前,一个I/O操作会将同一份数据进行多次拷贝,如下图——无零拷贝数据传输,传输过程中涉及内核态和用户态的上下文切换,CPU的开销非常大,因此极大地限制了OS的数据传输能力。其中DMA拷贝也叫直接存储器访问技术(Direct Memory Access)拷贝。

零拷贝技术很好的改善了这个问题:在内核驱动程序处理I/O数据的时候,它不再需要进行上下文切换,节省了内核缓冲区与用户态应用程序缓冲区之间的数据拷贝,同时它利用直接存储器访问技术执行I/O操作,因此也避免了OS内核缓冲区之间的数据拷贝。如下图,其中transferTo方法是java.nio.channels.FileChannel接口的方法(Linux提供的sendfile系统调用)。

综上所述,Kafka就是依靠下面四点达到高吞吐量、低延时的设计目标。

  • 大量使用操作系统页缓存,内存操作速度快且命中率高。
  • Kafka不直接参与物理I/O操作,而是交由最擅长此事的操作系统来完成。
  • 采用追加写入方式(顺序读写),摒弃了缓存的磁盘随机读/写操作。
  • 使用以sendfile为代表的零拷贝技术加强网络间的数据传输效率。

消息持久化

Kafka消息持久化的好处是:

  • 解耦消息发送和消息消费。
  • 实现灵活的消息处理

负载均衡和故障转移

负载均衡(Load Balancing):让系统的负载根据一定的规则均衡地分配在所有参与工作的服务器上,从而最大限度地提升系统整体的运行效率。leader选举算法来实现。

故障转移(fail-over):当服务器意外中止时,整个集群可以快速地检测到该失效(failure),并立即将服务器上的应用或服务自动转移到其他服务器上。通常以“心跳”或“会话”的机制实现。

伸缩性

伸缩性(scalability)表示向分布式系统中增加额外的计算资源(比如CPU、内存、存储或带宽)时吞吐量提升的能力。举个例子,对于计算密集型(computation-intensive)的业务而言,CPU的消耗一定时最大的,这类系统上的操作我们称之为CPU-bound。那么如果一个CPU的运算能力是U,我们自然希望两个CPU的运算能力是2U,即可以线性地扩容计算能力,这种线性伸缩性是最理想的状态,但实际中几乎不可能达到,毕竟分布式系统中有很多隐藏的“单点”瓶颈制约了这种线性的计算能力扩容。阻碍线性扩容的一个很常见的因素就是状态的保存。Kafka服务器上的状态统一交由Zookeeper保存,这样整个集群的服务器之间就无须繁重的状态共享,极大地降低了维护复杂度。

Kafka架构

Kafka随着不断发展,把交由下游数据处理平台的事情自己做,演进成了流式处理组件。其架构图如下,Kafka服务器官方名称broker。

消息

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。

img
img
img

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

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

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

转存中…(img-xTX209b1-1715417403296)]
[外链图片转存中…(img-oNAhFYPY-1715417403296)]
[外链图片转存中…(img-L7hABh01-1715417403296)]

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

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

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

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值