【Kafka】图解概念

我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码


一、基础概念

  • Broker
    一个独立的kafka服务器被称为 broker。消息中间件处理节点,一个或者多个Broker可以组成一个Kafka集群。broker接收producer的消息,将消息保存在磁盘,也为consumer提供服务,对读取分区的请求作出响应,返回消息。

  • Topic
    每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。

  • Partition
    用于存放消息的队列,存放的消息都是有序的,同一主题可以分多个Partition,如分多个Partiton时,同样会以如partition1存放1、3、5消息,partition2存放2、4、6消息

  • Producer
    消息生产者,向Broker发送消息的客户端。

  • Consumer
    消息消费者,从Broker读取消息的客户端,Consumer是通过offset 识别读取位置。Consumer与partition之间的映射关系称为Consumer对partition的所有权关系。

  • Consumer Group
    每个Consumer属于一个特定的Consumer Group,一条消息可以发送到多个不同的Consumer Group,但是同一个Consumer Group中只能有一个Consumer能够消费该消息。

  • Offset
    偏移量 offset:不断递增的一个整数(consum 消息,递增offset),每个消息在不同的partition上的offset是不一样的,也是唯一的。

二、图解基本概念

2.1 Producer与Consumer

在这里插入图片描述

2.2 Partition 分区

在这里插入图片描述

  1. KafkaConsumer 可以保证单个消息在Partition内的读取顺序,但是无法保证再整个 topic 的顺序,上图是3个消费者消费了4个Partition,Partition数量可以大于Consumer,Consumer1读取Partition1+ Partition2,保证了Producer生产的消息都可以被读取到,若每个Consumer只能读取到1个Partition,那么势必有消息没法会被漏掉。

2.2.1 分区中的 AR、ISR、OSR、HW、LEO

在这里插入图片描述
一个Topic分为N个分区,比如分了4个Partition,每个Partition可以设置3个副本,也就是合计4个Replica,1个主的Replica和3个从的Replica

AR = ISR + OSR

  1. AR (Assigned Replicas):partition中所有副本称为AR。
  2. ISR (In-Sync-Replicas): 所有与partition leader replica保持一致的 replicas 称为 ISR。ISR是AR的一个子集
  3. OSR(Out-Sync-Replicas) : 与 partition leader replica 滞后过多的 replicas 称为 OSR。
  4. HW (high WaterMark)高水位:Consumer只能拉到这个 offset 之前的 Msg,HW表示全部replicas都同步到的一个offset (别的replica的LEO如果小于leader的HW,那么判定为OSR,否则ISR)
  5. LEO ( Log End Offset ) :当前日志文件下一条插入消息的 offset。

请记住,上面这几个概念,都是针对 leader 副本和 follower 副本之间来说的,下面的 LSO 和 Lag 是针对 leader来说的。

2.2.2 分区中的 LSO、Lag

LSO ( Last Stable Offset ) 最新稳定offset : 主要影响Kafka堆积量 Lag。
Lag (Lagging 滞后):消息滞后量。取决于消费端参数——isolation.level,
默认是read_uncommited ,也就是读未提交。那么Lag = HW - Consumer offset.
如果改为 read_commited 。那么 Lag = LSO - Consumer offset。如果事务已经完成,那么 HW = LSO,
如果事务没有完成,LSO的值等于事务中的第一条消息所在的位置,(firstUnstableOffset)。

在这里插入图片描述

事务,是针对生产者生产来说的,如上图,从offset=3开始生产,到offset=6还没结束,如果生产还没结束就能读取到,说明是读未提交read_uncommited,那么LSO=7,如果是读已提交read_commited,那么LSO=2.
事务也是针对leader replica来说的!

对未完成的事务而言,LSO 的值等于事务中第一条消息的位置(firstUnstableOffset,如上图所示),对已完成的事务而言,它的值同 HW 相同, 所以我们可以得出一个结论:LSO≤HW≤LEO。(如下图所示)
在这里插入图片描述

2.3 全流程汇总

在这里插入图片描述

1. Producer会将消息均衡写入某个 Partition
注意:每个 Partition 都有N个副本 replica(1个主副本,N-1个从副本),其中,leader replica处理读写请求,剩下的 follower replica只负责复制备份,具体有几个副本,由参数 replication.factor 设置。复制系数 N 越大,越占磁盘空间,但是可靠性更强。

2. 为了减少网络开销,消息是分批次写入Kafka的。
类似于redis中的zadd要一批批写,别一个个写。具体每批次几条消息,可以由 batch.size 来控制,收集消息的超时时间由linger.ms参数控制。但是需要对吞吐量与时间延迟作出权衡。批次内消息量越大,单位时间内要处理出的消息就会越多,单条消息的传输时间就会越长,毕竟你得等人齐了才会发车。此外,批次消息会被压缩,压缩后可以调高数据的传输和存储能力,但是需要付出额外的cpu计算。

3. 关于Partition数量与Consumer数量的关系:
	a. 假如Partition数量 > Consumer数量,那么一个Consumer可以读取多个分区,保证全部分区的消息都能被消费到。
	b. 假如Partition数量 = Consumer数量,那么一对一,刚刚好。
	c. 假如Partition数量 < Consumer数量,那么会有一部分Consumer未能抢占到Partition空闲着。

2.4 硬件相关

在这里插入图片描述

三、 参数配置

在这里插入图片描述

3.1 操作系统配置

页面缓存:保存在内存中的页面大小的文件块 =原文链接=

为了用图去说明页面缓存,我捏造出一个名为 render 的 Linux 程序,它打开了文件 scene.dat,并且一次读取 512 字节,并将文件内容存储到一个分配到堆中的块上。第一次读取的过程如下:
在这里插入图片描述

render 请求 scene.dat 从位移 0 开始的 512 字节。
内核搜寻页面缓存中 scene.dat 的 4kb 块,以满足该请求。假设该数据没有缓存。
内核分配页面帧,初始化 I/O 请求,将 scend.dat 从位移 0 开始的 4kb 复制到分配的页面帧。
内核从页面缓存复制请求的 512 字节到用户缓冲区,系统调用 read() 结束。
脏页:该内存被update或者write了,但是还没持久化到磁盘

+  虚拟内存调优 :(linux系统中的swap) ,如果使用到了swap,表明没有多余内存可以给页面缓存了。
1. vm.swappiness 
该参数表明虚拟机的子系统将如何使用 swap分区,而不是只把内存也从页面缓存里移除。要有限考虑见效页面缓存,而不是进行内存交换。vm.swappiness = 60(默认60)表明内存使用量达到 1- 60 = 40% 的时候,开始使用swap分区,参数调成1,就表明 1 - 1% = 99%,内存使用达到99%的时候才使用分区,目的是最大化使用内存。(cat /etc/sysctl.conf)  针对 kafka,建议设置为 1

2.  vm.dirty_ratio: (同步刷脏页)
进行磁盘IO,会阻塞应用程序。默认是 10 。表示当前文件系统脏页数量达到系统10%的时候,开始向磁盘写出数据。数值越小,IO频率越高,数值越大,IO频率越低,但是每次IO的处理时间会越长。针对kafka,建议设置为 60-80

3.  vm.dirty_background_ratio :(异步刷脏页)
不阻塞应用程序。 达到阈值,触发 pdflush / flush /kdmflush 等后台会写进程运行。 默认值是 5 。 原则上,若  vm.dirty_background_ratio 大于 vm.dirty_ratio,那么永远无法触发 vm.dirty_ratio 的阈值,但是加入异步写入磁盘的数据慢于各个应用程序写到内存的数据,也就是增加的量大于刷出去磁盘的量,那么也是会触发 vm.dirty_ratio 这个参数设定的坎,那么也会进行同步处理脏页,导致 IO 阻塞。 针对 kafka,建议设置为 10

