0f68a64829
Deploy Examination / deploy (push) Successful in 10s
Subtopics: - distributed-microservice: 45 questions (分布式微服务架构) - message-queue: 45 questions (消息队列) - k8s-observability: 45 questions (K8s与可观测性) - go-java-concurrency: 45 questions (Go/Java并发模型) - database-advanced: 35 questions (数据库进阶) - ai-engineering: 35 questions (AI工程实践) Question types: single_choice, true_false, fill_blank, short_answer, code_reading
308 lines
21 KiB
JSON
308 lines
21 KiB
JSON
{
|
||
"topic": "message-queue",
|
||
"type": "single_choice",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-09T10:30:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "sc-001",
|
||
"type": "single_choice",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"kafka",
|
||
"partition"
|
||
],
|
||
"question": "在 Kafka 中,一个 Topic 被分为多个 Partition,以下关于 Partition 的描述正确的是?",
|
||
"options": {
|
||
"A": "Partition 内的消息是全局有序的",
|
||
"B": "每个 Partition 内的消息是有序的,但不同 Partition 之间不保证顺序",
|
||
"C": "Partition 的数量在创建 Topic 时固定后不可更改",
|
||
"D": "每条消息会被广播到所有 Partition"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Kafka 的 Partition 是消息的物理分片单元,每个 Partition 内部的消息按照写入顺序严格有序(通过 offset 标识),但不同 Partition 之间不保证全局顺序。A 错误:全局有序需要只有一个 Partition。C 错误:Kafka 从 1.0 版本起支持动态增减 Partition 数量(但不能减少到低于当前最大 offset)。D 错误:消息通过分区器(Partitioner)根据 key 的 hash 值路由到特定的单个 Partition,而非广播。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-002",
|
||
"type": "single_choice",
|
||
"difficulty": 1,
|
||
"tags": [
|
||
"dead-letter-queue"
|
||
],
|
||
"question": "关于消息队列中的死信队列(Dead Letter Queue),以下说法正确的是?",
|
||
"options": {
|
||
"A": "死信队列中的消息会自动删除,无法再次消费",
|
||
"B": "死信队列用于存放消费失败且重试次数耗尽的消息",
|
||
"C": "死信队列只能由消息中间件自动创建,不支持手动配置",
|
||
"D": "死信队列中的消息优先级一定低于正常队列"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "死信队列(DLQ)的核心作用是存放因消费失败(如格式错误、业务异常、消费超时等)且重试次数耗尽而无法正常消费的消息,便于后续人工排查或修复后重新投递。A 错误:DLQ 中的消息默认持久化保存,消费者可以再次消费或由运维人员处理。C 错误:大多数消息中间件(如 RocketMQ、RabbitMQ)都支持手动配置死信队列的名称和策略。D 错误:死信队列没有自动降低优先级的说法,它的优先级取决于消费者的消费顺序。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-003",
|
||
"type": "single_choice",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"kafka",
|
||
"rocketmq",
|
||
"pulsar"
|
||
],
|
||
"question": "以下关于 Kafka、RocketMQ 和 Pulsar 的对比,描述正确的是?",
|
||
"options": {
|
||
"A": "三者都采用 Broker + 存储耦合的架构设计",
|
||
"B": "Pulsar 采用计算与存储分离的架构,支持多租户和分层存储",
|
||
"C": "RocketMQ 的吞吐量一定高于 Kafka",
|
||
"D": "Kafka 原生支持事务消息,而 RocketMQ 不支持"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Pulsar 采用 BookKeeper 作为存储层、Broker 作为计算层的分离架构,天然支持多租户命名空间和分层存储(将冷数据卸载到 S3 等对象存储)。A 错误:Pulsar 是计算存储分离的,Kafka 和 RocketMQ 是存储耦合的。C 错误:Kafka 在高吞吐场景(日志收集、大数据流处理)中吞吐量通常优于 RocketMQ;RocketMQ 的优势在于低延迟和丰富的消息特性(如事务消息、延迟消息)。D 错误:Kafka 从 0.11 版本开始支持事务(Exactly-Once 语义),RocketMQ 也原生支持事务消息(半消息机制),两者都支持。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-004",
|
||
"type": "single_choice",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"consumer-group"
|
||
],
|
||
"question": "关于 Consumer Group 的行为,以下说法正确的是?",
|
||
"options": {
|
||
"A": "同一个 Consumer Group 内的不同消费者可以消费同一个 Partition 的消息",
|
||
"B": "不同 Consumer Group 之间消费进度互相影响",
|
||
"C": "同一个 Consumer Group 内,一条消息只会被其中一个消费者消费",
|
||
"D": "Consumer Group 的消费者数量必须等于 Partition 数量"
|
||
},
|
||
"answer": "C",
|
||
"explanation": "Consumer Group 是消息队列实现「负载均衡「和「广播「的核心机制。同一个 Group 内,一条消息只会被组内的一个消费者消费(点对点模式),实现负载均衡。A 错误:同一个 Group 内,一个 Partition 在同一时刻只能被一个消费者消费。B 错误:不同 Group 之间完全独立,各自维护独立的消费位点(offset),互不影响。D 错误:消费者数量可以少于或多于 Partition 数量;少于时一个消费者消费多个 Partition,多于时部分消费者空闲。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-005",
|
||
"type": "single_choice",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"push-pull"
|
||
],
|
||
"question": "关于消息队列的推(Push)拉(Pull)模式,以下描述正确的是?",
|
||
"options": {
|
||
"A": "Push 模式下消费者主动向 Broker 请求新消息",
|
||
"B": "Pull 模式下 Broker 主动将消息推送给消费者",
|
||
"C": "RocketMQ 采用 Push 模式时,底层实际上是基于长轮询(Long Polling)的 Pull 实现",
|
||
"D": "Kafka 的 Consumer 完全基于 Push 模式消费消息"
|
||
},
|
||
"answer": "C",
|
||
"explanation": "RocketMQ 的 Consumer 虽然名为 PushConsumer(API 表现为推送语义),但底层实现是基于长轮询(Long Polling)的 Pull 模式:消费者定期向 Broker 发起拉取请求,如果当前没有新消息,Broker 会 hold 住该请求(挂起一段时间),直到有新消息到达或超时后才返回。这种设计结合了 Pull 模式的消费者端流控能力和 Push 模式的消息及时性。A 错误:Push 模式是 Broker 主动推送。B 错误:Pull 模式是消费者主动拉取。D 错误:Kafka 的 Consumer 完全基于 Pull 模式,由消费者控制拉取频率。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-006",
|
||
"type": "single_choice",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"kafka",
|
||
"partition"
|
||
],
|
||
"question": "在 Kafka 中,以下哪种方式可以保证消息的全局顺序性?",
|
||
"options": {
|
||
"A": "将 Topic 的 Partition 数量设置为 3,并为消息设置 key",
|
||
"B": "将 Topic 的 Partition 数量设置为 1,所有消息不设置 key",
|
||
"C": "使用多个 Partition,通过消息 key 保证相同 key 的消息有序",
|
||
"D": "配置 acks=all 并设置 min.insync.replicas=2"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Kafka 只能保证单个 Partition 内的顺序性。要实现全局有序,必须将 Partition 数量设为 1,使所有消息写入同一个 Partition,从而利用 Partition 内的 offset 顺序保证全局有序。A 错误:3 个 Partition 只能保证每个 Partition 内有序,Partition 之间不保证顺序。C 错误:相同 key 的消息会被路由到同一个 Partition,保证了 key 级别的局部有序,但不同 key 的消息仍然跨 Partition 分布,不保证全局有序。D 错误:acks 和 min.insync.replicas 控制的是数据可靠性和一致性,与消息顺序性无关。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-007",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"kafka",
|
||
"durable",
|
||
"topic"
|
||
],
|
||
"question": "Kafka 的高吞吐量很大程度上依赖于其对零拷贝(Zero-Copy)技术的使用,关于该技术以下描述正确的是?",
|
||
"options": {
|
||
"A": "零拷贝通过内核态和用户态之间的内存映射实现数据传输",
|
||
"B": "零拷贝使用 sendfile 系统调用,使数据直接从磁盘(PageCache)传输到网卡,绕过用户空间",
|
||
"C": "零拷贝只能用于消费者首次消费消息的场景",
|
||
"D": "零拷贝要求消息必须存储在内存中而非磁盘上"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Kafka 的 Consumer Fetch 数据时,使用 Linux 的 sendfile 系统调用实现零拷贝。传统 I/O 需要经过「磁盘→内核缓冲区→用户缓冲区→Socket 缓冲区→网卡」四次拷贝,而 sendfile 直接在内核态将数据从 PageCache 传输到网卡(DMA gather copy),绕过了用户空间,减少了上下文切换和内存拷贝的开销。A 错误:零拷贝的核心是 sendfile,不是 mmap。C 错误:零拷贝对所有消费读取都适用(包括重复消费和多消费者场景)。D 错误:零拷贝读取的数据来自 PageCache(磁盘数据在内核页缓存中的映射),不要求数据在应用层内存中。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-008",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"kafka",
|
||
"cluster"
|
||
],
|
||
"question": "关于 Kafka 的 ISR(In-Sync Replicas)机制,以下描述正确的是?",
|
||
"options": {
|
||
"A": "ISR 是所有副本的集合,包括与 Leader 完全同步的和落后的副本",
|
||
"B": "ISR 中的副本必须与 Leader 保持数据同步,落后太多的副本会被移出 ISR",
|
||
"C": "当 ISR 中所有副本都确认写入后,Producer 才会收到 ack,这会导致可用性降低",
|
||
"D": "ISR 的大小永远等于 Replication Factor 的值"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "ISR 是与 Leader 保持数据同步的副本集合。Kafka 通过 replica.lag.time.max.ms 参数控制副本的最大允许落后时间,如果某个 Follower 副本落后超过该阈值,会被移出 ISR。这样保证了 ISR 中的副本都有能力在 Leader 故障时被选为新 Leader。A 错误:ISR 严格排除了落后过多的副本。C 错误:acks=all 只要求 ISR 中所有副本确认,ISR 缩小反而降低了写入延迟;可用性降低主要在 ISR 缩为 1 且该节点故障时发生。D 错误:ISR 大小是动态变化的,可能小于 Replication Factor(因副本落后被踢出),也可能等于(正常情况)。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-009",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"rocketmq",
|
||
"transactional-message"
|
||
],
|
||
"question": "关于 RocketMQ 的事务消息机制,以下描述正确的是?",
|
||
"options": {
|
||
"A": "事务消息的半消息(Half Message)在发送后消费者立即可见",
|
||
"B": "事务消息通过两阶段提交实现:先发半消息,本地事务执行成功后发送 Commit,失败则发送 Rollback",
|
||
"C": "RocketMQ 事务消息依赖数据库 XA 事务来保证一致性",
|
||
"D": "事务消息的回查机制是由消费者端触发的"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "RocketMQ 事务消息采用两阶段提交:Producer 先发送半消息(Half Message)到 Broker,此时消费者不可见;然后 Producer 执行本地事务(如数据库操作);成功则发送 Commit 使消息对消费者可见,失败则发送 Rollback 删除消息。A 错误:半消息在 Commit 之前对消费者不可见,这是事务消息隔离性的关键。C 错误:RocketMQ 事务消息不依赖数据库 XA 事务,而是通过消息回查(Transaction Check)机制——如果 Broker 未收到 Commit 或 Rollback,会定期回查 Producer 本地事务状态来决定最终提交或回滚。D 错误:回查机制是由 Broker 端主动发起,查询 Producer 的本地事务状态。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-010",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"kafka",
|
||
"durable"
|
||
],
|
||
"question": "Kafka 顺序写磁盘的性能优势来源于什么?",
|
||
"options": {
|
||
"A": "顺序写避免了磁盘寻道时间,同时利用了操作系统的 PageCache 做读写加速",
|
||
"B": "顺序写时磁盘的 IOPS 指标会显著提升",
|
||
"C": "顺序写意味着每条消息只写入一次,不需要追加写",
|
||
"D": "顺序写通过 RAID 0 条带化实现并行写入多个磁盘"
|
||
},
|
||
"answer": "A",
|
||
"explanation": "Kafka 的核心设计哲学是将磁盘当作顺序写入的存储来使用。顺序写磁盘避开了随机 I/O 的磁盘寻道开销(机械硬盘的寻道时间通常 5-10ms),在顺序写入场景下磁盘吞吐量可达 600MB/s 以上。同时,Kafka 利用操作系统的 PageCache 作为读写缓冲层:写入时数据先写入 PageCache(用户态到内核态的一次拷贝),再由 OS 异步刷盘;读取时优先从 PageCache 返回,未命中时再读磁盘。B 错误:IOPS 是衡量随机 I/O 的指标,顺序写关注的是吞吐量(Throughput)。C 错误:Kafka 是 append-only 的追加写模式,每条消息确实只写一次,但这不是顺序写的性能来源。D 错误:RAID 条带化是硬件层面的并行方案,不是 Kafka 顺序写的设计原理。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-011",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"kafka",
|
||
"consumer-group",
|
||
"push-pull"
|
||
],
|
||
"question": "当 Consumer Group 内有消费者加入或离开时,Kafka 会触发 Rebalance。关于 Rebalance,以下描述正确的是?",
|
||
"options": {
|
||
"A": "Rebalance 过程中消费者可以继续正常消费消息",
|
||
"B": "Rebalance 由 Consumer 端主动发起,Broker 不参与分配决策",
|
||
"C": "Rebalance 会导致所有消费者暂停消费,直到新的分区分配方案确定",
|
||
"D": "Rebalance 只在消费者宕机时才会触发"
|
||
},
|
||
"answer": "C",
|
||
"explanation": "Kafka 的 Rebalance 是将 Partition 重新分配给 Consumer Group 内的消费者的过程。在 Rebalance 期间,所有消费者会暂停消费(进入 rebalancing 状态),直到分配方案确定后才恢复。A 错误:Rebalance 期间消费者无法消费消息,这是一个已知的延迟来源。B 错误:在 Kafka 2.3+ 的 Cooperative Rebalance(增量再平衡)中 Broker(Group Coordinator)参与协调,且新版 Kafka 支持 Sticky 分配策略,由协调者参与决策。D 错误:Rebalance 不仅在宕机时触发,消费者主动加入/离开(如发布新版本重启、扩容缩容)、心跳超时(session.timeout.ms)、Poll 超时(max.poll.interval.ms)等都会触发 Rebalance。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-012",
|
||
"type": "single_choice",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"kafka",
|
||
"transactional-message"
|
||
],
|
||
"question": "关于 Kafka 的 Exactly-Once 语义实现,以下描述正确的是?",
|
||
"options": {
|
||
"A": "Kafka 通过acks=all就能实现端到端的Exactly-Once语义",
|
||
"B": "Kafka的Exactly-Once语义依赖于幂等Producer(PID+序列号去重)和事务API的组合",
|
||
"C": "Kafka的Exactly-Once语义仅适用于Producer端,Consumer端无法实现",
|
||
"D": "Kafka的Exactly-Once语义要求所有Partition的Replication Factor必须为1"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Kafka 的 Exactly-Once 语义由两个机制组合实现:(1) 幂等 Producer——Broker 为每个 Producer 分配唯一的 PID(Producer ID),每条消息携带递增的序列号,Broker 端通过 PID+序列号去重,解决单个 Producer 到 Broker 的重复问题;(2) 事务 API——Producer 可以在一个原子事务中写入多条消息(跨 Partition),确保要么全部提交要么全部回滚,解决跨 Partition 的原子写入问题。A 错误:acks=all 只保证消息被所有 ISR 副本接收,不能解决 Producer 重试导致的重复发送问题,更不是端到端的 Exactly-Once。C 错误:Consumer 配合 read_committed 隔离级别和幂等消费逻辑(如数据库唯一键),也可以实现端到端的 Exactly-Once。D 错误:Replication Factor 与 Exactly-Once 无关。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-013",
|
||
"type": "single_choice",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"kafka",
|
||
"durable"
|
||
],
|
||
"question": "以下关于 Kafka 中 PageCache 和 fsync 策略的描述,哪项是正确的?",
|
||
"options": {
|
||
"A": "Kafka 默认使用同步刷盘(每条消息写入后立即 fsync),以确保数据不丢失",
|
||
"B": "Kafka 依赖操作系统的 PageCache 做写缓冲,由操作系统异步刷盘,这在 broker 崩溃时可能导致少量数据丢失",
|
||
"C": "配置 log.flush.interval.messages=1 可以实现每条消息都 fsync,同时不影响写入吞吐量",
|
||
"D": "PageCache 是用户态的内存缓存,用于缓存 Kafka 的日志数据"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Kafka 的默认设计是利用操作系统的 PageCache 作为写入缓冲:Producer 写入的数据先到达 PageCache(内核态),然后由操作系统的 pdflush 等机制异步刷盘。这意味着如果 Broker 进程崩溃(OS 仍正常运行),PageCache 中未刷盘的数据不会丢失;但如果 OS 也崩溃(断电),未刷盘的数据可能丢失。这是 Kafka 在吞吐量和可靠性之间的权衡。A 错误:Kafka 默认不是同步刷盘,否则吞吐量会大幅下降。C 错误:虽然配置 log.flush.interval.messages=1 可以每条消息 fsync,但这会严重降低写入吞吐量,是已知的性能反模式。D 错误:PageCache 是内核态的内存页缓存,不是用户态的。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-014",
|
||
"type": "single_choice",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"dead-letter-queue",
|
||
"rocketmq"
|
||
],
|
||
"question": "在 RocketMQ 中,关于死信队列和消息重试的机制,以下描述正确的是?",
|
||
"options": {
|
||
"A": "消息消费失败后直接进入死信队列,不进行任何重试",
|
||
"B": "RocketMQ 的重试队列支持按时间延迟重试,重试次数耗尽后消息自动转入死信队列",
|
||
"C": "死信队列中的消息只能由运维人员手动删除,不支持再次消费",
|
||
"D": "RocketMQ 的重试次数由 Broker 全局统一配置,消费者无法自定义"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "RocketMQ 的消息重试机制:当消息消费失败时,Broker 会将消息投递到内置的重试队列(%RETRY%{ConsumerGroup})。重试队列按照延迟级别组织(默认 18 个级别:10s, 30s, 1m, 2m, 3m, ... 2h),消息会按照延迟级别逐步重试。当重试次数超过配置的最大重试次数(默认 16 次)后,消息会被自动转入死信队列(%DLQ%{ConsumerGroup})。A 错误:消费失败后会先进入重试队列进行延迟重试,而非直接进死信队列。C 错误:死信队列中的消息可以被消费者消费(通常是由专门的死信消费者来处理),也可以选择删除。D 错误:最大重试次数由消息的属性(reconsumeTimes)控制,消费者可以通过修改消息属性来自定义重试行为。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-015",
|
||
"type": "single_choice",
|
||
"difficulty": 5,
|
||
"tags": [
|
||
"kafka",
|
||
"cluster"
|
||
],
|
||
"question": "在 Kafka 集群中,当 Leader 副本所在的 Broker 宕机后,以下关于 Leader 选举的描述正确的是?",
|
||
"options": {
|
||
"A": "Kafka 使用 Paxos 算法进行 Leader 选举,保证强一致性",
|
||
"B": "ISR 中的存活副本会参与 Leader 选举,由 Controller 从 ISR 中按优先级选择新 Leader",
|
||
"C": "所有 Follower 副本都会参与投票,得票最多的成为新 Leader",
|
||
"D": "Leader 选举完成后,所有 Follower 需要从新的 Leader 全量同步数据才能开始提供读服务"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Kafka 的 Leader 选举由集群中的 Controller(一个特殊的 Broker,通过 ZooKeeper/KRaft 选举产生)负责管理。当 Leader 副本故障时,Controller 从该 Partition 的 ISR 列表中选择一个存活的副本作为新 Leader(如果配置了 unclean.leader.election.enable=true,ISR 全部不可用时还可能从非 ISR 副本中选择,但会有数据丢失风险)。新 Leader 选定后立即对外提供服务,其他 Follower 在新 Leader 上开始拉取数据逐步同步。A 错误:Kafka 不使用 Paxos,早期使用 ZooKeeper 的 ZAB 协议,新版 Kafka 使用内置的 KRaft(基于 Raft 的变体)进行元数据管理。C 错误:Kafka 不采用投票机制,而是由 Controller 直接从 ISR 中选择。D 错误:新 Leader 选出后立即可用,Follower 异步追赶数据,不需要全量同步完成后才提供服务(这正是 ISR 机制的意义——ISR 中的副本数据已经足够接近 Leader)。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |