后端系统设计面试题集
总题数: 21道 | 重点领域: 架构设计、系统优化 | 难度分布: 中高级
本文档整理了后端系统设计的完整21道面试题目,涵盖架构设计、功能实现、性能优化等各个方面。
面试题目列表
1. 让你设计一个 RPC 框架,怎么设计?
核心组件:代理层、序列化、网络通信(Netty)、服务注册(Zookeeper)、负载均衡、容错
关键实现:
- 动态代理生成客户端
- 多种序列化方式(Protobuf/Hessian)
- 服务注册与发现
- 负载均衡(轮询/随机/一致性Hash)
- 容错机制(重试/熔断/降级)
2. 如何设计一个秒杀功能?
核心方案:
- 前端:按钮防重、倒计时
- 网关:限流(令牌桶1000 QPS)
- Redis:预减库存(DECR原子操作)
- MQ:削峰填谷(异步创建订单)
- 数据库:乐观锁防超卖
- 防刷:接口签名、单用户限流
3. 让你设计一个消息队列,怎么设计?
核心设计:
- 存储:CommitLog(顺序写)+ ConsumeQueue(索引)
- 生产者:同步/异步发送
- 消费者:Push/Pull模式、消费者组
- 可靠性:消息确认、重试机制、死信队列
- 高可用:主从复制、故障转移
4. 让你设计一个线程池,怎么设计?
核心参数:
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:空闲线程存活时间
- workQueue:任务队列
- handler:拒绝策略
执行流程:线程数小于核心数时创建核心线程,否则加入队列,队列满则创建非核心线程,达到最大线程数则执行拒绝策略
5. 让你设计一个 HashMap ,怎么设计?
核心设计:
- 结构:数组 + 链表/红黑树
- Hash函数:
(h = key.hashCode()) ^ (h >>> 16) - 扩容:负载因子0.75,容量翻倍
- 树化:链表长度≥8转红黑树
- 线程安全:ConcurrentHashMap(CAS + Synchronized)
6. 让你设计一个短链系统,怎么设计?
核心方案:
- 生成算法:自增ID转62进制 / Hash / 雪花算法
- 存储:MySQL存储映射 + Redis缓存热点
- 跳转:302重定向
- 统计:MQ异步统计点击数
- 优化:布隆过滤器防穿透、CDN加速
7. 让你实现一个订单超时取消功能,怎么设计?
方案对比:
- 延迟队列:RabbitMQ延迟插件、RocketMQ延迟消息
- 定时任务:每分钟扫描未支付订单
- Redis过期:监听key过期事件(不可靠)
- 时间轮:Netty HashedWheelTimer
推荐方案:延迟队列 + 定时任务兜底
8. 让你实现一个分布式单例对象,如何实现?
方案1:Redis SETNX
java
1Boolean success = redis.setnx("singleton:instance", "1", 3600);2if (success) return new SingletonObject();方案2:Zookeeper临时节点
java
1zkClient.create("/singleton", data, CreateMode.EPHEMERAL);9. 商家想要知道自己店铺卖的最好的 top 50 商品,如何实现这个功能?
实时统计:
java
1// Redis ZSET存储销量2redis.zincrby("shop:" + shopId + ":sales", 1, productId);3// 查询Top504Set<String> top50 = redis.zrevrange("shop:" + shopId + ":sales", 0, 49);离线统计:定时任务从订单表统计,结果存Redis
10. 朋友圈点赞功能如何实现,简单说说?
核心设计:
- 存储:Redis SET存储点赞用户ID
- 点赞:
SADD post:{postId}:likes {userId} - 取消:
SREM post:{postId}:likes {userId} - 统计:
SCARD post:{postId}:likes - 判断:
SISMEMBER post:{postId}:likes {userId} - 持久化:异步批量写入MySQL
11. 分布式锁一般都怎样实现?
Redis实现:
java
1// 加锁2redis.set(lockKey, requestId, "NX", "PX", 30000);3// 解锁(Lua脚本保证原子性)4if redis.call('get', KEYS[1]) == ARGV[1] then5 return redis.call('del', KEYS[1])6endZookeeper实现:创建临时顺序节点,最小节点获得锁
Redisson:自动续期、可重入、RedLock
12. 如果让你统计每个接口每分钟调用次数怎么统计?
方案1:Redis INCR
java
1String key = "api:" + apiName + ":" + (timestamp / 60);2redis.incr(key);3redis.expire(key, 120);方案2:滑动窗口(ZSET)
java
1redis.zadd(key, timestamp, uuid);2redis.zremrangeByScore(key, 0, timestamp - 60000);3long count = redis.zcard(key);13. 让你设计一个文件上传系统,怎么设计?
核心功能:
- 分片上传:大文件切分成小块(5MB)
- 断点续传:Redis记录已上传分片
- 秒传:MD5校验文件是否已存在
- 合并:所有分片上传完成后合并
- 存储:OSS/MinIO对象存储
- 安全:上传凭证、文件类型校验
14. 让你设计一个分布式 ID 发号器,怎么设计?
方案对比:
- 雪花算法:1位符号 + 41位时间戳 + 10位机器ID + 12位序列号
- 数据库号段:批量获取ID段,本地分配
- Redis INCR:简单但依赖Redis
- 美团Leaf:号段模式 + 双buffer
推荐:雪花算法(高性能)或Leaf(高可用)
15. 什么是限流?限流算法有哪些?怎么实现的?
限流算法:
- 固定窗口:计数器,简单但有临界问题
- 滑动窗口:精确但内存占用大
- 漏桶:平滑流量,无法应对突发
- 令牌桶:允许突发,推荐使用(Guava RateLimiter)
实现:
java
1RateLimiter limiter = RateLimiter.create(100); // 100 QPS2if (limiter.tryAcquire()) {3 // 处理请求4}16. 如何设计一个点赞系统?
同问题10,核心使用Redis SET + 异步持久化
扩展功能:
- 点赞通知:MQ异步发送
- 点赞列表:ZSET按时间排序
- 热点优化:本地缓存 + 布隆过滤器
17. 即时通讯项目中怎么实现历史消息的下拉分页加载?
游标分页:
java
1// 使用消息ID作为游标2List<Message> messages = messageMapper.selectByUserId(3 userId, lastMessageId, 204);5// WHERE user_id = ? AND id < ? ORDER BY id DESC LIMIT 20优化:
- Redis缓存最近100条消息
- 分表存储历史消息(按月分表)
- 冷数据归档到对象存储
18. HashMap 是不是线程安全的?如果让你来实现一个线程安全的 HashMap 你要怎么设计?如果不用加锁你要怎么设计?
HashMap不是线程安全的
线程安全实现:
- ConcurrentHashMap:分段锁(JDK7)/ CAS+Synchronized(JDK8)
- Collections.synchronizedMap:全局锁,性能差
- 无锁实现:CopyOnWriteMap(写时复制,适合读多写少)
19. 让你设计一个购物车功能,怎么设计?
核心设计:
- 存储:Redis Hash,key=
cart:{userId},field=productId,value=quantity - 添加:
HINCRBY cart:{userId} {productId} {quantity} - 删除:
HDEL cart:{userId} {productId} - 查询:
HGETALL cart:{userId} - 持久化:定期同步到MySQL或下单时同步
- 优化:购物车商品信息缓存、库存校验
学习指南
核心要点:
- 系统架构设计原则
- 高并发系统设计
- 分布式系统解决方案
- 性能优化策略
学习路径建议:
- 掌握系统设计的基本方法
- 熟悉高并发场景的解决方案
- 理解分布式系统的设计原则
- 学习性能优化和故障排查
评论区 / Comments