标签:扩展性 取消 经典 imageview 掌握 分区 strip 解决 别人
最近工作中呢,频频用到消息中心,包括异步转同步的功能,分布式收集日志信息等功能,在面试中也常会问到候选人关于消息中心的知识点,但大多数程序员,尤其是工作两三年的,虽然平时工作中都有用到消息中心,但都总是不能够说明白其中的原理,于是觉得有必要把消息中心作为一个篇章,专门进行总结梳理一番~看的时候,建议大家不妨先看看问题,自己先尝试回答一下,再看答案。看看自己掌握得如何了那准备好了的话,我们就要开始啦啊~消息中心,有以下几大作用:
1)日志信息收集记录我个人接触的项目中,Kafka使用最多的场景,就是用它与FileBeats和ELK组成典型的日志收集、分析处理以及展示的框架
该图为FileBeats+Kafka+ELK集群架构。Kafka在框架中,作为消息缓冲队列
FileBeats先将数据传递给消息队列,Logstash server(二级Logstash)拉取消息队列中的数据,进行过滤和分析,然后将数据传递给Elasticsearch进行存储,最后,再由Kibana将日志和数据呈现给用户
由于引入了Kafka缓冲机制,即使远端Logstash server因故障停止运行,数据也不会丢失,可靠性得到了大大的提升
2)用户轨迹跟踪:kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等操作,这些活动信息被各个服务器发布到kafka的topic中,然后消费者通过订阅这些topic来做实时的监控分析,当然也可以保存到数据库
3)运营指标:kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告
4)流式处理:比如spark streaming和storm
Kafka的消费者使用pull(拉)的方式将消息从broker中拉下来
1 这样做的好处是:
1)Kafka可以根据consumer的消费能力以适当的速率消费消息
2)消费者可以控制自己的消费方式:可以使用批量消费,也可以选择逐条消费
3)消费者还可以选择不同的提交方式来实现不同的传输语义,要是使用了push的方式,就没有这些优点了
2 缺点是:
会出现一种情况:如果Kafka没有数据,消费者会专门有个线程去等待数据,可能会陷入循环等待中
3 Kafka如何避免这一缺点:
我们可以通过在拉请求中设置参数,允许消费者请求在等待数据到达的“长轮询”中进行阻塞(并且可选地等待到给定的字节数,以确保大的传输大小)来避免这一问题
4 关于push的方式的话,它的优点是:
1)相对于pull的方式来说,它不需要专门有一个消息去等待,而可能造成线程循环等待的问题
2)它的缺点是: push(推)模式一般是会以同样的速率将消息推给消费者,很难适应消费速率不同的消费者,这样很容易造成有些消费能力比较低的consumer来不及处理消息,导致出现拒绝服务以及网络拥塞的情况
Kafka的数据会存储在zookeeper上。包括broker和消费者consumer的信息 其中,
broker信息:包含各个broker的服务器信息、Topic信息
消费者信息:主要存储每个消费者消费的topic的offset的值
总的来说,Kafka是分为三个角色:Producer、Kafka集群以及Consumer生产者将消息发送到Kafka集群,然后消费者再去Kafka集群进行消息的消费
稍微具体一点,就是下面这幅图
1)图中,除了包含前面说到的生产者Producer、Kafka集群以及消费者Consumer三个角色之外,还包含了用于存储信息的注册中心-Zookeeper
2)生产者:很明显,它是消息的生产者,用于发送消息的客户端
3)消费者:消息的消费者,用于消费消息的客户端。
4)消费者组:kafka的消费者角色,还有消费者组的概念,也就是说每个消费者组中可以包含多个consumer。其中,Kafka规定,消费者组中的消费者不能同时消费topic中的同一分区
比如说,图中,消费者组中包含Consumer A 和Consumer B两个,对于有两个分区的topic A,Consumer A消费了partition0,这时Consumer B就不能消费partition0的消息了,它只能消费partition1中的消息
延伸出消息如何保证顺序?
因为队列的先进先出的特点,保证了消息在发送的时候是有序的,而在同一个分区中,它是被一个消费者所消费的,那么它就也可以在一个分区中,保证消费消息时的顺序性。而在一个有两个及两个以上的topic内的话,就不能保证消息的顺序性了
因此,想要保证消息的顺序性,只在新建topic时,指定一个分区即可
5)Kafka集群:消息存储转发的地方,一般是集群的方式存在,而每个集群节点称为一个broker
6)Zookeeper:用于存储broker信息和消费者信息
7)broker:即Kafka集群的一台机器,可包含多个Topic
8)Topic : 主题,可以理解为一个队列
9)Partation:?队列Topic的分区,一个Topic可以分为多个分区,用于高并发场景的负载功能;实际上Topic只是一个逻辑概念,真正存在的是分区
10)Offset:即队列中当前读取消息的位置。顺便说一下,kafka的存储文件都是按照offset.kafka来命名,使用offset做名字,就方便查找。例如你想找位于2035的位置,只要找到2035.kafka的文件即可
无论消息是否被消费,kafka都会保留所有消息。而当消息的大小,大于设置的最大值log.retention.bytes(默认为1073741824)的值,也就是说这个缓冲池满了的时候,Kafka便会清除掉旧消息
那么它每次删除多少消息呢?
topic的分区partitions,被分为一个个小segment,按照segment为单位进行删除(segment的大小也可以进行配置,默认log.segment.bytes = 1024 1024 1024),由时间从远到近的顺序进行删除
此外,Kafka还支持基于时间策略进行删除数据,过期时间默认为:log.retention.hours=168
注意:因为Kafka读取特定消息的时间复杂度为O(1),即与文件大小无关,所以这里删除过期文件与提高 Kafka 性能无关
有以下三种:
这样,不可避免地存在一种可能:在记录offset之后,还没处理消息就出现故障了,新的consumer会继续从这个offset处理,那么就会出现有些消息永远不会被处理。那么这种机制,就是消息最多被处理一次
最少一次:consumer可以先读取消息,处理消息,最后记录offset
当然如果在记录offset之前就crash了,新的consumer会重复的消费一些消息。那么这种机制,就是消息最多被处理一次
精确一次:可以通过将提交分为两个阶段来解决:保存了offset后提交一次,消息处理成功之后再提交一次。当然也可以直接将消息的offset和消息被处理后的结果保存在一起,这样就能够保证消息能够被精确地消费一次
以下几个阶段,都有可能会出现消息丢失的情况
1)消息发送的时候,如果发送出去以后,消息可能因为网络问题并没有发送成功
2)消息消费的时候,消费者在消费消息的时候,若还未做处理的时候,服务挂了,那这个消息不就丢失了
3)分区中的leader所在的broker挂了之后
我们知道,Kafka的Topic中的分区Partition是leader与follower的主从机制,发送消息与消费消息都直接面向leader分区,并不与follower交互,follower则会去leader中拉取消息,进行消息的备份,这样保证了一定的可靠性
但是,当leader副本所在的broker突然挂掉,那么就要从follower中选举一个leader,但leader的数据在挂掉之前并没有同步到follower的这部分消息肯定就会丢失掉
Kafka的性能好在两个方面:顺序写和零拷贝
1)顺序写
我们知道,操作系统每次从磁盘读写数据的时候,都需要找到数据在磁盘上的地址,再进行读写。而如果是机械硬盘,寻址需要的时间往往会比较长
而一般来说,如果把数据存储在内存上面,少了寻址的过程,性能会好很多;但Kafka 的数据存储在磁盘上面,依然性能很好,这是为什么呢?
这是因为,Kafka采用的是顺序写,直接追加数据到末尾。实际上,磁盘顺序写的性能极高,在磁盘个数一定,转数一定的情况下,基本和内存速度一致
因此,磁盘的顺序写这一机制,极大地保证了Kafka本身的性能
2)零拷贝
比如:读取文件,再用socket发送出去这一过程
buffer = File.read
Socket.send(buffer)
传统方式实现:
先读取、再发送,实际会经过以下四次复制
传统方式,读取磁盘文件并进行网络发送,经过的四次数据copy是非常繁琐的
重新思考传统IO方式,会注意到在读取磁盘文件后,不需要做其他处理,直接用网络发送出去的这种场景下,第二次和第三次数据的复制过程,不仅没有任何帮助,反而带来了巨大的开销。那么这里使用了零拷贝,也就是说,直接由内核缓冲区Read Buffer将数据复制到网卡,省去第二步和第三步的复制。
这样必定会大大减少读取的开销,使得Kafka读取消息的性能有一个质的提升
总而言之
本次文章通过10个常见的Kafka经典面试题,带大家再次重新学习了一次Kafka,相信大家能够掌握得更深入一些了。
想想自己当年在毕业第一年,实际上就已经开始使用Kafka了,但是当时就只知道它是个消息中心,对于它的特点啊,原理啊一无所知;第二年,因为要做新项目,有机会了解了一下,大概知道了它的框架,一些基本概念,但当时的学习,也还只是照本宣科,网上说多少是可以得到多少,但很多东西根本没法消化,记了很多笔记也总是没法给别人讲得特别清楚;直到现在,有了一定的学习和实战经验,再去看它,你会发现似乎一切都变得简单,你的脑子里很容易就出现了它的架构全局,它的一些特点,对于它的一些设计思路表示亲切与赞赏。而且很多东西,在看的时候,你会觉得更轻松,也会有一些自己的理解,并且基本不用做太多的笔记,便可以很快理解它的原理,因为这次是真正地学会了
所以,每个阶段都有每个阶段该做的事,可能正因为之前的填鸭式地学习基础,才会有今天的快速理解的效果。不断学习才是真理,它会让你不断发现惊喜,包括对外界的,也包括对你自己的
掌握这10个常见的Kafka经典面试题,你还怕被问消息中心吗?
标签:扩展性 取消 经典 imageview 掌握 分区 strip 解决 别人
原文地址:https://blog.51cto.com/14570694/2530757