一、原理简述


【1】Producer将消息进行分组分别发送到对应 Leader节点;
【2】Leader将消息写入本地 log;
【3】Followers从 Leader pull最新消息,写入 log后向 Leader发送 ack确认;
【4】Leader收到所有 ISR中的 Follower节点的 ACK后,增加 HW,标记消息已确认全部备份完成,最后返回给 Producer 消息已提交成功;
【5】消费端从对应 Leader 节点 poll最新消息并消费,消费完成后将最新的 offset位置提交至 Topic为 _consumer_offsets的主节点中保存。

二、Producer 原理


初始化 KafkaProducer,会创建一个后台线程 KafkaThread,会循环的判断缓存中的数据是否需要提交。同时会发送消息,主要指定 Topic和 Value,不建议指定 partition和 key防止分区分配的不均匀,扩容不方便等。然后拉取 metadata 它是在 zk中维护的,里面存储了 topic 可用的分区和正在同步的备份。分区器由两种分区策略,第一种是根据 key的 hash值,将相同的 key放在同一个分区,保证相同 key的顺序性。第二种是轮询,key不存在的时候就会轮询的向1、2、3依次存储。当确定了要发送的分区后,会发送到 RecordAccmulator缓存中,key是要发送到指定的分区,value是一个双端队列。然后会判断双端队列是否已满(batch.size)会唤醒 send发送到 kafka broker中。同时,后端线程也会循环的判断这个双端队列是否已满。还有一种就是根据固定的时间判断是否该发送消息,从而提高 kafka的性能。当发送失败的时候,会将发送失败的消息放到双端队列的最前面。Retry默认是3,一般发送失败是网络等原因或者 broker有问题,因此这个值不建议设置比较大。

三、Producer 端参数详解


bootstrap.servers broker 的地址,集群的地址用逗号分隔,也可以指写集群的一个地址,但防止单点故障,最好都写。
key.serializer 关键字的序列化方式
value.serializer 消息值的序列化方式
acks 指定必须要有多少个分区的副本接收到该消息
max.block.ms 表示 send() 方法在抛出异常之前可以阻塞多久的时间,默认是60s
compression.type 消息在发往 kafka 之前可以进行压缩处理,不建议压缩,因为会消耗CPU资源,建议设置大一点
retries 生产者向 kafka 发送消息发生错误时重试
retry.backoff.ms 每次重试之间间隔的时间
batch.size 生产者在发送消息时,可以将同一个分区的消息放在一个批次里,一次性提交。如果数据体比较大时,该值应该设置大一些
linger.ms 生产者在发送一个批次之前,延迟指定时间,让更多的消息加入到该批次
buffer.memory 生产者的内存缓冲区大小,对应的 RecordAccmulator

四、Kafka Server 基本原理


【1】Zookeeper 集群作用:管理 Kafka集群,同步元数据信息;
【2】Metadata 信息用来存放什么数据的:broker中主从分区信息(是否可用等),以及从分区进行数据同步的信息;
【3】Producer 发送过来的数据怎么落盘的:数据进来会先存储在页缓存中,提高性能。

五、KafkaServer 主分区与副本数据同步原理


HW高水位:HW之前的数据是已经备份的数据;
LEO末端位移:HW至 LEO之间的是未备份数据;
如上5-9之间的数据未备份,Follower 节点会从 Leader节点拉取数据,Leader 节点存储了一个 Follower 副本,该副本也具有 HW和 LEO ,Follower节点会拉去 Leader节点上的 Follower副本,并将数据写入到 log文件中,同时更新 LEO为拉取到的值9。Follower 更新完后,会通知 Leader节点的 Follower 副本,并将 HW 写到该副本中。最后 Leader 副本的 HW会更新为所有 Follower 副本 LEO的最小值。然后判断 HW 是否等于 LEO,如果相等则说明备份好了。

六、KafkaServer 零拷贝原理


Kafka 的数据并不是实时的写入硬盘,利用操作系统分页存储来提高 I/O效率:
【1】数据直接在内核完成输入和输出,不需要拷贝到用户空间再写出去。可能会存在系统挂掉时,数据丢失的风险。
【2】Kafka 数据写入磁盘前,数据先写到进程的内核空间;
【3】副本备份数据以及消息者读取数据直接从内核空间的网卡读取;
【4】只能缓存有限大小的数据,即如果消费时间久远的数据需要从磁盘读取;

生产者将数据写入页缓存,然后再同步到磁盘,消费者也会先读取页缓存,只有部分数据才会从磁盘中获取。从而提高性能。

七、KafkaServer Leader 选举


