这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天 本次笔记将记录Kafka
什么是Kafka
Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写,Linkedin于2010年贡献给了Apache基金会并成为顶级开源 项目。
Kafka特性
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒
- 可扩展性:kafka集群支持热扩展
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
- 高并发:支持数千个客户端同时读写
Kafka的应用
- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
- 消息系统:解耦和生产者和消费者、缓存消息等。
- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
- 流式处理:比如spark streaming和storm
- 事件源
Kafka架构原理
注:每个broker可以看成一个服务器,每个服务器存储这一些topic,这些topic可以是follower或者leader,leader是主存储,follower是用来备份的,加入leader1是某个主存储,follower1是leader1的备份,那么follower1一定不能与leader1在同一个broker内。也就是说leader与它的follower们必须都是在不同broker里!
名词解释
- Producer:Producer即生产者,消息的产生者,是消息的入口。
- Broker:Broker是kafka实例,每个服务器上有一个或多个kafka的实例。每个kafka集群内的broker都有一个不重复的编号,如图中的broker-0、broker-1等……
- Topic:消息的主题,消息的分类,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。每个topic要么是leader,要么是follower。
- Partition:Topic的分区,每个topic可以有多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式就是每一个文件夹
- Replication:每一个分区都有多个副本。当主分区(Leader)故障的时候会选择一个Follower上位,成为Leader。在kafka中默认副本的最大数量是10个,且副本的数量不能大于Broker的数量,follower和leader是在不同的机器,同一机器对同一个分区也只可能存放一个副本。
- Message:每一条发送的消息主体。
- Consumer:消费者,即消息的消费方,是消息的出口。
- Consumer Group:将多个消费组组成一个消费者组,在kafka的设计中同一个分区的数据只能被消费者组中的某一个消费者消费。同一个消费者组的消费者可以消费同一个topic的不同分区的数据,这也是为了提高kafka的吞吐量!
- Zookeeper:kafka集群依赖zookeeper来保存集群的的元信息,来保证系统的可用性。
工作流程
图片来自CSDN,blog.csdn.net/wanghailan1…
1、producer会在broker(kafuka实例)里面寻找leader(某个topic),再讲消息保存到kafka
2、然后对应follower(副本)主动拉取leader所写的消息进行备份
3、备份完成后,follower发送成功信息ACK给leader
4、leader收到所有follower发送的ACK后,再发送成功信息ACK给producer
5、producer收到ACK后继续寻找leader发送消息
注:roducer采用push模式将数据发布到broker,每条消息追加到分区中,顺序写入磁盘,所以保证同一分区内的数据是有序的。
kafka保存消息到本地
partition(文件夹)
每个topic可以分为一个或多个partition,Partition在服务器上的表现形式就是文件夹,每个partition的文件夹下面会有多组segment文件,每组segment文件又包含.index文件、.log文件、.timeindex文件(早期版本中没有)三个文件, log文件就实际是存储message的地方,而index和timeindex文件为索引文件,用于检索消息。
文件的命名是以该segment最小offset来命名的,如000.index存储offset为0~368795的消息,kafka就是利用分段+索引的方式来解决查找效率的问题(二分法)。
Message结构
message就是要保存的消息数据,message的主要结构如下:
- offset:offset是一个占8byte的有序id号,它可以唯一确定每条消息在parition内的位置!
- 消息大小:消息大小占用4byte,用于描述消息的大小。
- 消息体:消息体存放的是实际的消息数据(被压缩过),占用的空间根据具体的消息而不一样。
consumer获取消息
Kafka采用的是发布订阅模式,消费者主动的去kafka集群拉取消息,与producer相同的是,消费者在拉取消息的时候也是找leader去拉取。
发布订阅模式
发布订阅模式是一个基于消息送的消息传送模型,改模型可以有多种不同的订阅者。生产者将消息放入消息队列后,队列会将消息推送给订阅过该类消息的消费者(类似微信公众号)。由于是消费者被动接收推送,所以无需感知消息队列是否有待消费的消息。
多个消费者可组成一个消费者组(consumer group),每个消费者组都有一个组id。同一组的消费者可消费同一topic下不同分区的数据,但是不会组内多个消费者消费同一分区的数据
也就是说,一组consumer可以消费同一个topic,但不能消费同一个topic下面的同一个partition
如上图,consumer小于partition的数量时,某个consumer会读取多个partition,从而降低性能,所以建议消费者组的consumer的数量与partition的数量一致
consumer如何查找数据
-
先找到offset的368801message所在的segment文件(利用二分法查找),这里找到的就是在第二个segment文件。
-
打开找到的segment中的.index文件(也就是368796.index文件,该文件起始偏移量为368796+1,我们要查找的offset为368801的message在该index内的偏移量为368796+5=368801,所以这里要查找的相对offset为5)。由于该文件采用的是稀疏索引的方式存储着相对offset及对应message物理偏移量的关系,所以直接找相对offset为5的索引找不到,这里同样利用二分法查找相对offset小于或者等于指定的相对offset的索引条目中最大的那个相对offset,所以找到的是相对offset为4的这个索引。
-
根据找到的相对offset为4的索引确定message存储的物理偏移位置为256。打开数据文件,从位置为256的那个地方开始顺序扫描直到找到offset为368801的那条Message。
参考文章:https://blog.csdn.net/wanghailan1818/article/details/125166287