一、概念和初识
1、简介和特征
- 由Apache软件基金会开发的开源六处理平台;
- scala和java编写的;
- 高吞吐量
- 分布式
- 发布订阅消息系统
2、应用场景:
采集用户在网站中的动作流数据;
物联网设备采样信息;
3、作用:
数据缓冲
异步通讯
架构解耦
消息订阅发布
4、Message Queue的两种工作模式
(1)至多一次:生产者写入数据,由消费者去拉取数据,一旦消息被消费,消息服务器删除数据,保证不重复消费;
(2)没有限制:生产者写入消息,消费者可能被多个消费者消费,消消费消息的偏移量,消息可以长时间保息服务器仅仅是保存消费者存,每个消费者之间互不影响,在大数据场景使用多
二、kafka的基础架构
1、一般情况下Kafka是以集群的形式搭建的,即有多个kafka的broker,由Zookeeper来协调选举leader节点,其他的是fllower节点;
2、以topic模式负责分类集群的中record,topic可以理解为一种通讯模式,在逻辑上属于一类消息;实际kafka会根据topic的配置将消息发送到topic下的partition里面;
3、理解几个概念:
zookeeper:分布式协调框架
broker:服务节点
product:生产者
consume:消费者
topic:主题
partition:分区
record:消息记录,日志默认保存168小时,7天;
leader:主节点,负责读写
follower:从节点,主要是备份
4、kafka的逻辑架构:
(1)kafka从整体上分为生产者、消费者和kafka集群(一般情况下都是集群);
(2)生产者和消费者都属于客户端(client),kafka集群属于服务端(server);
(3)kafka集群主要由2个部分,zookeeper分布式协调框架和多个broker节点,其中zk负责监控和leader选举,选举出来的leader节点负责消息的读写操作,follower节点负责数据备份;
(4)当消息从生产者发送到kafka集群的时候,会根据指定topic,将消息发送到server端;
(5)一条消息(record)包含三个部分:key:唯一id,value:消息内容,timestamp:消息产生的系统时间;
(6)一个topic下,可能有多个pattition分区;当消息发送到toipc时,默认情况下,hash(key)% 分区个数=消息将存在topic的哪个分区;也可以采用轮询的方式进行消息发送到分区;
(7)同时,每个partition会根据服务器节点,生成多个副本,消息(record)除了存储在leader节点上,还会将副本消息存储到每一个follower节点上;
(8)当zk监控到leader节点发生故障不可用时,会在剩下的follower节点上选举出新的leader,并且将副本上的消息进行恢复,重新对外提供读写服务
(9)存在问题:当zk进行leader选举时,会出现消息丢失或者数据不同步的问题;
存储逻辑说明:
- 当生产者发送消息01,根据key计算出partition为1,则kafka会将消息存入broker-01号节点的partition1,并将该节点设置为消息01的主节点;同时将消息同步给broker-02里面的partition2和broker-03里面的partition3作为该消息的副本;
- 当生产者再次发送消息02,根据key计算出partition为2时,则kafka会将消息存入broker-02号节点的partion1,并将该节点设置为消息02的主节点;同时将消息同步给broker-01里面的partition2和broker-03里面的partition2作为该消息的副本;
- 当生产者再次发送消息03,根据key计算出partition为3时,则kafka会将消息存入broker-03号节点的partion1,并将该节点设置为消息03的主节点;同时将消息同步给broker-01里面的partition3和broker-02里面的partition3作为该消息的副本;
三、分区:topic是以分区组的形式来存储数据的
虽然kafka牺牲了topic的顺序,但增加了分区,加大了topic的并发,以及单个topic的数据存储量;
1、消费者在消费数据时,会维护本次消费对应的分区偏移量,然后批量向kafka提交这些偏移量,也就是说,这个偏移量完全右消费者控制,消费者之间相互独立;
2、实现分区的目的:
这种分区设计使得kafka服务器既可充当某些分区的leader,也可以是follower,使得负载得到很好的平衡;
日志的扩展得到最大程度的发挥;加大并发量和存储海量数据,分区越多,能存储越多的数据
四、消费者和消费组
- 一个消费者必须属于一个消费组;
- 消费者使用Consumer Group名称来标记自己;
- kafka会将消息发送给ConsumerGroup,具体ConsumerGroup根据什么原则去将消息分配给消费者实例,由Group的分配原则决定;
- ConsumerGroup可以理解为逻辑的订阅者,有多个消费者实例,
- 可以实现消费端性能伸缩性(可扩展),也可以实现容错(一个消费者挂了可以有其他的实例来消费);
- 同一个消费组内的实例对同一个topic的partition是均分实现的,也就是说topic1下的partition1只会把消费发送到ConsumerGroup下的消费者实例1,不会把消息既发送给ConsumerGroup1下的消费者实例1,又发送给消费者实例2;在消费组内不会存在消息重复消费;
- 但是不同的消费组是广播模式,比如ConsumerGroup2也订阅了topic1,则Topic1下的partition1也会将消息发送给ConsumerGroup2下的消费者实例1;
五、顺序写入和ZeroCopy:(高性能之道,根据官方的基准测试,每秒在2百万的写入(廉价机器)
1、高性能写入原理:
问题:kafka用了磁盘写入还能保持那么高的性能是为什么?
顺序写入:kafka会把收到的消息写入磁盘,保证数据不丢失,一般情况下,写数据到磁盘经历磁盘寻址和写入,而对磁盘而言,寻址是机械动作,效率很低;因此kafka采用顺序写入,顺序I/O,顺序寻址,提升效率;
优势:
- 顺序读写磁盘的速度超过内存随机读写;(即使磁盘顺序读写再快也不可能高于内存顺序读写?-->充分利用现代操作系统的页缓存(MMFiles))
- 如果写入JVM,占用内存并且需要GC;
- 磁盘可以保证数据持久化;
- 可以把partition理解为一个文件,而每次消息写入都是在文件末尾追加;
- 而文件是保存在磁盘的,不会删除;
- 缺陷:文件不删除,磁盘总会有被写满的时候?
Memory Mapped Files:(简称MMFiles)
MMFiles可以理解为一个文件(本来也是一个文件),是一个内存映射文件,在64位操作系统中,MMFiles文件可以表示20G大小的数据;
MMFiles的工作原理:利用操作系统的Page实现文件到物理内存的映射;kafka会提前开辟一块磁盘空间,将磁盘空间映射到PageCache(内核空间);写入的时候只写到PageCache即可返回;
kafka完成MMFiles后,对内存的所有操作都会被操作系统自动刷新到磁盘,降低用户程序到内存再到磁盘的IO操作;
问题:既然MMFiles是内存映射文件,如果重启,数据丢失怎么办?
kafka提供了配置参数producer.type,在生产者中配置是否马上flush磁盘;
如果是,则product发送后马上flush磁盘,称为同步发送(sync),如果否,则发送后立即返回,由操作系统去flush磁盘,称为(async);
kafka应用程序-->PageCache(内核空间)--->磁盘;两个阶段都会导致数据丢失;
保证消息不丢失会导致性能下降,而要保证性能,则会导致数据少量丢失
2、高性能读取原理:
了解概念:ZeroCopy零拷贝
用户空间:操作系统以上的,应用程序使用的内存空间叫用户空间
内核空间:操作系统以下,操作硬件的,叫内核空间;
正常情况下,读取磁盘的数据走以下流程:
磁盘--cp-->内核空间--cp--> 用户空间--cp-->网络IO协议发送数据
至少要经过4次数据拷贝;
面试题:Kafka为什么快?读写快,从以下三个方面去分析:
分区和日志;
顺序写入和MMFile;
ZeroCopy: