阿里妹导读
本文是技术人面试系列Kafka篇,面试中关于Kafka都需要了解哪些基础?一文带你详细了解,欢迎收藏!
消息队列的作用:异步、削峰填谷、解耦
中小型公司,技术挑战不是特别高,用 RabbitMQ (开源、社区活跃)是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ(Java二次开发) 是很好的选择。
如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。
RabbitMQ开始是用在电信业务的可靠通信的,也是少有的几款支持AMQP协议的产品之一。
优点:
缺点:
RocketMQ借鉴了Kafka的设计并做了很多改进,几乎具备了消息队列应该具备的所有特性和功能。
缺点:
跟周边系统的整合和兼容不是很好。
高可用,几乎所有相关的开源软件都支持,满足大多数的应用场景,尤其是大数据和流计算领域,
Kafka的数据单元称为消息。可以把消息看成是数据库里的一个“数据行”或一条“记录”。
批次
为了提高效率,消息被分批写入Kafka。提高吞吐量却加大了响应时间。
主题Topic
通过主题进行分类,类似数据库中的表。
分区Partition
Topic可以被分成若干分区分布于kafka集群中,方便扩容单个分区内是有序的,partition设置为一才能保证全局有序
副本Replicas
每个主题被分为若干个分区,每个分区有多个副本。
生产者Producer
生产者在默认情况下把消息均衡地分布到主题的所有分区上:
消费者Comsumer
消费者通过偏移量来区分已经读过的消息,从而消费消息。把每个分区最后读取的消息偏移量保存在Zookeeper 或Kafka上,如果消费者关闭或重启,它的读取状态不会丢失。
消费组ComsumerGroup
消费组保证每个分区只能被一个消费者使用,避免重复消费。如果群组内一个消费者失效,消费组里的其他消费者可以接管失效消费者的工作再平衡,重新分区。
节点Broker
连接生产者和消费者,单个broker可以轻松处理数千个分区以及每秒百万级的消息量。
集群
每隔分区都有一个首领,当分区被分配给多个broker时,会通过首领进行分区复制。
生产者Offset
消息写入的时候,每一个分区都有一个offset,即每个分区的最新最大的offset。
消费者Offset
不同消费组中的消费者可以针对一个分区存储不同的Offset,互不影响。
LogSegment
How Kafka
优点
应用场景
Leader选举
假设某个topic有N+1个副本,kafka可以容忍N个服务器不可用,冗余度较低
如果ISR中的副本都丢失了,则:
副本消息同步
首先,Follower 发送 FETCH 请求给 Leader。接着,Leader 会读取底层日志文件中的消 息数据,再更新它内存中的 Follower 副本的 LEO 值,更新为 FETCH 请求中的 fetchOffset 值。最后,尝试更新分区高水位值。Follower 接收到 FETCH 响应之后,会把消息写入到底层日志,接着更新 LEO 和 HW 值。
相关概念:LEO和HW。
Rebalance
leader选举完成后,当以上三种情况发生时,Leader根据配置的RangeAssignor开始分配消费方案,即哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案封装进SyncGroup请求中发给coordinator,非leader也会发SyncGroup请求,只是内容为空。coordinator接收到分配方案之后会把方案塞进SyncGroup的response中发给各个consumer。这样组内的所有成员就都知道自己应该消费哪些分区了。
分区分配算法RangeAssignor
增删改查
kafka-topics.sh --zookeeper localhost:2181/myKafka --create --topic topic_x --partitions 1 --replication-factor 1kafka-topics.sh --zookeeper localhost:2181/myKafka --delete --topic topic_xkafka-topics.sh --zookeeper localhost:2181/myKafka --alter --topic topic_x --config max.message.bytes=1048576kafka-topics.sh --zookeeper localhost:2181/myKafka --describe --topic topic_x
如何查看偏移量为23的消息?
通过查询跳跃表ConcurrentSkipListMap,定位到在00000000000000000000.index ,通过二分法在偏移量索引文件中找到不大于 23 的最大索引项,即offset 20 那栏,然后从日志分段文件中的物理位置为320 开始顺序查找偏移量为 23 的消息。
切分文件
保证在消息重发的时候,消费者不会重复处理。即使在消费者收到重复消息的时候,重复处理,也要保证最终结果的一致性。所谓幂等性,数学概念就是:f(f(x)) = f(x)
如何实现?
添加唯一ID,类似于数据库的主键,用于唯一标记一个消息。
ProducerID:#在每个新的Producer初始化时,会被分配一个唯一的PIDSequenceNumber:#对于每个PID发送数据的每个Topic都对应一个从0开始单调递增的SN值
如何选举
可用性
因集群架构变动导致的消费组内重平衡,如果kafka集内节点较多,比如数百个,那重平衡可能会耗时导致数分钟到数小时,此时kafka基本处于不可用状态,对kafka的TPS影响极大。
产生的原因:
订阅主题的分区数发生变化
组成员崩溃和组成员主动离开是两个不同的场景。因为在崩溃时成员并不会主动地告知coordinator此事,coordinator有可能需要一个完整的session.timeout周期(心跳周期)才能检测到这种崩溃,这必然会造成consumer的滞后。可以说离开组是主动地发起rebalance;而崩溃则是被动地发起rebalance。
解决方案:
加大超时时间 session.timout.ms=6s加大心跳频率 heartbeat.interval.ms=2s增长推送间隔 max.poll.interval.ms=t+1 minutes
目前,Kafka 使用 ZooKeeper 存放集群元数据、成员管理、Controller 选举,以及其他一些管理类任务。之后,等 KIP-500 提案完成后,Kafka 将完全不再依赖于 ZooKeeper。
一言以蔽之:KIP-500 ,是使用社区自研的基于 Raft 的共识算法,实现 Controller 自选举。同样是存储元数据,这几年基于Raft算法的etcd认可度越来越高。
越来越多的系统开始用它保存关键数据。比如,秒杀系统经常用它保存各节点信息,以便控制消费 MQ 的服务数量。还有些业务系统的配置数据,也会通过 etcd 实时同步给业务系统的各节点,比如,秒杀管理后台会使用 etcd 将秒杀活动的配置数据实时同步给秒杀 API 服务各节点。
Kafka 只有 Leader 副本才能 对外提供读写服务,响应 Clients 端的请求。Follower 副本只是采用拉(PULL)的方 式,被动地同步 Leader 副本中的数据,并且在 Leader 副本所在的 Broker 宕机后,随时准备应聘 Leader 副本。
if (maxOffset - curOffset > 100000) { // TODO 消息堆积情况的优先处理逻辑 // 未处理的消息可以选择丢弃或者打日志 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}// TODO 正常消费过程return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
需要支持快速水平扩容,broker+partition,partition放不同的机器上,增加机器时将数据根据topic做迁移,分布式需要考虑一致性、可用性、分区容错性
性能上,可以借鉴时间轮、零拷贝、IO多路复用、顺序读写、压缩批处理。
Copyright© 2013-2019