目录
1.用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗?
13.Kafka消息是采用Pull模式,还是Push模式?(必考)
19.Netty和kafka都是用了零拷贝,那么零拷贝究竟是怎么实现的?底层原理是?
干货分享,感谢您的阅读!备注:针对基本问题做一些基本的总结,不是详细解答!
1.用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗?
常见的消息中间件
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题,实现高性能、高可用、可伸缩和最终一致性架构。
当前使用较多的消息队列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMQ等,而部分数据库如Redis、MySQL以及phxsql也可实现消息队列的功能。
Kafka主要特性、优缺点
Apache Kafka是一个分布式消息发布订阅系统。Kafka性能高效、可扩展良好并且可持久化。它的分区特性、可复制和可容错都是其不错的特性。
主要特性
- 快速持久化:可以在O(1)的系统开销下进行消息持久化;
- 高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
- 完全的分布式系统:Broker、Producer和Consumer都原生自动支持分布式,自动实现负载均衡;
- 支持同步和异步复制两种高可用机制;
- 支持数据批量发送和拉取;
- 零拷贝技术(zero-copy):减少IO操作步骤,提高系统吞吐量;
- 数据迁移、扩容对用户透明;
- 无需停机即可扩展机器;
- 其他特性:丰富的消息拉取模型、高效订阅者水平扩展、实时的消息订阅、亿级的消息堆积能力、定期删除机制;
优点
- 客户端语言丰富:支持Java、.Net、PHP、Ruby、Python、Go等多种语言;
- 高性能:单机写入TPS约在100万条/秒,消息大小10个字节;
- 提供完全分布式架构,并有replica机制,拥有较高的可用性和可靠性,理论上支持消息无限堆积;
- 支持批量操作;
- 消费者采用Pull方式获取消息。消息有序,通过控制能够保证所有消息被消费且仅被消费一次;
- 有优秀的第三方KafkaWeb管理界面Kafka-Manager;
- 在日志领域比较成熟,被多家公司和多个开源项目使用。
缺点
- Kafka单机超过64个队列/分区时,Load时会发生明显的飙高现象。队列越多,负载越高,发送消息响应时间变长;
- 使用短轮询方式,实时性取决于轮询间隔时间;
- 消费失败不支持重试;
- 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
- 社区更新较慢。
RabbitMQ主要特性、优缺点
RabbitMQ于2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。
主要特性
- 可靠性:提供了多种技术可以让你在性能和可靠性之间进行权衡。这些技术包括持久性机制、投递确认、发布者证实和高可用性机制;
- 灵活的路由:消息在到达队列前是通过交换机进行路由的。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果你有更复杂的路由需求,可以将这些交换机组合起来使用,你甚至可以实现自己的交换机类型,并且当做RabbitMQ的插件来使用;
- 消息集群:在相同局域网中的多个RabbitMQ服务器可以聚合在一起,作为一个独立的逻辑代理来使用;
- 队列高可用:队列可以在集群中的机器上进行镜像,以确保在硬件问题下还保证消息安全;
- 支持多种协议:支持多种消息队列协议;
- 支持多种语言:用Erlang语言编写,支持只要是你能想到的所有编程语言;
- 管理界面:RabbitMQ有一个易用的用户界面,使得用户可以监控和管理消息Broker的许多方面;
- 跟踪机制:如果消息异常,RabbitMQ 提供消息跟踪机制,使用者可以找出发生了什么;
- 插件机制:提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。
优点
- 由于Erlang语言的特性,消息队列性能较好,支持高并发;
- 健壮、稳定、易用、跨平台、支持多种语言、文档齐全;
- 有消息确认机制和持久化机制,可靠性高;
- 高度可定制的路由;
- 管理界面较丰富,在互联网公司也有较大规模的应用,社区活跃度高。
缺点
- 尽管结合 Erlang 语言本身的并发优势,性能较好,但是不利于做二次开发和维护;
- 实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点增加了延迟,消息封装后也比较大;需要学习比较复杂的接口和协议,学习和维护成本较高。
RocketMQ主要特性、优缺点
RocketMQ出自阿里的开源产品,用Java语言实现,在设计时参考了Kafka,并做出了自己的一些改进,消息可靠性上比Kafka更好。RocketMQ在阿里内部被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。
主要特性
- 基于队列模型:具有高性能、高可靠、高实时、分布式等特点;
- Producer、Consumer、队列都支持分布式;
- Producer向一些队列轮流发送消息,队列集合称为Topic。Consumer如果做广播消费,则一个Consumer实例消费这个Topic对应的所有队列;如果做集群消费,则多个Consumer 实例平均消费这个Topic对应的队列集合;
- 能够保证严格的消息顺序;
- 提供丰富的消息拉取模式;
- 高效的订阅者水平扩展能力;
- 实时的消息订阅机制;
- 亿级消息堆积能力;
- 较少的外部依赖。
优点
- 单机支持1万以上持久化队列;
- RocketMQ的所有消息都是持久化的,先写入系统PAGECACHE,然后刷盘,可以保证内存与磁盘都有一份数据,而访问时,直接从内存读取;
- 模型简单,接口易用(JMS的接口很多场合并不太实用);
- 性能非常好,可以允许大量堆积消息在Broker中;
- 支持多种消费模式,包括集群消费、广播消费等;
- 各个环节分布式扩展设计,支持主从和高可用;
- 开发度较活跃,版本更新很快。
缺点
- 支持的客户端语言不多,目前是Java及C++,其中C++还不成熟;
- RocketMQ社区关注度及成熟度也不及前两者;
- 没有Web管理界面,提供了一个 CLI (命令行界面) 管理工具带来查询、管理和诊断各种问题;
- 没有在MQ核心里实现JMS等接口;
ActiveMQ主要特性、优缺点
ActiveMQ是由Apache出品,ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的JMS Provider实现。它非常快速,支持多种语言的客户端和协议,而且可以非常容易的嵌入到企业的应用环境中,并有许多高级功能。
主要特性
- 服从JMS规范:JMS 规范提供了良好的标准和保证,包括:同步 或 异步 的消息分发,一次和仅一次的消息分发,消息接收和订阅等等。遵从JMS规范的好处在于,不论使用什么JMS实现提供者,这些基础特性都是可用的;
- 连接灵活性:ActiveMQ提供了广泛的连接协议,支持的协议有:HTTP/S,IP多播,SSL,TCP,UDP等等。对众多协议的支持让ActiveMQ拥有了很好的灵活性;
- 支持的协议种类多:OpenWire、STOMP、REST、XMPP、AMQP;
- 持久化插件和安全插件:ActiveMQ提供了多种持久化选择。而且,ActiveMQ的安全性也可以完全依据用户需求进行自定义鉴权和授权;
- 支持的客户端语言种类多:除了Java之外,还有:C/C++,.NET,Perl,PHP,Python,Ruby;
- 代理集群:多个ActiveMQ代理可以组成一个集群来提供服务;
- 异常简单的管理:ActiveMQ是以开发者思维被设计的。所以,它并不需要专门的管理员,因为它提供了简单又使用的管理特性。有很多中方法可以监控ActiveMQ不同层面的数据,包括使用在JConsole或者在ActiveMQ的WebConsole中使用JMX。通过处理JMX的告警消息,通过使用命令行脚本,甚至可以通过监控各种类型的日志。
优点
- 跨平台(JAVA编写与平台无关,ActiveMQ几乎可以运行在任何的JVM上);
- 可以用JDBC:可以将数据持久化到数据库。虽然使用JDBC会降低ActiveMQ的性能,但是数据库一直都是开发人员最熟悉的存储介质;
- 支持JMS规范:支持JMS规范提供的统一接口;
- 支持自动重连和错误重试机制;
- 有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权;
- 监控完善:拥有完善的监控,包括WebConsole,JMX,Shell命令行,Jolokia的RESTful API;
- 界面友善:提供的WebConsole可以满足大部分情况,还有很多第三方的组件可以使用,比如hawtio;
缺点
- 社区活跃度不及RabbitMQ高;
- 根据其他用户反馈,会出莫名其妙的问题,会丢失消息;
- 目前重心放到activemq6.0产品Apollo,对5.x的维护较少;
- 不适合用于上千个队列的应用场景;
2.消息中间件的组成有哪些?
- Broker:消息服务器,作为server提供消息核心服务
- Producer:消息生产者,业务的发起方,负责生产消息传输给broker
- Consumer:消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
- Topic:主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播
- Queue:队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收
- Message:消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输
3.消息中间件模式分类有哪些?(必考)
点对点:使用queue作为通信载体
消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。
消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
发布/订阅:使用topic作为通信载体
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。
topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者都能得到一个消息的拷贝。
4.分析消息中间件的普遍优势(必考)
- 系统解耦
交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低。
- 提高系统响应时间
例如原来的一套逻辑,完成支付可能涉及先修改订单状态、计算会员积分、通知物流配送几个逻辑才能完成;通过MQ架构设计,就可将紧急重要(需要立刻响应)的业务放到该调用方法中,响应要求不高的使用消息队列,放到MQ队列中,供消费者处理。
- 为大数据处理架构提供服务
通过消息作为整合,大数据背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持。
- Java消息服务——JMS
Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
JMS中的P2P和Pub/Sub消息模式:点对点(point to point, queue)与发布订阅(publish/subscribe,topic)最初是由JMS定义的。这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)。
5.消息中间件常用协议分析
- AMQP协议
AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
优点:可靠、通用
- MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。
优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统
- STOMP协议
STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。
优点:命令模式(非topic\queue模式)
- XMPP协议
XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。
优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大
6.消息队列应用场景分析(必考)
在实际应用中常用的使用场景:异步处理、应用解耦、流量削锋和消息通讯四个场景
场景一:异步处理
场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种 1.串行的方式;2.并行方式
- 串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。
- 并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。
假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。
因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150),并行方式处理的请求量是10次(1000/100)
小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?
引入消息队列,将不是必须的业务逻辑,异步处理。改造后的架构如下:
按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。
场景二:应用解耦
场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,缺点在于订单系统与库存系统耦合。
如何解决以上问题呢?引入应用消息队列后的方案,如下图:
- 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功
- 库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作
假如:在下单时库存系统不能正常使用,也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。
场景三:流量削锋
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列:可以控制活动的人数、可以缓解短时间内高流量压垮应用。用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面,秒杀业务根据消息队列中的请求信息,再做后续处理。
场景四:日志处理
日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。架构简化如下,
- 日志采集客户端:负责日志数据采集,定时写受写入Kafka队列
- Kafka消息队列:负责日志数据的接收,存储和转发
- 日志处理应用:订阅并消费kafka队列中的日志数据
查看新浪kafka日志处理应用案例:转自(http://cloud.51cto.com/art/201507/484338.htm)
- (1)Kafka:接收用户日志的消息队列
- (2)Logstash:做日志解析,统一成JSON输出给Elasticsearch
- (3)Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能
- (4)Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因
场景五:消息通讯
消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等
- 点对点通讯:客户端A和客户端B使用同一队列,进行消息通讯。
- 聊天室通讯:客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。
以上实际是消息队列的两种消息模式,点对点或发布订阅模式。模型为示意图,供参考。
7.Kafka数据如何保证不丢失?(必考)
Apache Kafka是一个分布式流处理平台,它提供了一些机制来保证数据在传输过程中不丢失。下面是Kafka保证数据不丢失的主要机制:
- 持久化存储:Kafka使用持久化存储来保存消息。消息被写入磁盘,因此即使在系统故障或重启后,消息仍然可靠地保留。Kafka使用顺序写入和零拷贝技术来提高磁盘写入性能,并确保消息的持久性。
- 复制机制:Kafka使用分布式的复制机制来保证数据的可靠性。每个主题的分区都可以配置为多个副本,每个副本都位于不同的Broker上。消息被复制到多个副本中,确保了数据的冗余和高可用性。如果某个Broker故障,其他副本仍然可以提供服务。
- ISR机制:Kafka使用ISR(In-Sync Replicas)机制来保证数据不丢失。ISR是指与主副本保持同步的副本集合。只有ISR中的副本才能被认为是“可靠的”,消息被写入ISR中的副本后,才被认为是已提交的。如果ISR中的副本出现故障或延迟,Kafka将等待它们恢复或追赶上来,以确保数据不丢失。
- 确认机制:Kafka使用生产者确认机制来确保消息的可靠传输。生产者发送消息后,可以选择等待Kafka的确认或异步发送消息。确认机制可以保证消息到达Kafka,并且生产者可以根据确认状态进行相应的处理。
- 数据复制策略:Kafka提供了多种数据复制策略,例如“全部副本”和“一部分副本”。在“全部副本”策略下,消息必须被所有副本确认后才被认为是已提交的。在“一部分副本”策略下,只需要少数副本确认即可。这样可以在数据可靠性和性能之间进行权衡。
- 数据备份和恢复:Kafka支持数据备份和恢复,可以设置合适的备份策略,定期备份数据到其他存储介质。在发生数据丢失或其他故障时,可以通过备份数据进行恢复,避免数据的永久丢失。
通过这些机制和策略,Kafka能够提供高度可靠的数据传输和存储,有效地保证数据在分布式环境中不丢失。
8.Kafka如何保证消息按顺序执行?(必考)
Kafka通过以下机制来保证消息按顺序执行:
- 分区机制:Kafka将主题划分为多个分区,并且每个分区中的消息是有序的。在同一个分区中,消息的顺序是保证的,即先入先出。通过分区机制,Kafka能够将消息按照顺序分布在不同的分区中,以实现消息的有序性。
- 消费者组:Kafka的消费者可以组成一个消费者组,每个分区只能由同一个消费者组中的一个消费者进行消费。这样,每个分区中的消息将由同一个消费者顺序地进行处理。在同一个消费者组中,Kafka会确保每个分区只被一个消费者消费,从而保证消息的有序执行。
- 分区分配策略:Kafka提供了不同的分区分配策略,用于将分区分配给消费者。其中一种常用的策略是"Range"(范围)策略,该策略将分区均匀地分配给消费者,从而保证消息在各个分区之间的顺序性。
- 分区顺序保证:在某些特定情况下,业务需要保证同一个分区内消息的严格顺序。在这种情况下,可以将分区数设置为1,将所有的消息都发送到同一个分区中,从而确保消息在分区内按照顺序执行。
需要注意的是,Kafka并不能保证跨分区的消息的全局顺序。由于Kafka的分区机制,不同分区的消息是并行处理的,因此在不同分区之间的消息顺序无法保证。如果业务需要全局有序性,可以考虑将相关消息发送到同一个分区,或者通过应用层面的逻辑进行排序和处理。
总之,通过分区机制、消费者组和分区分配策略,Kafka能够有效地保证消息按照顺序执行。根据业务需求,合理设置分区数和消费者组,选择合适的分区分配策略,可以进一步优化消息的有序性。
9.Kafka如何保证消息不重复消费?(必考)
Kafka通过以下机制来保证消息不重复消费:
- 唯一消费者组:在Kafka中,每个消费者都必须属于一个消费者组。每个分区只能由同一个消费者组中的一个消费者进行消费。这样,Kafka确保了每个分区中的消息只会被消费者组内的一个消费者处理。
- 消费者位移管理:Kafka使用消费者位移(offset)来标识消费者在分区中的位置。消费者从指定位移开始消费消息,并且在处理消息后,将位移提交到Kafka。Kafka会记录消费者的位移,并在消费者重新加入或发生故障恢复后,根据位移进行消息的恢复和继续消费。
- 自动位移提交和手动位移提交:Kafka提供了自动位移提交和手动位移提交两种位移管理方式。在自动位移提交模式下,Kafka会自动定期或在消费者提交位移后进行位移的提交。在手动位移提交模式下,消费者可以根据业务逻辑来控制何时提交位移。手动位移提交能够提供更细粒度的位移控制,从而更可靠地保证消息不重复消费。
- 消费者故障恢复:当消费者发生故障或重新加入消费者组时,Kafka会根据之前提交的位移来确定消费者在分区中的消费位置。这样即使消费者发生故障,Kafka也能够保证消费者从故障前的位移处继续消费消息,避免消息的重复消费。
- Exactly-Once语义支持:Kafka提供了Exactly-Once语义的支持,通过事务和幂等性等机制,确保消息在生产和消费过程中的精确一次性。这可以保证即使在发生故障或重试的情况下,消息也不会被重复消费。
需要注意的是,消息不重复消费在一些特定的场景中可能需要应用层面的逻辑来处理。例如,如果消息的处理过程中有写操作,可以通过记录处理状态或使用幂等性操作来保证消息的唯一性。
综上所述,通过消费者组、位移管理、故障恢复和Exactly-Once语义等机制,Kafka能够有效地保证消息不重复消费。根据业务需求,合理配置消费者组和位移提交方式,并结合应用层面的逻辑,可以进一步确保消息的可靠性和唯一性。
10.Kafka如何保证消息队列的高可用?(必考)
Kafka通过以下机制来提供高可用性的消息队列:
- 分布式架构:Kafka采用分布式架构,消息被划分为多个主题(topics)和分区(partitions),每个分区可以在集群中的多个Broker之间进行复制和分布。这种分布式架构提供了高可用性和容错性,即使其中一个Broker或节点发生故障,其他节点仍然可以继续服务。
- 副本机制:Kafka支持将每个分区的副本(replica)复制到多个Broker上。每个分区可以配置多个副本,其中一个为主副本(leader),其他为从副本(follower)。主副本负责处理读写请求,从副本通过复制主副本的数据来提供冗余和故障恢复。如果主副本发生故障,Kafka会自动从从副本中选举出一个新的主副本。
- ISR机制:Kafka使用ISR(In-Sync Replicas)机制来保证消息的可用性。ISR是指与主副本保持同步的副本集合。只有ISR中的副本才能被认为是“可靠的”,消息必须被写入ISR中的副本才被认为是已提交的。如果ISR中的副本出现故障或延迟,Kafka将等待它们恢复或追赶上来,以确保数据的可用性。
- 监控和自动平衡:Kafka提供了监控工具和自动平衡机制来监控集群的健康状态并进行故障恢复。通过监控和管理工具,可以实时监测Broker的状态和负载情况,并自动进行分区的重新分配和副本的选举,以实现负载均衡和故障恢复。
- 数据冗余和备份:Kafka支持数据的冗余和备份。每个分区的副本可以分布在不同的Broker上,即使其中一个Broker发生故障,其他副本仍然可以提供服务。此外,Kafka还支持将数据备份到其他存储介质,以提供更高级别的冗余和恢复能力。
- 水平扩展:Kafka可以通过添加更多的Broker节点来实现水平扩展。当消息流量增加时,可以添加更多的Broker来扩展集群的吞吐能力和存储容量,从而提供更好的可用性和可扩展性。
通过上述机制和策略,Kafka能够提供高可用性的消息队列。分布式架构、副本机制、ISR机制、监控和自动平衡、数据冗余和备份以及水平扩展等特性共同确保了消息队列的高可用性。
- 分布式架构和副本机制提供了容错能力,当某个Broker或节点发生故障时,其他节点仍然可以继续服务。
- ISR机制保证了消息的可用性,只有与主副本保持同步的副本才被认为是“可靠的”。
- 监控和自动平衡机制可以实时监测集群的状态,进行故障恢复、分区重新分配和副本选举,以实现负载均衡和故障恢复。
- 数据冗余和备份使得即使某个Broker发生故障,其他副本仍然可以提供服务,并且数据备份到其他存储介质,提供更高级别的冗余和恢复能力。
- 水平扩展允许通过添加更多的Broker节点来提高吞吐能力和存储容量,实现横向扩展。
综上所述,Kafka通过这些机制和策略来确保消息队列的高可用性。这些特性使得Kafka在处理大规模消息流和关键业务数据时能够提供可靠的消息传递保证,并保证系统的稳定性和可扩展性。
11.Kafka 如何保证可靠性?(必考)
总结起来,Kafka通过持久化存储、写入确认机制、副本机制、Exactly-Once语义支持和消费者位移管理等机制,提供了高度可靠的消息传递和处理能力。这使得Kafka成为处理大规模数据流和关键业务数据的可靠消息系统。
- 持久化存储:Kafka将消息持久化地存储在磁盘上,即使在发生故障或重启后,消息仍然可靠地存在。
- 写入确认机制:生产者可以选择等待写入确认后再发送下一条消息,以确保消息被成功写入Kafka。
- 副本机制:Kafka的副本机制提供了数据冗余和故障恢复能力。每个分区可以配置多个副本,主副本负责处理读写请求,从副本通过复制主副本的数据来提供冗余和故障恢复。
- Exactly-Once语义支持:Kafka提供了事务和幂等性等机制,确保消息在生产和消费过程中的精确一次性,避免重复或丢失。
- 消费者位移管理:Kafka使用消费者位移(offset)来标识消费者在分区中的位置,并根据位移进行消息的恢复和继续消费,从而保证消费的可靠性。
这些机制和特性结合起来,保证了Kafka的可靠性。然而,需要根据具体场景和需求进行合理的配置和使用。例如,选择合适的副本因子、确认级别和事务支持等,可以根据应用程序的要求来平衡性能和可靠性。
综上所述,Kafka通过多种机制来保证消息的可靠性,使得它在处理大规模数据流和关键业务数据时成为一个可靠的消息系统。
12.Kafka的文件存储机制
Kafka使用文件存储机制来持久化消息数据。下面是对Kafka文件存储机制的分析:
- 分区文件:Kafka中的消息被组织成一个个分区(partition),每个分区对应一个磁盘上的文件。每个分区文件以固定大小的片段(segment)进行存储,通常是一系列连续的文件片段。
- 文件片段(Segment):每个分区文件由多个文件片段组成,每个文件片段对应一个时间范围内的消息。文件片段的大小可以配置,通常为一定的存储容量或时间长度。当一个文件片段达到指定的大小或时间限制时,Kafka会创建一个新的文件片段。
- 日志索引:为了快速定位消息在分区文件中的位置,Kafka使用了日志索引。每个文件片段都有对应的日志索引文件,它包含了消息在文件片段中的偏移量(offset)和物理位置的索引。通过使用日志索引,Kafka可以快速定位和查找消息,提高读写的效率。
- 文件清理和压缩:Kafka通过一系列的策略来管理分区文件,包括文件清理和压缩。文件清理是指删除已经过时的文件片段,即已经被所有消费者消费完的文件片段。文件压缩是将多个文件片段合并为一个更大的文件,以减少存储空间和提高读写性能。
- 零拷贝技术:Kafka使用零拷贝(Zero-Copy)技术来提高数据的传输效率。在消息写入和读取过程中,Kafka避免了数据在内核空间和用户空间之间的多次拷贝,减少了CPU和内存的开销,提高了性能和吞吐量。
- 快速写入和追加:Kafka采用追加写入(Append-Only)的方式来存储消息。新的消息会被追加到分区文件的末尾,不涉及文件的修改和移动操作,提高了写入的效率。
通过以上文件存储机制,Kafka能够高效地持久化消息数据,并提供快速的读写能力。文件分段、日志索引、文件清理和压缩等策略和优化措施,进一步提升了Kafka的性能和存储效率。这使得Kafka在大规模的消息处理场景下具备了良好的可扩展性和可靠性。
13.Kafka消息是采用Pull模式,还是Push模式?(必考)
Kafka使用拉取(pull)模式来消费消息。这意味着消费者需要主动从Kafka服务器请求(拉取)消息,而Kafka服务器不会主动将消息推送给消费者。
在Kafka中,消费者通过向Kafka集群发送拉取请求来获取消息。消费者可以控制拉取的频率和批量大小,以适应自身的处理能力和需求。消费者发送的拉取请求会包含消费者的位移(offset),指定从哪个位置开始拉取消息。
这种拉取模式带来了一些好处:
- 灵活性:消费者可以根据自身的处理能力和速度来控制消息的消费速率,可以按需拉取消息,以避免处理能力不足或消息堆积的情况。
- 高吞吐量:拉取模式允许消费者一次性获取一批消息,减少了网络通信的开销,提高了吞吐量和效率。
- 随机访问:消费者可以根据自身需求选择从任意位置开始拉取消息,可以回溯到之前的位移,重新消费消息或者跳过一些消息。
- 延迟控制:消费者可以控制拉取请求的频率和批量大小,以平衡处理延迟和实时性的要求。
需要注意的是,虽然Kafka使用拉取模式来消费消息,但在实际应用中,可以结合其他机制,如长轮询(long polling)或基于时间的触发器,来实现近实时的消息推送效果。
总结起来,Kafka使用拉取模式来消费消息,消费者通过发送拉取请求来获取消息。这种模式带来了灵活性、高吞吐量、随机访问和延迟控制的优势,使得Kafka在处理大规模数据流和实时消息的场景下具备高效、可靠的特性。
14.Kafka是如何实现高吞吐率的?
- 顺序读写:kafka的消息是不断追加到文件中的,这个特性使kafka可以充分利用磁盘的顺序读写性能
- 零拷贝:跳过“用户缓冲区”的拷贝,建立一个磁盘空间和内存的直接映射,数据不再复制到“用户态缓冲区”
- 文件分段:kafka的队列topic被分为了多个区partition,每个partition又分为多个段segment,所以一个队列中的消息实际上是保存在N多个片段文件中
- 批量发送:Kafka允许进行批量发送消息,先将消息缓存在内存中,然后一次请求批量发送出去
- 数据压缩:Kafka还支持对消息集合进行压缩,Producer可以通过GZIP或Snappy格式对消息集合进行压缩
15.Kafka判断一个节点还活着的两个条件?
Kafka判断一个节点是否还活着通常依赖于两个条件:
- 心跳机制:Kafka使用心跳机制来检测节点的活跃状态。每个Broker节点会定期发送心跳信号给集群的控制器(Controller),以表示它仍然活着。如果一段时间内没有收到来自节点的心跳信号,Kafka会认为该节点不再活跃,并将其标记为失效。
- ISR(In-Sync Replicas)列表:ISR是指与Leader副本保持同步的副本集合。Kafka通过监测ISR列表来判断节点的活跃状态。如果一个节点的ISR列表中没有该节点的副本,说明该节点与集群的同步已经中断,Kafka会认为该节点不再活跃,并将其标记为失效。
这两个条件的结合可以帮助Kafka监测节点的状态,及时发现失效节点并进行相应的故障处理。当一个节点被标记为失效后,Kafka可以执行副本重分配和重新选举等操作,以确保集群的可用性和数据的一致性。
16.Kafka采用的拉取模式还是推送模式?两者有啥区别?
Kafka采用的是拉取(Pull)模式,而不是推送(Push)模式。下面是拉取模式和推送模式的区别:
拉取模式(Pull Model)
• 消费者主动发起拉取请求,向Kafka服务器请求获取消息。
• 消费者决定何时拉取消息,可以按照自己的处理能力和需求进行控制。
• 消费者可以按照自己的节奏和速率处理消息,可以批量拉取一定数量的消息。
• 消费者可以重复拉取、重试或跳过某些消息。
• 拉取模式可以根据消费者的处理能力进行动态的负载均衡,适应不同消费者的处理速度差异。
推送模式(Push Model)
• 消息由Kafka服务器主动推送给消费者。
• 消费者需要实时监听消息,无法主动控制消息的接收速度。
• 消费者需要实现长连接或使用轮询等方式进行实时监听。
• 如果消费者的处理能力跟不上消息的推送速度,可能会导致消息堆积或丢失。
区别:
• 主动性:拉取模式中,消费者主动发起拉取请求获取消息;推送模式中,消息由服务器主动推送给消费者。
• 控制能力:拉取模式中,消费者可以根据自身需要和处理能力决定何时拉取消息、以及拉取的数量;推送模式中,消费者无法主动控制消息的接收速度。
• 灵活性:拉取模式下,消费者可以根据需求进行消息的重试、跳过或重复拉取;推送模式下,消费者无法灵活地控制消息的处理。
• 适应性:拉取模式可以根据消费者的处理能力进行动态的负载均衡,适应不同消费者的处理速度差异;推送模式下,消息的推送速度无法根据消费者的处理能力进行调整。
Kafka选择采用拉取模式的主要原因是为了提供更好的灵活性和可控性,使消费者能够根据自身需求进行消息的拉取和处理,以适应不同的消费场景和消费者的处理能力。
17.如果流量突增导致MQ积压过高,该如何处理?
处理流量突增导致MQ(消息队列)积压过高的问题需要综合考虑多个因素,并采取适当的措施来解决。以下是一些可能的处理方法:
- 扩容MQ集群: 如果MQ集群的规模不够大,可以考虑增加节点或者扩容机器规格,以提高MQ集群的处理能力和吞吐量。
- 优化消费者端: 确保消费者端的处理能力足够强大,可以通过增加消费者数量或者优化消费者的代码逻辑来提高消费速度。
- 增加MQ Topic和分区: 将消息按照不同的Topic或分区进行划分,可以减少单一队列的压力,提高并行处理能力。
- 流量限制和流控机制: 在MQ生产者端和消费者端实施流量限制和流控机制,防止过多的消息涌入队列,同时防止消费者消费能力不足导致积压。
- 优化消息处理逻辑: 评估MQ消息处理逻辑,确保消费者处理消息的效率,避免不必要的复杂计算或资源浪费。
- 持久化设置: 确保MQ的消息持久化设置合理,避免消息丢失。
- 监控和报警: 设置监控和报警机制,实时监控MQ队列的积压情况,及时发现问题并采取措施。
- 灾备处理: 在极端情况下,如果MQ集群无法快速消化积压的消息,可以考虑设置灾备机制,将消息持久化到磁盘,保证数据不丢失,待MQ恢复正常后再进行处理。
以上方法中的选择和执行需要根据具体情况来决定,以及根据系统架构和业务需求来调整。同时,持续监控和性能优化也是保障系统稳定性的重要手段。
18. Kafka 什么情况下数据丢失?
Kafka 是一种分布式消息队列系统,具有高吞吐量和可靠性。但在某些情况下,数据可能会丢失。以下是一些导致 Kafka 数据丢失的常见情况:
- Producer 发送失败: 当 Kafka Producer 发送消息到 Kafka 集群时,如果遇到网络问题、Kafka 集群故障或其他异常情况,可能导致消息发送失败。在这种情况下,消息可能会丢失。
- Replica 副本不足: Kafka 通过复制数据来保障可靠性。如果某些分区的 Replica 副本数量不足,当 Leader 副本(主副本)出现故障时,无法保障数据可靠性。
- Producer 未设置acks=all: 如果 Kafka Producer 的 acks 配置未设置为 “all”,即等待所有 Replica 副本确认消息写入成功后再返回 ACK,那么在某些情况下可能出现数据丢失。
- 数据过期: 如果 Kafka Broker 配置了数据保留时间或者数据保留大小,当消息的时间戳超过保留时间或者数据大小超过限制时,消息会被删除,从而导致数据丢失。
- Producer 重试机制: 在某些情况下,Producer 可能会启用重试机制以确保消息发送成功。但是,如果设置的重试次数过少或者未启用重试机制,可能会导致数据在发送失败后被丢弃。
为了降低数据丢失的风险,可以考虑以下措施:
- 配置 Producer 的 acks 为 “all”,确保数据在 Leader 和所有 Replica 副本上写入成功后才返回 ACK。
- 设置合理的数据保留时间和大小,避免数据过期删除。
- 确保足够的 Replica 副本,保障数据的可靠性。
- 启用 Producer 的重试机制,设置适当的重试次数和重试时间间隔。
- 监控 Kafka 集群的状态,及时发现异常并采取相应措施。
19.Netty和kafka都是用了零拷贝,那么零拷贝究竟是怎么实现的?底层原理是?
零拷贝(Zero-copy)是一种优化技术,用于在数据传输过程中减少数据从一个应用程序到另一个应用程序的复制操作,从而提高数据传输的效率和性能。Netty和Kafka都使用了零拷贝技术,尽量减少数据在内存中的复制,从而降低CPU和内存开销。
底层实现零拷贝的关键技术包括以下几点:
- 操作系统提供的零拷贝特性:现代操作系统(例如Linux)提供了一些特性,如sendfile(网络发送文件)和mmap(内存映射文件),它们允许数据从一个文件传输到另一个文件或网络套接字,而不需要经过应用程序内存缓冲区。这样可以避免额外的复制操作,提高数据传输效率。
- Direct Memory Buffers:零拷贝技术还可以通过使用Direct Memory Buffers来避免数据复制。Direct Memory Buffers 是JVM提供的一种特殊类型的缓冲区,可以绕过Java堆内存,在堆外直接分配内存。通过将数据存储在堆外内存中,可以实现直接数据传输,避免了将数据从堆内存复制到堆外内存的操作。
- 文件描述符传递: 对于网络传输,零拷贝还可以通过文件描述符传递实现。在一些操作系统中,可以将一个文件描述符传递给另一个进程,从而避免数据在内核中的复制。
- Scattering和Gathering:这是一种将数据从多个源写入到单个目标或者从单个源读取到多个目标的方式,避免了中间数据的复制。
综合利用这些技术,Netty和Kafka等优化网络传输和数据处理的框架能够最大限度地减少数据复制,提高数据传输效率,从而实现更高的性能和吞吐量。这对于高性能的网络通信和数据处理非常重要。
20.导致MQ积压的原因有哪些?怎么应对?
消息队列(MQ)积压是指在消息队列中累积了大量未处理的消息,导致系统处理能力不足,影响正常的消息传递和处理。导致消息队列积压的原因可以有很多,以下是一些常见的原因和应对方法:
原因:
-
消费者处理速度慢: 消费者处理消息的速度比生产者生成消息的速度慢,导致消息堆积。
-
消费者故障: 消费者出现故障,停止了正常的消息处理,导致消息堆积。
-
消费者数量不足: 消费者的数量不足以处理消息的产生速度,导致积压。
-
生产者发送过快: 生产者发送消息的速度过快,超过了消费者的处理能力。
-
消息处理失败重试: 消息处理失败后会重试,如果重试失败,会导致消息不断堆积。
-
消息体积大: 如果消息体很大,会占用更多的存储空间,导致消息队列积压。
应对方法:
-
增加消费者数量: 增加消费者的数量,以提高消息处理的速度。
-
优化消费者处理逻辑: 优化消费者的处理逻辑,提升处理效率,减少处理时间。
-
监控和报警: 部署监控系统,及时发现消息积压问题,并设置报警机制。
-
消息处理失败策略: 设计合理的消息处理失败策略,避免消息无限重试,可以将处理失败的消息暂时移到死信队列中。
-
增加消息队列容量: 增加消息队列的容量,以适应高峰期的消息产生。
-
限流和熔断: 实施限流和熔断策略,避免过多的请求导致消息队列积压。
-
消息过期处理: 设置消息的过期时间,对于长时间未处理的消息进行清理,避免积压。
-
水平扩展: 根据需求进行消息队列的水平扩展,以提高处理能力。
-
定期清理: 定期清理过期的、无法处理的消息,以避免长期的积压。
综合上述方法,需要根据实际情况进行合理的调整和应对,以确保消息队列的稳定运行,避免积压问题影响整体系统性能。
参考书籍、文献和资料
1.https://www.cnblogs.com/Vito-Yan/p/10319826.html
2.https://blog.csdn.net/wqc19920906/article/details/82193316
3.https://www.jianshu.com/p/70c5b8d51c75
评论记录:
回复评论: