后端架构面试准备指南¶
面试题库¶
系统设计题¶
1. 设计一个短链接系统¶
需求: - 支持短链接生成 - 支持短链接跳转 - 支持自定义短链接 - 支持访问统计
设计要点: - 短链接生成算法 - 数据存储方案 - 缓存策略 - 防止重复 - 访问统计
参考答案:
Python
import hashlib
import redis
class ShortLinkService:
def __init__(self, redis_client):
self.redis = redis_client
def generate_short_link(self, long_url):
# 生成短链接
hash_value = hashlib.md5(long_url.encode()).hexdigest()[:8]
short_code = self._base62_encode(int(hash_value, 16))
# 检查是否重复
if self.redis.exists(f"short:{short_code}"):
return self.generate_short_link(long_url + "_")
# 存储映射
self.redis.setex(f"short:{short_code}", 86400, long_url)
self.redis.incr(f"count:{short_code}")
return f"http://short.link/{short_code}"
def get_long_link(self, short_code):
# 获取长链接
long_url = self.redis.get(f"short:{short_code}")
if long_url:
# 增加访问计数
self.redis.incr(f"count:{short_code}")
return long_url.decode()
return None
def _base62_encode(self, num):
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
if num == 0:
return characters[0]
base62 = []
while num:
num, rem = divmod(num, 62)
base62.append(characters[rem])
return ''.join(reversed(base62))
2. 设计一个秒杀系统¶
需求: - 支持高并发 - 防止超卖 - 保证公平性 - 实时库存
设计要点: - 缓存预热 - 限流策略 - 库存扣减 - 消息队列 - 数据库优化
参考答案:
Python
import redis
import json
class SeckillService:
def __init__(self, redis_client, producer):
self.redis = redis_client
self.producer = producer
def seckill(self, user_id, product_id):
# 检查用户是否已购买
if self.redis.sismember(f"bought:{product_id}", user_id):
return {"success": False, "message": "Already bought"}
# 检查库存
stock = self.redis.decr(f"stock:{product_id}")
if stock < 0:
self.redis.incr(f"stock:{product_id}")
return {"success": False, "message": "Out of stock"}
# 标记用户已购买
self.redis.sadd(f"bought:{product_id}", user_id)
# 发送消息到MQ
self.producer.send('seckill-orders', {
'user_id': user_id,
'product_id': product_id,
'timestamp': time.time()
})
return {"success": True, "message": "Success"}
3. 设计一个即时通讯系统¶
需求: - 支持实时消息 - 支持群聊 - 支持离线消息 - 支持消息已读
设计要点: - WebSocket连接管理 - 消息路由 - 离线消息存储 - 消息同步 - 消息确认
参考答案:
Python
from fastapi import FastAPI, WebSocket
import json
from typing import Dict
app = FastAPI()
# 存储WebSocket连接
connections: Dict[int, WebSocket] = {}
@app.websocket("/ws/{user_id}")
async def websocket_endpoint(websocket: WebSocket, user_id: int):
await websocket.accept()
connections[user_id] = websocket
try:
while True:
data = await websocket.receive_text()
message = json.loads(data)
# 处理消息
await handle_message(user_id, message)
finally:
del connections[user_id]
async def handle_message(sender_id, message):
receiver_id = message['receiver_id']
# 如果接收者在线,直接发送
if receiver_id in connections:
await connections[receiver_id].send_json(message)
else:
# 否则存储离线消息
store_offline_message(receiver_id, message)
4. 设计一个推荐系统¶
需求: - 支持个性化推荐 - 支持实时推荐 - 支持冷启动 - 支持A/B测试
设计要点: - 用户画像 - 物品画像 - 推荐算法 - 实时计算 - 效果评估
5. 设计一个分布式ID生成器¶
需求: - 全局唯一 - 趋势递增 - 高性能 - 高可用
设计要点: - 雪花算法 - 数据库自增 - Redis生成 - 号段模式
参考答案:
Python
import time
import threading
class SnowflakeIDGenerator:
def __init__(self, datacenter_id, worker_id):
self.datacenter_id = datacenter_id
self.worker_id = worker_id
self.sequence = 0
self.last_timestamp = -1
self.lock = threading.Lock()
def generate_id(self):
with self.lock:
timestamp = int(time.time() * 1000)
if timestamp < self.last_timestamp:
raise Exception("Clock moved backwards")
if timestamp == self.last_timestamp:
self.sequence = (self.sequence + 1) & 0xFFF
if self.sequence == 0:
timestamp = self.wait_next_millis(self.last_timestamp)
else:
self.sequence = 0
self.last_timestamp = timestamp
return ((timestamp - 1288834974657) << 22) | \
(self.datacenter_id << 17) | \
(self.worker_id << 12) | \
self.sequence
def wait_next_millis(self, last_timestamp):
timestamp = int(time.time() * 1000)
while timestamp <= last_timestamp:
timestamp = int(time.time() * 1000)
return timestamp
架构设计题¶
1. 如何设计一个高可用系统?¶
答案要点: 1. 消除单点故障 2. 负载均衡 3. 故障转移 4. 容灾备份 5. 限流降级
2. 如何设计一个高性能系统?¶
答案要点: 1. 缓存策略 2. 数据库优化 3. 异步处理 4. 连接池 5. 代码优化
3. 如何设计一个可扩展系统?¶
答案要点: 1. 水平扩展 2. 垂直扩展 3. 分库分表 4. 微服务架构 5. 弹性伸缩
技术问题¶
数据库¶
- 什么是索引?有哪些类型?
- 什么是事务?有哪些隔离级别?
- 什么是锁?有哪些类型?
- 什么是分库分表?如何实现?
- 什么是读写分离?如何实现?
缓存¶
- 什么是缓存穿透?如何解决?
- 什么是缓存击穿?如何解决?
- 什么是缓存雪崩?如何解决?
- 如何保证缓存一致性?
- Redis有哪些数据类型?
消息队列¶
- 什么是消息队列?有什么作用?
- 如何保证消息不丢失?
- 如何保证消息不重复?
- 如何保证消息顺序?
- Kafka、RabbitMQ、RocketMQ的区别?
分布式¶
- 什么是CAP理论?
- 什么是分布式事务?有哪些解决方案?
- 什么是分布式锁?如何实现?
- 什么是服务发现?有哪些实现?
- 什么是熔断器?如何实现?
项目经验准备¶
项目描述模板¶
Text Only
项目名称:[项目名称]
技术栈:[使用的技术]
角色:[担任的角色]
时长:[项目周期]
背景:
- 项目的业务背景和目标
- 面临的技术挑战
我的贡献:
- [具体技术方案1]:解决了什么问题,效果如何
- [具体技术方案2]:解决了什么问题,效果如何
- [具体技术方案3]:解决了什么问题,效果如何
技术亮点:
- [技术难点1]:如何解决,有什么创新
- [技术难点2]:如何解决,有什么创新
成果:
- [量化指标1]:性能提升XX%
- [量化指标2]:开发效率提升XX%
- [量化指标3]:用户满意度提升XX%
反思:
- 如果重新做,会有什么改进
- 学到了什么
常见追问¶
- 为什么选择这个技术方案?
- 遇到过什么技术难点?如何解决?
- 如果给你更多时间,你会怎么优化?
- 团队协作中如何处理技术分歧?
- 如何保证代码质量?
行为面试准备¶
自我介绍¶
简洁明了,突出重点: - 教育背景 - 工作经验 - 技术能力 - 项目经验
常见问题¶
- 介绍一下你最有成就感的项目
- 你如何处理技术债务?
- 你如何保持技术更新?
- 你如何与产品经理协作?
- 你如何指导新人?
STAR原则¶
- Situation:情境
- Task:任务
- Action:行动
- Result:结果
面试技巧¶
技术面试¶
- 先理解问题,再回答
- 边说边写,展示思路
- 考虑边界情况
- 优化时间和空间复杂度
- 主动沟通,及时反馈
系统设计¶
- 先明确需求和约束
- 从简单方案开始
- 逐步优化和扩展
- 考虑可扩展性和可维护性
- 权衡不同方案的优劣
行为面试¶
- 用具体事例支撑观点
- 量化成果和影响
- 展示团队合作能力
- 体现学习能力和成长
- 表达对公司的了解和热情
资源推荐¶
书籍¶
- 《系统设计面试》
- 《数据密集型应用系统设计》
- 《大型网站技术架构》
- 《微服务架构设计模式》
网站¶
- High Scalability
- The Morning Paper
- Engineering at Meta
- Netflix Tech Blog
面经分享¶
- 牛客网面经
- 掘金面经
- 知乎面经
- 公司官网
祝你面试顺利,拿到心仪的Offer! 🎉