字节真题:高并发消息队列设计

面试重要程度:⭐⭐⭐⭐⭐

真题来源:字节跳动2024校招技术面试

考察重点:高并发架构设计、消息队列原理、系统优化

预计阅读时间:45分钟

真题背景

面试官: "我们需要设计一个高并发的消息队列系统,支持每秒百万级消息处理,要求消息不丢失、有序性保证、支持多种消费模式。请详细设计这个系统的架构,包括存储方案、网络通信、性能优化等方面。如果消息堆积严重怎么处理?"

考察意图:

  • 高并发系统架构设计能力
  • 消息队列核心原理的深度理解
  • 性能优化和问题解决思路
  • 分布式系统设计经验

🎯 系统架构设计

整体架构

/**
 * 高并发消息队列架构
 */
@Component
public class HighPerformanceMessageQueue {
    
    // 性能指标
    public static final int MAX_TPS = 1_000_000;           // 百万级TPS
    public static final int MAX_LATENCY_MS = 10;           // 延迟<10ms
    public static final int REPLICATION_FACTOR = 3;        // 3副本
    
    /**
     * Broker节点
     */
    public static class BrokerNode {
        private String brokerId;
        private BrokerRole role; // MASTER, SLAVE
        private StorageEngine storageEngine;
        private NetworkServer networkServer;
        
        public SendResult handleSendMessage(SendMessageRequest request) {
            try {
                // 1. 验证消息
                validateMessage(request.getMessage());
                
                // 2. 选择队列
                TopicQueue queue = selectQueue(request.getTopic());
                
                // 3. 存储消息
                MessageStoreResult result = storageEngine.storeMessage(
                    queue.getQueueId(), request.getMessage());
                
                // 4. 同步到从节点
                if (role == BrokerRole.MASTER) {
                    syncToSlaves(result);
                }
                
                return SendResult.success(result.getMessageId());
                
            } catch (Exception e) {
                return SendResult.failed(e.getMessage());
            }
        }
    }
}

🚀 存储引擎设计

高性能存储方案

/**
 * 基于文件的存储引擎
 */
@Component
public class FileBasedStorageEngine {
    
    /**
     * CommitLog - 顺序写入的消息日志
     */
    public static class CommitLog {
        private final MappedByteBuffer mappedByteBuffer;
        private final AtomicLong wrotePosition;
        private final int fileSize = 1024 * 1024 * 1024; // 1GB
        
        /**
         * 追加消息到CommitLog
         */
        public AppendMessageResult appendMessage(Message message) {
            try {
                ByteBuffer messageBuffer = serializeMessage(message);
                int messageSize = messageBuffer.remaining();
                
                // 检查空间
                if (wrotePosition.get() + messageSize > fileSize) {
                    return AppendMessageResult.END_OF_FILE;
                }
                
                // 写入消息
                long currentPos = wrotePosition.get();
                mappedByteBuffer.position((int) currentPos);
                mappedByteBuffer.put(messageBuffer);
                wrotePosition.addAndGet(messageSize);
                
                return AppendMessageResult.success(currentPos, messageSize);
                
            } catch (Exception e) {
                return AppendMessageResult.failed(e.getMessage());
            }
        }
        
        /**
         * 异步刷盘
         */
        public void flush() {
            if (mappedByteBuffer != null) {
                mappedByteBuffer.force();
            }
        }
    }
    
    /**
     * ConsumeQueue - 消费队列索引
     */
    public static class ConsumeQueue {
        private final MappedByteBuffer mappedByteBuffer;
        private final AtomicLong maxOffset;
        
        // 每个索引项20字节:8字节偏移量 + 4字节大小 + 8字节Tag
        private static final int CQ_STORE_UNIT_SIZE = 20;
        
        public void putMessagePositionInfo(long offset, int size, long tagsCode) {
            ByteBuffer buffer = ByteBuffer.allocate(CQ_STORE_UNIT_SIZE);
            buffer.putLong(offset);
            buffer.putInt(size);
            buffer.putLong(tagsCode);
            
            buffer.flip();
            
            long currentOffset = maxOffset.get();
            mappedByteBuffer.position((int) (currentOffset * CQ_STORE_UNIT_SIZE));
            mappedByteBuffer.put(buffer);
            maxOffset.incrementAndGet();
        }
    }
}

🌐 网络通信优化

高性能网络层

/**
 * 基于Netty的网络服务器
 */
@Component
public class NettyRemotingServer {
    
    private final EventLoopGroup bossGroup;
    private final EventLoopGroup workerGroup;
    
    @PostConstruct
    public void start() {
        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup(16);
        
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .option(ChannelOption.SO_BACKLOG, 1024)
            .option(ChannelOption.SO_REUSEADDR, true)
            .childOption(ChannelOption.TCP_NODELAY, true)
            .childOption(ChannelOption.SO_KEEPALIVE, false)
            .childHandler(new ChannelInitializer<SocketChannel>() 

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

评论
点赞
8
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务