Kafka Broker 启动的时候,会启动一个 controller 节点,该节点就是选举的时候使用,controller 会与zk进行通信。如果 broker挂掉了,就会取通知 ctroller 进行统计,看那些节点存活者,然后进行选举,看那个分区成为主分区。这个计算为什么要分在 broker上,因为 zk不适合做大量的计算和读写操作。计算的规则是 LSR中同步的副本,如果那个分区先备份完成就会放在最前面,因此就选择 ISR表中的第一个备份分区为主分区。

八、KafkaConsumer 原理


【1】Consumer 是如何协调消费分区数据的:Consumer 初始化时都会初始化一个 Consumer 协调器,发送心跳检测;Consumer 协调器与 Kafka 对应 Broker 的 group协调器进行通讯,并获取正在消费的所有 Consumer 信息,并将信息发送给主 Consumer协调器,Consumer Leader计算当前所有 Consumer应该对应消费哪个的分区数据(减少broker的压力)。
【2】Consumer 的 offset是如何管理的:Kafka 内部维护了一个_consumer_offsets用于存储 offset;consumer 消费完数据时会将当前消费分区最新的 offset ack到 _consumer_offsets(分区有50个)中。
【3】Consumer group 如何 rebalance的:group 协调器检测有 consumer节点挂掉,会将当前存在的 consumer 发送给 consumer 协调器,主协调器计算 consumer 应对应消费哪个分区数据。计算完成将结果发回至 group协调器。group 协调器与 consumer 协调器通信,通知对应 consumer节点是否需要消费,以及接着消费 offset位置。

九、KafkaConsumer 参数详解


【1】group.id:组ID,唯一标识一个消费组,需要确定一个不重复的组ID;
【2】session.timeout.ms:用于检测 consumer失效(failure)的时间,如果要缩短错误检测时间,可适当减少该值;
【3】auto.offset.reset:指定 consumer启动时消费策略,earliest(设定位移为当前最小位移);latest(设定位移为当前最新位移);
【4】enable.auto.commit:是否让Kafka 在后台自动提交位移,推荐 false,手动提交;
【5】heartbeat.interval.ms:心跳检测频率,如果 consumer group 中成员很多的话推荐将此值设置大一点;
【6】max.poll.interval.ms:用于调节消费主线程的消费速度,需比 poll消息消耗时长更大,否则可能导致 consumer再平衡;
【7】max.poll.records:控制单次 poll回来的消息数,建议越少越好;

十、性能优化方案


【1】acks 按需设置;
【2】尽量使用随机分区,防止数据分配不均匀;
【3】为各个 Producer 配置 retries,建议设置为整形的最大大小,感觉没什么用;
【4】为高吞吐量的 Producer,调优缓冲区的大小,分别是 buffer.memory 和 batch.size(以字节为单位)

KafkaServer 端的建议:
【1】评估当前项吞吐量,测定主分区的写入和消费速率,合理申请分区个数;使用 kafka 测试工具,根据自己实际吞吐量进行计算;分区多消耗资源,同时进行Leader选举也会比较耗时,备份的次数也就多。不断的调整测试,因为分区和吞掉量是一个驼峰式的曲线,存在一个最佳值,并不是越大越好。分区建议是机器的整数倍。

./kafka-producer-perf-test.sh --topic test --num-records 5000 --record-size 1024 --throughput -1 --producer-props bootstrap.servers=192.168.32.12:9092 acks=1

【2】建议每个 partition 至少两个副本,建议有几个 broker就设置几个副本;
【3】log.dirs优化:数据是存在磁盘中的,可以将数据存在不同的磁盘中。进行分盘保存,就可以减少磁盘的压力;
【4】在各个 Brokers上,请压缩 Topics所需的内存和 CPU资源;
【5】不要忽略监控 Brokers的 in-sync replica(ISR);
【6】禁止 Topic 自动创建,默认创建是一份分区一份副本;
【7】对于那些具有持续高吞吐量的 Brokers,请提供足够的内存,以避免它们从磁盘子系统中进行读操作;
【8】Topic 隔离,减少影响半径;

Consumer 消费端的建议:
【1】客户端版本升级到最新,因为老版本很多计算都是放在zk上,新版本都是放在broker上,offset新版本存储在topic中,旧版本存储在zk中;
【2】调优 consumer 的套接字缓冲区,例如poll(60) 超过60s获取不下来就会报错;
【3】设计具有高吞吐量的 consumers;
【4】JVM 上运行各种 consumers时,请警惕垃圾回收对它们可能产生的影响;

