在没有kafka之前,多个进程之间的通信可以通过,serverSocet ,socet之间进行通信。但是遇到以下问题这种通信是不能很好解决的:
1.生产者生产数据大于消费者消费,导致数据积压,产生oom
2.同样的1条消息如果向两个消费者发送,需要发送多次。
3.进程之间增加耦合度,逻辑变得复杂。
kafka可以解决以上遇到的问题。
kafka概念理解
为了保证kafka可以横向扩展,提升生产和消费的性能。kafka可以有多个broker,例如 生产者向指定的topic生产数据,如果这个时候kafka的topic只在一个broker上面,还是会导致多个生产者和消费者来一个broker上面操作数据,增加broker没有任何意义。这个时候可以将在一个broker上面的topic进行切分,放到不同的broker上面,提升生产消费的性能。为了好管理切分后的topic,引入partitions(分区)的概念。同时这个时候多个消费者从多个broker的分区上面消费的数据不是完整的,为了保证多个消费者消费数据的完整性引入消费者组的概念。
为了保证数据的安全性(类似redis中的持久化),kafka中有副本的概念,副本有leader和follower两种,leader是存放在broker自己所在的位置,用来读写操作。follower 存放在不同的broker,保证leader所在的broker宕机后,数据不会丢失,follower副本什么也不会做,只是保证数据的持久化。
kafka broker选举的过程
为了保证集群的高可用,先启动成功的broker会在zookeeper集群上面创建一个controller(集群管理者)名称的znode节点,将自己的唯一id设置进去,其他broker启动之后会监听这个znode节点。如果发现不存在之后,其他的broker就会去zookeeper上面创建这个znode节点,谁先抢到建立这个节点,谁就是新的controller,其他broker继续监听这个znode节点。
kafka中的分区管理replicas是什么
replicas是用来管理topic分区repatitions中副本的同步机制。
lsr:与leader副本保持同步的follower副本(包括 Leader 副本在内)组成 ISR
OSR:与 Leader 副本同步滞后过多的 Replica 组成了 OSR
注意:osr副本不参与集群管理者(controller)的竞选
如何读取日志的偏移量
在副本的概念中有日志开始偏移量(logstartoffset),高水位线(high watermark),即将写入的数据(LEO)
LogstartOffset:表示可以读取的偏移量,从哪里开始读
high watermark:表示不可以读取的位置。
kafka消息可靠性如何保证
rabbitmq通过生产者/消费者确认机制来保证消息的可靠性。
kafka通过 acks机制,发送消息的机制,手动提交offset
1.acks机制 类似cap理论,可以通过设置来保证消息的可靠性
acks = 1 默认为1。生产者发送消息,只要 leader 副本成功写入消息,就代表成功。不保证follower副本同步完成。
acks = 0 只要消息发出去就不管了。
acks = all 或者 -1 保证所有的副本同步完成。
2.发送消息的机制
总共有三种模式
- 1.发后即忘(fire-and-forget)
- 它只管往 Kafka 里面发送消息,但是不关心消息是否正确到达,这种方式的效率最高,但是可靠性也最差,比如当发生某些不可充实异常的时候会造成消息的丢失
- 2.同步(sync)
- producer.send()返回一个Future对象,调用get()方法变回进行同步等待,就知道消息是否发送成功,发送一条消息需要等上个消息发送成功后才可以继续发送
- 3.异步(async)
- Kafka支持 producer.send() 传入一个回调函数,消息不管成功或者失败都会调用这个回调函数,这样就算是异步发送,我们也知道消息的发送情况,然后再回调函数中选择记录日志还是重试都取决于调用方
3.手动提交位移
默认情况下,当消费者消费到消息后,就会自动提交位移。但是如果消费者消费出错,没有进入真正的业务处理,那么就可能会导致这条消息消费失败,从而丢失。我们可以开启手动提交位移,等待业务正常处理完成后,再提交offset。
服务端常规配置
broker加入集群需要的配置
主题的默认配置
如何选定分区的数量
硬件的选择
消费者和消费群组
深入了解kafka
服务端常规配置
broker.id:每个broker都需要一个标识符,在整个集群中必须唯一。
port: kafka服务的端口。
zookeeper.connect: zookeeper保存broker元数据地址。
log.dirs:kafka所有消息的保存目录。如果指定多个,broker会往拥有最少数目分区的路径中新增分区。最少使用原则。
num.recovery.threads.per.data.dir:指定服务端发生故障和关闭时多少线程执行保存数据。指定的数是针对log.dir指定的一个路径 路径。如果这个值配成3,那就是log.dir指定的每一个目录都会有三个线程进行保存数据。
auto.create.topics.enable:是否自动创建topic ,false不自动,ture自动创建
broker加入集群需要的配置
要把一个broker加入到集群,只需要修改两个配置参数。首先,所有的broker都必须配置相同的zookeeper.connect,该参数
指定了用于保存元数据的Zookeeper群组和路径。其次,每个broker都必须为broker.id参数设置唯一的值。
主题的默认配置
num.partitions:指定新创建的主题包含几个分区。为了负载均衡,可以多设置分区的个数。
log.retention.ms:指定数据可以保留多久。log.retention.hours和log.retention.minutes同样可以达到效果,
推荐使用 log.retention.ms ,如果指定多个kafka会优先使用时间最少的。默认值是168小时。
log.retention.bytes:保存的最大数据,如果主题有8个分区,这个值被设置为1GB那就是说这个主题可以保留8GB数据。
log.segment.bytes:设置分区日志片段到达多大关闭。日志片段不关闭就认为是新数据。就算到了数据保留的时间(168小时)
数据也不会删除。
log.segment.ms:设置分区日志片段多久关闭。
message.max.bytes:设置生产者单个消息的大小,默认值是1MB
如何选定分区的数量
为主题选定分区数量要严谨,需要考虑如下因素。
1.主题需要达到多大的吞吐量?例如,是希望每秒写入100KB还是1GB?
2.从单个分区读取数据的最大吞吐量是多少?每个分区一般都会有一个消费者,如果你知道消费者将数据写入数据库的速度不会超过
每秒50MB,那么你也该知道,从一个分区读取数据的吞吐量不需要超过每秒50MB.
3.可以通过类似的方法估算生产者向单个分区写入数据的吞吐量,不过生产者的速度一般比消费者快的多,
所以最好为消费者多估算一些吞吐量。
4.每个broker包含的分区个数,可用的磁盘空间和网络的带宽。
5.如果消息是按照不同的健来写入分区的,那么为已有的主题新增分区就会很困难。
6.单个broker对分区个数是有限制的,因为分区越多,占用的内存越多,完成首领选举需要的时间也越长。
硬件的选择
磁盘吞吐量和容量,内存,网络和cpu.
1.磁盘吞吐量和容量
选择传统的机械硬盘(HDD)还是固态硬盘(SSD),固态硬盘的查找和访问速度都很快,提供了最好的性能。
机械硬盘更便宜,单块硬盘容量大。在同一服务器上使用多个机械硬盘,可以设置多个数据目录,或者把它们设置成
磁盘阵列,这样可以提升机械硬盘的性能。其他方面的因素,比如磁盘特定的技术(穿行连接存储技术或SATA),或者
磁盘控制器的质量,都会影响吞吐量。
需要多大的磁盘容量取决于需要保存的消息数量。
2.内存
服务端可用的内存容量是影响客户端性能的主要因素。磁盘的性能影响生产者,而内存影响消费者。消费者一般从分区尾部
读取消息。
3.网络
网络吞吐量决定了kafka能够处理的最大数据流量。它和磁盘磁盘存储是制约kafka扩展规模的主要因素。
消费者和消费群组
消费者群组:kafka消费者从属于消费者群组。群组里的消费者消费的是同一个主题,每个消费者接受主题的一部分分区的消息。
多个消费者群组消费同一个topic的数据互不影响。
深入了解kafka
概念
1.kafka如何进行复制?
1) 集群成员关系
kafka使用zookeeper来维护集群成员的关系。每个broker都有一个唯一的标识符,这个标识符可以在配置文件里面指定,也可 以随机生成。在broker启动的时候,它通过创建临时节点把自己的id注册到zookeeper。kafka组件监听zookeeper的 /broker/ids 路径(broker的注册路径),当有broker加入集群或退出集群时,这些组件就可以获得通知。
如果启动相同唯一的标识符的broker就会错误。
在broker关闭,或发生网络卡钝时,broker在zookeeper创建的唯一标识符节点就会自动从zookeeper移除。但是这个唯 一 标识符还保存在其他数据结构中,如果使用相同唯一标识符的broker启动,它会立即加入集群。并拥有与旧broker相同的主题 和分区。
2)控制器(负责分区首领选举,broker加入和退出)
控制器就是一个broker,它除了拥有broker的功能之外还负责分区首领选举的工作(下面介绍分区首领选举)。第一个启动的 broker会在zookeeper注册一个临时节点 /controller让自己成为控制器,其他broker启动时也会注册这个节点,会收到一个节点 已经存在的消息。其他broker会创建一个监听这个节点的warch 对象,监听这个节点的动向(进行选举新的控制器),这样可 以保持只有一个控制器。
控制器用来监听broker的动向,发现zookeeper节点中broker的唯一标识符消失后,那些失去首领的分区需要一个新首领,控制 器遍历分区选出新的首领,然后向所有包含新首领或现有跟随者的broker发送谁是新首领以及跟随者的信息。随后,新首领开 始处理生产者和消费者的请求,跟随者从新首领那里复制数据。
当控制器发现新broker加入集群时。他会使用broker ID 来检查新加入的broker是否包含现有分区的副本,如果有,控制器就把 变更发送给新加入的broker和其他的broker,新broker上的副本就会从首领那里复制消息。
3)分区首领选举
kafka使用topic来保存数据,每个主题被分成若干个分区,每个分区有很多副本。那些副本被保存在broker上,每个broker可以 保存成百上千个属于不同主题和分区的副本。
首领用来和跟随者副本进行同步数据,当首领失效后,只有同步的副本有资格顶替。
分区一个一样的逻辑。有分区首领和分区跟随者。
2.kafka如何处理来自生产者和消费者的请求?
3.kakfa的存储细节,比如文件格式和索引?
1) 片段
2) 文件格式
是生产者传递消息的格式
3) 索引