topic分区管理
preferred leader选举
在一个 Kafka集群中, broker服务器宕机或崩溃是不可避免的。一旦发生这种情况,该broker上的那些 leader副本将变为不可用,因此就必然要求Kaka把这些分区的 leader转移到其他的 broker上。即使崩溃 broker重启回来,其上的副本也只能作为 follower副本加入ISR。
随着集群的不断运行,这种 leader的不均衡现象开始出现,即集群中的一小部分 broker上承载了大量的分区 leader副本。为了校正这种情况,Kaka引入了首选副本( preferred replica)的概念
broker重启后,可以通过脚本,将leader副本重新调整到相应的broker上。
增加broker
当kafka的broker不够用时,我们需要对kafka进行扩容。
新增的broker是不会自动分担已有的topic负载的
由于Kaka集群的服务发现交由 ZooKeeper来处理,因此向Kaka集群增加新的 broker服务器非常容易。用户只需要为新增 broker设置一个唯一的 broker. id,然后启动即可。 Kafka集群能自动地发现新启动的 broker并同步所有的元数据信息,主要包括当前集群有哪些主题(下称 topic)以及 topic都有哪些分区等。
唯一有缺憾的是,新增的 broker不会自动被分配任何已有的 topic分区,因此用户必须手动执行分区重分配。
分区重分配(扩容)
kafka可以通过脚本,完成分区重分配的工作,在实际生产环境中,用户一定要谨慎地发起分区重分配操作,因为分区在不同 broker间进行数据迁移会极大地占用 broker机器的带宽资源,从而显著地影响 clients端业务应用的性能。如果可能的话,尽量在非高峰业务时段执行重分配操作。
实现原理
首先 kafka会在新的broker上创建对应副本,并同步leader 副本的进度,直到加入ISR。
然后kafka会停止目前的leader副本的写入,并将leader副本 设置为新的broker上的副本。
常见问题
消息堆积
当出现消息堆积,需要增加消费者。如果topic分区数很少的话(小于消费者数量),新增的消费者会闲置,不会消费数据。
所以创建topic分区数的时候,应该设置合理的分区数,不能太小。
对于生产环境,无法进行紧急扩容的,可以通过新建一个topic,原来的topic的消费者不消费任何数据,直接转发到新的topic进行消费。
磁盘快满了
如果mq磁盘快慢了,创建一个新的mq,把数据放到新的mq里面,等闲时在去补数据。
kafka是如何保证高可用的
副本因子,ISR
消息丢失
通过producer设置和broker设置,可以做到消息不丢失,见producer篇。
消息顺序
kafka会保证同一个key的消息,会被分配到同一个分区里面。
消息重复
consumer端保证消息消费的幂等性
kafka消息消费超时(消息重试)
创建两个topic,consumer如果在指定时间不能消费掉一条消息的话,强制结束,并将消息发到重试的topic
kafka为什么这么快
写入的时候
- 顺序写入
- MMFile
即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以Kafka的数据并不是实时的写入硬盘 ,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。
Memory Mapped Files(后面简称mmap)也被翻译成 内存映射文件 ,在64位操作系统中一般可以表示20G的数据文件,它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。
完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),也不必关心内存的大小有虚拟内存为我们兜底。
使用这种方式可以获取很大的I/O提升,省去了用户空间到内核空间复制的开销(调用文件的read会把数据先放到内核空间的内存中,然后再复制到用户空间的内存中。)
但也有一个很明显的缺陷——不可靠,写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。
Kafka提供了一个参数——producer.type来控制是不是主动flush,如果Kafka写入到mmap之后就立即flush然后再返回Producer叫 同步 (sync);写入mmap之后立即返回Producer不调用flush叫异步 (async)。
读的时候
零拷贝 sendfile
数据直接在内核完成输入和输出,不需要拷贝到用户空间再写出去。