4. vm.dirty_expire_centisecs:  
声明Linux内核写缓冲区里面的数据多“旧”,pdflush进程就开始考虑写磁盘。 单位是 0.01s。默认是3000,也就是30s,建议1500.

5. vm.dirty_writeback_centisecs : 
 声明了进程 pdflush 的运行间隔(内核flush脏数据的线程),单位 0.01s。 默认值是500,也就是5秒。也就是5秒后才可以进行新的flush磁盘操作,如果你的系统是持续的写入动作,那么要降低这个数值。 但是如果你的写入不是持续的,而是短暂的尖峰式写入,并且内存也很赋予,那么应该增大此数值。

6. Vm.vfs_cache_pressure : 
声明了内核回收用于 directory 和 inode cache 内存的倾向。默认100
缺省值100表示内核将根据pagecache和swapcache,把directory和inode cache保持在一个合理的百分比;降低该值低于100,将导致内核倾向于保留directory和inode cache;增加该值超过100,将导致内核倾向于回收directory和inode cache。


+ 磁盘
7. 文件系统采用 XFS 取代 EXT4 
EXT4 使用了分配延迟,一旦系统奔溃,容易造成数据丢失和文件系统毁坏。XFS也使用了分配延迟算法,但是比EXT4更安全,XFS有自动调优功能,批量磁盘写入具有更高的效率,可以提升整体的 IO 吞吐量。

8. 对挂在点的noatime参数进行合理的设置。文件元数据包含3个时间戳 :ctime(创建时间),mtime(最后修改时间),atime(最后访问时间)。默认情况下,每次读取都会更新 atime,导致大量的磁盘写操作,而且atime用处不大。Kafka也用不到该属性,可以把该属性禁用掉。

+ 网络
9.  socket 读写缓冲区
 配置参数 net.core.wmem_default 和 net.core.rmem_max  指定的大小。合理的值是(131072,也就是128KB)
 
10.  socket 读写缓冲区最大值对应的参数是net.core.wmem_max 和 net.core.rmem_max 合理的值是 ( 2097152 ,也就是2MB)

11.  TCP socket 读写缓冲区
参数 net.ipv4.tcp_wmem 和 net.ipv4.tcp_rmem 。这些参数的值由3个整数组成,空格分隔,分别表示最小值、默认值和最大值。三个值都不能大于上面的 net.core.wmem_max 和 net.core.rmem_max 。eg:“4096 65536 2048000” 表示最小值是 4KB 、默认值是64KB、最大值是2MB。

12. 其他。例如 :
net.ipv4.tcp_window_scaling 
设为 1,启动TCP时间窗扩展,可以提升客户端传输数据的效率,传输的数据可以在服务器端进行缓冲。

net.ipv4.tcp_max_syn_backing 
设为比默认值 1024 更大的值,可以接收更多的并发连接。

net.core.netdev_max_backlog
 设为比默认值1000更大的值,有助于应对网络流量的爆发,特别是在使用千兆网络的情况下,允许更多的数据包排队等待内核处理。

3.2 Broker 配置

  • 常规配置
1. broker.Id 默认值是0,可以其他整数。

2. port 默认9092,自定义的话,若1024以下的端口,需要用root启动kafka,不建议使用。