高性能 Kafka队列的原理的更多相关文章

  1. 高性能消息队列 CKafka 核心原理介绍(上)

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:闫燕飞 1.背景 Ckafka是基础架构部开发的高性能.高可用消息中间件,其主要用于消息传输.网站活动追踪.运营监控.日志聚合.流式 ...

  2. kafka集群原理介绍

    目录 kafka集群原理介绍 (一)基础理论 二.配置文件 三.错误处理 kafka集群原理介绍 @(博客文章)[kafka|大数据] 本系统文章共三篇,分别为 1.kafka集群原理介绍了以下几个方 ...

  3. 《转载》仅需3分钟,你就能明白Kafka的工作原理

    仅需3分钟,你就能明白Kafka的工作原理 周末无聊刷着手机,某宝网 App 突然蹦出来一条消息“为了回馈老客户,女朋友买一送一,活动仅限今天!”. 买一送一还有这种好事,那我可不能错过!忍不住立马点 ...

  4. kafka知识体系-kafka设计和原理分析

    kafka设计和原理分析 kafka在1.0版本以前,官方主要定义为分布式多分区多副本的消息队列,而1.0后定义为分布式流处理平台,就是说处理传递消息外,kafka还能进行流式计算,类似Strom和S ...

  5. 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转

    线程安全使用(四)   这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来. 这里主要讲解下CancellationT ...

  6. JUC并发编程与高性能内存队列disruptor实战-下

    并发理论 JMM 概述 Java Memory Model缩写为JMM,直译为Java内存模型,定义了一套在多线程读写共享数据时(成员变量.数组)时,对数据的可见性.有序性和原子性的规则和保障:JMM ...

  7. 消息队列NetMQ 原理分析1-Context和ZObject

    前言 介绍 NetMQ是ZeroMQ的C#移植版本,它是对标准socket接口的扩展.它提供了一种异步消息队列,多消息模式,消息过滤(订阅),对多种传输协议的无缝访问. 当前有2个版本正在维护,版本3 ...

  8. PHP实现队列的原理

    关于的队列的介绍,我这里就不多讲了,随便百度一下都很多 用过laravel框架的童鞋都知道其自带队列功能,之前我很费解,PHP只是一个脚本,有超时机制 为什么能不停的去执行队列呢? 带着这个问题,在网 ...

  9. 消息队列NetMQ 原理分析2-IO线程和完成端口

    消息队列NetMQ 原理分析2-IO线程和完成端口 前言 介绍 目的 IO线程 初始化IO线程 Proactor 启动Procator线程轮询 处理socket 获取超时时间 从完成端口获取处理完的状 ...

  10. 消息队列NetMQ 原理分析3-命令产生/处理和回收线程

    消息队列NetMQ 原理分析3-命令产生/处理和回收线程 前言 介绍 目的 命令 命令结构 命令产生 命令处理 创建Socket(SocketBase) 创建连接 创建绑定 回收线程 释放Socket ...

随机推荐

  1. 目前为止最完善专业的微信小程序商城

    购买商业版(368元): http://market.zhenzikj.com/detail/82.html帮助文档:https://www.kancloud.cn/crmeb/crmeb/66242 ...

  2. C语言||一作业03

    1.作业头 这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/SE2020-3/ 这个作业目标在哪 https://edu.cnblogs.com/cam ...

  3. oculus按键大全

    // OVRInput.Update(); if (OVRInput.GetUp(OVRInput.Button.Three)) { Debug.Log("remote click" ...

  4. PHP Redis - Set(集合)

    Redis 的 set 无序集合,与 list 类似,特殊之处在于 set 可以自动排重,不会出现重复数据 集合中最大的成员数为 232-1 (4294967295, 每个集合可存储40多亿个成员). ...

  5. powerbi 模板网站

    微软网站 https://community.powerbi.com/t5/Themes-Gallery/bd-p/ThemesGallery 中国区powerbi比赛网站 http://www.ch ...

  6. 微信小程序开发遇到的注意事项及奇怪事

    1.wx.uploadFile上传文件时只支持本地文件(相册或者拍摄的),网络文件不可以,可以将网络文件用wx.downloadFile下载到本地在下载,下载以后会返回一个微信临时地址然后再下载 2. ...

  7. deepin系统编辑pdf文件的两个简单方法(终端命令行模式)

    DEEPIN深度系统编辑PDF文件有时竟然超级简单好用,比WINDOWS系统需要单独下载一个PDF编辑软件的方法强多了,而且windows系统PDF编辑软件还有版权限制,各种作啊. 下面的两条命令,使 ...

  8. 第12组 Beta冲刺 (3/5)

    1.1基本情况 ·队名:美少女战士 ·组长博客:https://www.cnblogs.com/yaningscnblogs/p/14016611.html ·作业博客:https://edu.cnb ...

  9. php 后台注册环信用户

    <?php //Easemob.php <?php /** -------------------------------------------------- 环信PHP REST示例代 ...

  10. JS样式获取的封装方法

    样式获取 style属性 只能获取标签内容style属性里面存在的一些样式 如果你需要获取对应的全局所有地方设置样式 我们就需要采用一些方法 getComputedStyle 方法属于window的方 ...