• kafka知识点


    1、kafka三种能力

    1、数据的发布和订阅能力(消息队列

    2、数据的分布式存储能力(存储系统)

    3、数据的实时处理能力(流处理引擎)

    2、kafka消息模型

    Broker(代理): Kafka集群中,一个kafka实例被称为一个代理(Broker)节点。

    Producer(生产者): 消息的生产者被称为Producer。
    Producer将消息发送到集群指定的主题中存储,同时也自定义算法决定将消息记录发送到哪个分区。

    Consumer(消费者):
    消息的消费者,从kafka集群中指定的主题读取消息。

    Topic(主题):
    主题,kafka通过不同的主题区分不同的业务类型的消息记录。

    Partition(分区):
    每一个Topic可以有一个或者多个分区(Partition)。

    分区和代理节点的关系:
    一个分区只对应一个Broker,一个Broker可以管理多个分区。

    副本(Replication):
    每个主题在创建时会要求制定它的副本数(默认1)。

    记录(Record):
    实际写入到kafka集群并且可以被消费者读取的数据。
    每条记录包含一个键、值和时间戳。

    kafka将所有消息进行了持久化存储,由消费者自己各取所需,想取哪个消息,想什么时候取都行,只需要传递一个消息的offset即可。

    3、零拷贝

    零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文切换以及CPU的拷贝时间。它的作用是在数据报从网络设备到用户程序空间传递的过程中,减少数据拷贝次数,减少系统调用,实现CPU的零参与,彻底消除 CPU 在这方面的负载。
    实现零拷贝用到的最主要技术是DMA数据传输技术和内存区域映射技术。

    传统IO过程

     

    上下文切换:当用户程序向内核发起系统调用时,CPU将用户进程从用户态切换到内核态;当系统调用返回时,CPU 将用户进程从内核态切换回用户态。
    CPU拷贝:由CPU直接处理数据的传送,数据拷贝时会一直占用CPU的资源。
    DMA拷贝:由CPU向DMA磁盘控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给 CPU,从而减轻了CPU资源的占有率。

    (1)操作系统将数据从磁盘文件中读取到内核空间的页面缓存;
    (2)应用程序将数据从内核空间读入用户空间缓冲区;
    (3)应用程序将读到数据写回内核空间并放入socket缓冲区;
    (4)操作系统将数据从socket缓冲区复制到网卡接口,此时数据才能通过网络发送。

    mmap + write

    一种零拷贝方式是使用mmap + write代替原来的read + write方式,减少了 1 次CPU拷贝操作。mmap是 Linux 提供的一种内存映射文件方法,即将一个进程的地址空间中的一段虚拟地址映射到磁盘文件地址。

    使用 mmap 的目的是将内核中读缓冲区(read buffer)的地址与用户空间的缓冲区(user buffer)进行映射,从而实现内核缓冲区与应用程序内存的共享,省去了将数据从内核读缓冲区(read buffer)拷贝到用户缓冲区(user buffer)的过程,然而内核读缓冲区(read buffer)仍需将数据到内核写缓冲区(socket buffer),大致的流程如下图所示:

     

    基于mmap + write系统调用的零拷贝方式,整个拷贝过程会发生4次上下文切换,1次CPU拷贝和2次DMA拷贝,用户程序读写数据的流程如下:

    1、用户进程通过mmap() 函数向内核(kernel)发起系统调用,上下文从用户态(user space)切换为内核态(kernel space)。
    2、将用户进程的内核空间的读缓冲区(read buffer)与用户空间的缓存区(user buffer)进行内存地址映射。
    3、CPU利用DMA控制器将数据从主存或硬盘拷贝到内核空间(kernel space)的读缓冲区(read buffer)。 上下文从内核态(kernel space)切换回用户态(user space),mmap系统调用执行返回。
    4、用户进程通过 write() 函数向内核(kernel)发起系统调用,上下文从用户态(user space)切换为内核态(kernel space)。
    5、CPU将读缓冲区(read buffer)中的数据拷贝到的网络缓冲区(socket buffer)。
    6、CPU利用DMA控制器将数据从网络缓冲区(socket buffer)拷贝到网卡进行数据传输。
    7、上下文从内核态(kernel space)切换回用户态(user space),write 系统调用执行返回。

    mmap 主要的用处是提高 I/O 性能,特别是针对大文件。对于小文件,内存映射文件反而会导致碎片空间的浪费,因为内存映射总是要对齐页边界,最小单位是 4 KB,一个 5 KB 的文件将会映射占用 8 KB 内存,也就会浪费 3 KB 内存。

    sendfile

    通过 sendfile 系统调用,数据可以直接在内核空间内部进行 I/O 传输,从而省去了数据在用户空间和内核空间之间的来回拷贝。与 mmap 内存映射方式不同的是, sendfile 调用中 I/O 数据对用户空间是完全不可见的。也就是说,这是一次完全意义上的数据传输过程。

     

    基于 sendfile 系统调用的零拷贝方式,整个拷贝过程会发生 2 次上下文切换,1 次 CPU 拷贝和 2 次 DMA 拷贝,用户程序读写数据的流程如下:

    1、用户进程通过 sendfile() 函数向内核(kernel)发起系统调用,上下文从用户态(user space)切换为内核态(kernel space)。
    2、CPU 利用 DMA 控制器将数据从主存或硬盘拷贝到内核空间(kernel space)的读缓冲区(read buffer)。
    3、CPU 将读缓冲区(read buffer)中的数据拷贝到的网络缓冲区(socket buffer)。
    4、CPU 利用DMA控制器将数据从网络缓冲区(socket buffer)拷贝到网卡进行数据传输。
    5、上下文从内核态(kernel space)切换回用户态(user space),sendfile 系统调用执行返回。

    相比较于mmap内存映射的方式,sendfile少了 2 次上下文切换,但是仍然有 1 次 CPU 拷贝操作。sendfile 存在的问题是用户程序不能对数据进行修改,而只是单纯地完成了一次数据传输过程。

    RocketMQ 选择了mmap + write这种零拷贝方式,适用于业务级消息这种小块文件的数据持久化和传输;而 Kafka 采用的是sendfile这种零拷贝方式,适用于系统日志消息这种高吞吐量的大块文件的数据持久化和传输。但是值得注意的一点是,Kafka 的索引文件使用的是 mmap + write 方式,数据文件使用的是 sendfile 方式。

    4、Kafka 中的领导者副本(Leader Replica)和追随者副本 (Follower Replica)的区别

    副本当前分为领导者副本和追随者副本。只有Leader副本才能对外提供读写服务,响应Clients端的请求。Follower副本只是采用拉(PULL)的方式,被动地同步Leader副本中的数据,并且在Leader副本所在的Broker宕机后,随时准备竞选Leader副本。

    5、kafka为什么那么快?

    1、partition并行处理
    2、顺序写磁盘,充分利用磁盘特性
    3、利用了现代操作系统分页存储Page Cache来利用内存提高 I/O 效率
    4、采用了零拷贝技术
    5、Producer生产的数据持久化到broker,采用mmap文件映射,实现顺序的快速写入 Consumer从broker读取数据,采用sendfile,将磁盘文件读到OS内核缓冲区后,转到NIO buffer进行网络发送,减少CPU消耗
    6、批处理和数据压缩

    zhuanlan.zhihu.com/p/183808742

    6、kafka中consumer group是什么概念

    同样是逻辑上的概念,是Kafka实现单播和广播两种消息模型的手段。同一个topic的数据,会广播给不同的group;同一个group中的worker,只有一个worker能拿到这个数据。换句话说,对于同一个topic,每个group都可以拿到同样的所有数据,但是数据进入group后只能被其中的一个worker消费。group内的worker可以使用多线程或多进程来实现,也可以将进程分散在多台机器上,worker的数量通常不超过partition的数量,且二者最好保持整数倍关系,因为Kafka在设计时假定了一个partition只能被一个worker消费(同一group内)。

    7、Kafka中的消息是否会丢失和重复消费?

    要确定Kafka的消息是否丢失或重复,从两个方面分析入手:消息发送和消息消费。

    1、消息发送

    Kafka消息发送有两种方式:同步(sync)和异步(async),默认是同步方式,可通过producer.type属性进行配置。Kafka通过配置request.required.acks属性来确认消息的生产:

    0---表示不进行消息接收是否成功的确认; 1---表示当Leader接收成功时确认; -1(all)---表示Leader和Follower都接收成功时确认;
    综上所述,有6种消息生产的情况,下面分情况来分析消息丢失的场景:

    (1)acks=0,不和Kafka集群进行消息接收确认,则当网络异常、缓冲区满了等情况时,消息可能丢失;

    (2)acks=1,同步模式下,只有Leader确认接收成功后但挂掉了,副本没有同步,数据可能丢失;

    2、消息消费

    Kafka消息消费有两个consumer接口,Low-level API和High-level API:

    Low-level API:消费者自己维护offset等值,可以实现对Kafka的完全控制;

    High-level API:封装了对parition和offset的管理,使用简单;

    如果使用高级接口High-level API,可能存在一个问题就是当消息消费者从集群中把消息取出来、并提交了新的消息offset值后,还没来得及消费就挂掉了,那么下次再消费时之前没消费成功的消息就“诡异”的消失了;

    解决办法:

    针对消息丢失:同步模式下,确认机制设置为-1,即让消息写入Leader和Follower之后再确认消息发送成功;异步模式下,为防止缓冲区满,可以在配置文件设置不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态;
    针对消息重复:将消息的唯一标识保存到外部介质中,每次消费时判断是否处理过即可。

    8、为什么Kafka不支持读写分离?

    在 Kafka中,生产者写入消息、消费者读取消息的操作都是与 leader 副本进行交互的,从而实现的是一种主写主读的生产消费模型。

    Kafka 并不支持主写从读,因为主写从读有2个很明显的缺点:

    (1)数据一致性问题。数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间窗口会导致主从节点之间的数据不一致。某一时刻,在主节点和从节点中 A 数据的值都为 X, 之后将主节点中 A 的值修改为 Y,那么在这个变更通知到从节点之前,应用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不一致的问题。

    (2)延时问题。类似Redis这种组件,数据从写入主节点到同步至从节点中的过程需要经历网络→主节点内存→网络→从节点内存这几个阶段,整个过程会耗费一定的时间。而在Kafka中,主从同步会比Redis更加耗时,它需要经历网络→主节点内存→主节点磁盘→网络→从节点内存→从节点磁盘这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。

    读写分离适用于那种读负载很大,而写操作相对不频繁的场景,Kafka不属于这样的场景。

    作者:诚实可爱小郎君SK
    链接:https://juejin.cn/post/6962818405833375758
    来源:稀土掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    教你六步拆解 DDD领域驱动设计落地实践
    基于TensorFlow+CNN+协同过滤算法的智能电影推荐系统——深度学习算法应用(含微信小程序、ipynb工程源码)+MovieLens数据集(二)
    拔河攻略要点
    〖Python 数据库开发实战 - Redis篇③〗- Mac系统下通过homebrew安装Redis数据库
    docker容器内安装jupyter并远程开发--过程、遇到的问题和详解
    跨域配置代理 axios 请求封装
    【frp】cron定时检查zfrpc.service是否启动成功
    Netty实现udp发送消息给指定客户端
    分享今年接的几个私活项目
    【Linux操作系统】——安装VMware
  • 原文地址:https://blog.csdn.net/qq_32907195/article/details/127635894