3. zookeeper.connect 用户保存broker元数据的Zookeeper地址,是通过 zookeeper.connect 来指定的。(kafka需要依赖zk,hostname:port/path . eg. localhost:2181.
上面的 /path 是可选的zk路径,作为kafka集群的chroot环境,如果不指定他,默认使用根路径 /

4. log.dirs 日志保存在磁盘的路径,可以指定多个,broker会使用“最少使用”原则,同一partition的日志片段 segment 会保存在同一个路径下。增加新partition时,会往最少数目partition的路径添加,而不是往占据最小磁盘空间的路径添加。

5. num.recovery.threads.per.data.dir ,配置整数N,表明在broker启动,重启,关闭的时候,使用多少的线程Thread去进行并行操作,处理日志片段。默认每个目录dir是是1个线程,可以指定N个进行并发, 若上面 log.dirs 指定了多个路径,比如3个路径,这里的N=8的话,那么总共就需要24个线程thread。

对于以下3种情况,Kafka会使用可配置的线程池来处理日志片段segment:
a. 服务器正常启动,用于打开每个partition 的日志 segment
b. 服务器崩溃后重启,用于检查和截短每个 partition 的日志 segment
c. 服务器正常关闭,用于关闭日志 segment

6. auto.create.topic.enable (是否自动创建 topic,系统默认启用),以下3种情况会自动创建topic:
a. producer 往 topic 写入消息
b. consumer 从 topic 拉取消息
c. 任何一个客户端往topic发送元数据
  • 默认配置
1. num.partitions (新的topic包含多少个 partition,默认1。)
我们可以增加topic的partition的个数,但是不能减少partition的个数,若少于partition的个数,需要手动创建该 topic。
选partition数量的秘诀:关键是一个partition只能最多一个consumer,基于produce的速度肯定大于consume的速度,所以假如 producer每秒产生1MB的数据,consumer每秒消费处理50KB的数据,那么就需要20个Consumer,也就是最少要20个Partition,否则就会产生Lag,也就是堵塞。
公式就是:N = producer吞吐量 / consumer 吞吐量
注意:单个broker对partition是有数量限制的,因为partition越多,占用内存就越多,完成leader选举的时间也就越长。
=== ⬇️ ⬇️ ⬇️ 日志片段文件保留时机  ⬇️ ⬇️ ⬇️ === 

2. log.retention.ms (日志片段文件的保留时间)
默认是使用 log.retention.hours 参数来配置时间,默认是168小时,也就7天。也可以用其他配置参数:log.retention.minutes 或者 log.retention.ms,如果配置了多个,那么kafka会选用具有最小值的那个参数。比如 (log.retention.ms = 169) +  (log.retention.hours = 168),那么会选择 169 ms。  

3. log.retention.bytes (每个topic在每个partition最多保留的字节数),比如设置了1G,然后这个topic有8个partition,那么这个topic最多保留8G数据。当partition增加时,整个topic保留的数据也随之增加。
若同时配置了  log.retention.ms 与 log.retention.bytes,那么只要一个条件满足,那么多出来的消息也会被删除。
===  ⬇️ ⬇️ ⬇️ 日志片段文件关闭时机  ⬇️ ⬇️ ⬇️===

4. log.segment.bytes 日志片段文件的大小。比如设置了1G,那么当当前写入的文件size达到1G的时候,会关闭这个文件,重新创建写入新的文件。那么刚刚关闭的写完的日志片段文件就开始死亡倒计时,若是配置了 log.retention.ms 那么就抓取该文件的最后写入时间戳进行倒计时,目测是该file的last update time。 若是配置了 log.retention.bytes ,那么当当前topic在该partition写入的总字节数超过该配置时,就会删除旧的文件。

5. log.segment.ms 日志片段写入多久后会被关闭。这个默认不启动。与上面参数 log.segment.bytes 不互斥,谁先满足条件就关闭。

6. message.max.bytes 设置单个消息的大小,默认1,000,000 ,也就是1MB。若producer生产的信息大小大于这个数字,那么消息不会被接收,broker还会返回错误信息。该参数是压缩后的消息大小。该数字越大,那么负责网络连接和请求的线程就需要花费更多的时间来处理这些请求,也会增加磁盘写入块的大小,从而影响IO吞吐量。

7. fetch.message.max.bytes 消费者最大读取的信息大小,这个一定要大于等于 message.max.bytes ,否则大消息没法消费,导致消费者堵塞。
设置 replica.fetch.max.bytes 时,也遵循这个规律。

3.3 GC配置

Kafka 对堆内存的使用率非常高,容易产生垃圾对象。假如服务器有64G,使用5G堆内存来运行Kafka,那么可以配置以下俩参数:
1. MaxGcPauseMillis : 该参数指定每次垃圾回收默认的停顿时间。默认值是200ms。在这里建议设置成 20.

2. InitiatingHeapOccupancyPercent : 该参数指定俩在 G1 启动新一轮垃圾回收之前可以使用的堆内存的百分比。默认45 。也就是堆内存使用率达到45%之前,不会进行垃圾回收。这个百分比包括新生代和老年代的内存。在这里建议设置成 35 

3.4 Producer 配置

13. acks 
acks 参数指定了必须有几个partition副本收到消息,producer才认为消息写入成功。
ack=0 : 发完走人。高吞吐量,但是不能保证数据一致性。
ack=1 : 收到 leader 回应走人。中吞吐量,中一致性。 有一种情况就是假如 leader收到之后,返回response,然后没发给 replica 就挂了,那么消息还是会丢失。
ack=all : 全部参与复制的节点都收到才走人。最安全,但是吞吐量低。

14. buffer.memory
设置Producer内存缓冲区的大小,生产者先发送Msg --->  内存缓冲区 ---> 再发送到服务器。 如果发送到服务器的速度比Producer 发送到缓存区的慢,那么就会堵塞Producer,那么send() 方法调用就要么堵塞,要么抛出异常(先阻塞 max.block.ms 这个时间,超过了就抛异常)

15. compression.type
默认情况下,Msg不会被压缩。也可以设置为 snappy、gzip或者 lz4 ,指明了用哪种算法。
snappy 性能不错,占用较少CPU,gzip压缩比更佳,但是占用更多的CPU。主要选择因素是网络传输开销和存储开销。

16. retries
Producer 重发消息的次数。超过了就会放弃重试,返回错误。默认值情况下,Producer每次重试间隔是100ms,可以通过 retry.backoff.ms 修改。重试场景:某些临时性错误(比如partition 找不到 leader)。某些错误无法通过重试解决(比如”消息太大“错误),代码层面主要要解决这些无法通过重试解决的错误,还有就是要解决重试次数超出上限的情况。(不建议设置成0)

17. batch.size 
(配合 linger.ms)当有多个Msg需要被发送到同一个 partition 的时候,Producer会把他们放在同一个批次。该参数指定了一个批次可以使用的内存大小,按照字节数bytes计算(不是消息个数)。batch.size 设置的越大,占用内存越多,但是不会造成延迟。 如果设置得太小,那么Producer就会频繁地发送消息,增加额外地开销。

18. linger.ms
该参数指定了 Producer 的等待更多消息加入批次的时间。也就类似与开车等待时间。配合上面 batch.size ,kafkaProducer会在批次填满或者 linger.ms 达到上限时把批次发送出去。默认情况下,只要有可用的线程,Producer 就会把消息发送出去,就算批次里面只有一个消息。把linger.ms 设置成比0大的数,让producer在发送批次之前等一会,等待更多 Msg,虽然这样会增加延迟,但是提升了吞吐量。(一次性发送了更多的消息,平均下去每个消息的开销就变小了)

19. client.id
该参数可以是任意的字符串,只是用来识别Msg的来源。

20. max.in.flight.request.per.connection
该参数指定了Producer 在收到服务器响应之前可以发送多少个消息。它的值越高,就会占用越多的内存,不过也会提高吞吐量。设为 1 可以保证消息是按照发送顺序写入服务器的,即使发生了重试。因为设置为1的话,那么就意味着,只有等服务器确认成功无报错地接收了这一条消息,才会发下一条。如果设置成2 的话,那么可能我发了第一条(这一条待会会返回错误),服务器还没给我成功确认,我就发送了第二条,结果就是第二条被接收了,第一条打回了,重试的话,假如成功了,那么顺序就反了。

21. request.timeout.ms 
指定了Producer 在发送数据时等待服务器返回响应的时间。

22.  metadata.fetch.timeout.ms
metadata.fetch.timeout.ms 指定了Producer在获取元数据(比如目标partition 的leader是谁)时等待服务器返回响应的时间。如果等待超时,那么Producer 要么重试发送Msg,要么返回错误。

23. timeout.ms 
指定了 broker 等待同步副本返回消息确认的时间,与 asks 的配置相匹配。如果在指定时间内没有收到同步副本的确认,那么broker就会返回一个错误。

24. max.block.ms 
该参数定义了在调用 send() 方法或者使用 partitionsFor() 方法获取元数据时,producer 的阻塞时间。当producer的发送缓冲区(buffer.memory )已满,或者没有可用的元数据时,这个方法就会堵塞。在堵塞超过 max.block.ms 的时候,producer就会抛出异常。

25. max.request.size 
该参数控制producer发送的请求大小。也就是每一批次发送的数据大小。如何设置成1MB,那么你一批次无论有几条数据的话,那么总的字节数不能超过1MB。另外,broker对可接收的消息最大值也有自己的限制 (message.max.bytes),所以两边最好可以匹配,避免Producer生产的消息被broker拒绝。

26. receive.buffer.bytes 和 send.buffer.bytes
这俩参数分别指定了 TCP socket 接口接收和发送数据包的缓冲区大小。如果他们被设置为 -1,那么就按默认值来。如果producer 和consumer 位于不同的数据中心,那么可以适当增大这些值,因为跨数据中心的网络一般有较高的延迟和比较低的宽带。(类似于跨城就要搞个大货车,多载点货,比较socket连接的搭建,在跨数据中心的情形下,成本较高,得好好利用。)

3.5 Consumer 配置

1. fetch.min.bytes 
指定了Consumer从服务器获取记录的最小字节数。Broker 在收到Consumer 的数据请求时,如果可用的数据量大小小于该数值,那么他会等到有足够的数据时才会把它返回 Consumer,这样可以降低消费者与 broker 的工作负载,因为他们的Topic不是很活跃的时候,就不需要来来回回地处理数据,这样会导致 CPU 使用率变高,那么把该数值调大即可。

2. fetch.max.wait.ms
 默认500ms,和上面参数一起配合,达到 fetch.max.wait.ms 这个时间才进行传输,否则就等,当这两条件,至少满足一个才发送数据给 Consumer.

3. max.partition.fetch.bytes    
默认值是1M,指定了服务器从每个 partition 里返回给Consumer的最大字节数。也就是说,KafkaConsumer.poll() 从每个 Partition 返回的记录最多不超过该值。假设该值是 1MB,并且现在有20个partition,5个Consumer,那么意味着一个Consumer要应对4个Partition,那么给Consumer分配内存的时候,就要考虑最少4MB,尽量多分配点,因为假如倒下了3个Consumer的话,只剩下两个,那么这两个 Consumer就会最多占用10MB的内存,要注意。并且 max.partition.fetch.size 的值要大于broker能够从producer接收到的最大消息的字节数(max.message.size)。否则Consumer 可能无法读取到这些消息,导致Consumer一直报错(消息过大的Exception),配置该数值的另外一个要考虑的因素是Consumer的处理时间,如果poll()返回的数据太多,Consumer需要更多的时间来处理,那么距离下次 poll() 的时间就会变长,而Consumer本身需要频繁调用 poll() 方法来避免 session 过期和避免发生 partition rebalance 。如果为了避免该情况,可以把 max.partition.fetch.bytes 给调小,或者延长session过期时间。

4. heartbeat.interval.ms
指定了多久向协调器发送heatbeat的频率,一般是session.timeout.ms 的三分之一。如果session.timeout.ms 是3秒,那么 heartbeat.interval.ms 是1s。也就是3秒内至少有1次心跳,否则就认为该 Consumer死了。

5. session.timeout.ms
默认3s,会话超时时间,如果Consumer与服务器断开的时间超过这个数字,那么服务器就会认为 Consumer 已经死亡,协调器就会触发 Partition rebalance,把该Consumer负责的Partition分配给其他Consumer,该属性与heartbeat.interval.ms 参数紧密相关。否则就认为该 Consumer死了。如果把  session.timeout.ms 参数调低,优点是:可以加快检测和恢复崩溃的节点,缺点是:在某些情况下容易误判,比如poll之后数据量较大,进行长时间的业务处理,或者是因为 GC导致处理时间过长,那么都会导致该Consumer被误认为死亡。 如果把参数调高,那么情形跟上面相反。

6. auto.offset.reset
该属性指定了 Consumer 在读取一个没有偏移量offset 的Partition 或者偏移量offset无效的情况下(因Consumer长时间失效,包含偏移量的记录已经过时并被删除)该做何处理。他的默认值是 latest (largest),意思是读取最大。另一个值是 earliest (smallest),意思是读取最小。none(anything else) 抛出异常。

7. enable.auto.commit 
是否自动提交偏移量 offset,默认 true。

8. auto.commit.interval.ms
假如  enable.auto.commit  为 true才生效,自动提交的频率,默认5s。代码中 while(true) 后的poll(100),然后 foreach处理刚刚poll回来的record,每过5s,就会自动commit目前foreach处理到的最大的partition的offset(自动提交是在轮询foreach里面进行的),foreach内部逻辑,每次处理一条 consumerRecord 的时候会检查下是不是到5s了,该提交offset了,是的话就提交。
这个地方要注意一个问题:假如提交完的3s后,rebalance了,那么重新读取的offset是3s前提交的,也就是落后3s了,那么会导致消费重复的消息,那么解决方案就是a:自己内部代码逻辑要有能判断是否消费过的记号。b: close消费者的时候,提交一次offset

9. partition.assignment.strategy
指定分区策略。(默认 Range)
a. Range:Math.ceil() 分给第一个Consumer,剩下的均分给剩余的Consumer。(RangeAssignor)
b.RoundRobin : 每一个Consumer先拿一个,发完再继续继续发,这种方法较为平均。(RoundRobinAssignor)

10. client.id 
broker标记从客户端发送过来的消息。

11. max.poll.record 
控制单次 poll() 返回的记录record数量

12. receive.buffer.bytes 和 send.buffer.bytes 
socket在读取数据的时候用到的TCP缓冲区的大小。

四、kafka与zk的关系

1. Kafka 使用 Zk 来保存 broker、partition 和 topic 的元数据信息。在很多部署环境里,会让多个Kafka集群共享一个 ZK集群(每个集群使用一个chroot路径)

2. Kafka 0.9.0.0版本之前,消费者group的信息、partition信息,consumer offset是提交到zk,也就是zk来管理的。每个提交时间点上,consumer会往zk上写入一次 offset,合理的提交间隔是1min,因为这刚好是消费者group某个消费者发生失效时,能否读取到重复消息的时间。在这个版本之后,Kafka引入来一个新的消费者接口 Topic: __consumer_offsets,允许broker直接维护这些信息。由于提交信息流量对于zk'来说,并不算小,所以建议使用最新版的kafka,消除对zk的依赖。

3. 尽量kafka集群独占zk群组。虽然多个kafka集群可以共享一个zk群组,但是如果可能的话,不建议把zk共享给其他应用程序。kafka对zk的延迟和超时比较敏感,与zk群组之间的一个通信异常就可能导致 kafka服务器出现无法预测的行为。容易让多个 broker 同时掉线,如果 broker掉线,那么会导致 partition 离线,给集群控制器带来压力。

未完待续…未完待续…未完待续…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值