
1) 【一句话结论】
采用“WebSocket持久连接+分布式消息队列(如Kafka,按用户ID分区+日志持久化)+分布式缓存(如Redis主从复制+RDB/AOF持久化)+消息确认与指数退避重试机制”的架构,通过消息队列削峰填谷、缓存保障状态同步与重传,结合WebSocket低延迟通信,尽量保证百万级用户下的低延迟、消息不丢失且顺序正确。
2) 【原理/概念讲解】
老师口吻解释:
log.retention.hours=48,确保消息不因服务重启丢失;chat_messages主题按目标用户ID分区),保证同一用户消息顺序(因为同一分区消息按时间顺序写入)。3) 【对比与适用场景】
以消息队列(Kafka vs RocketMQ)和缓存(Redis vs Memcached)为例:
| 组件 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 消息队列(Kafka) | 分布式消息系统 | 高吞吐、持久化、支持消费组、按时间/分区顺序写入 | 实时日志、流处理、聊天消息 | 需持久化磁盘,启动慢,需配置日志保留时间 |
| 消息队列(RocketMQ) | 消息中间件 | 高可用、持久化、支持事务消息、顺序消息 | 金融、电商、聊天(事务消息复杂) | 事务消息实现复杂,需保证消息顺序 |
| 缓存(Redis) | 内存数据库 | 高速读写、支持数据结构(字符串、列表等)、主从复制 | 消息状态(已读标记)、会话、重传队列 | 容量有限,需限流,需持久化 |
| 缓存(Memcached) | 内存缓存 | 速度快、简单、无持久化 | 热点数据缓存 | 重启数据丢失,不适合持久化场景 |
4) 【示例】
伪代码示例(消息发送与接收流程):
POST /send_message
{
"user_id": "u1",
"target_id": "u2",
"content": "hello",
"timestamp": 1678888888
}
chat_messages,分区按target_id(如分区0对应u2),保证同一用户消息顺序;messages:u2:u1 = "hello"(消息内容,用于重传);u2消息,服务端从Kafka消费(按分区顺序)并推送给客户端。5) 【面试口播版答案】
面试官您好,设计百万级用户实时聊天系统,核心是解决高并发下的低延迟、消息可靠。首先,客户端用WebSocket建立持久连接,减少TCP握手开销。后端架构分为消息队列(如Kafka)和缓存(Redis)。消息队列用于削峰,比如用户激增时缓冲消息,避免服务端压垮;缓存用于存储消息状态(如已读标记)或重传队列。具体流程:客户端发送消息到服务端,服务端写入Kafka(按目标用户ID分区保证顺序),同时存入Redis,并发送ACK。客户端通过WebSocket订阅目标用户,服务端从Kafka消费并推送给客户端。这样既保证低延迟,又通过队列持久化避免消息丢失,缓存保障消息状态同步。总结来说,通过WebSocket实现实时通信,消息队列处理高并发,缓存保障可靠性,整体架构能支撑百万级用户同时在线。
6) 【追问清单】
7) 【常见坑/雷区】
log.retention.hours)。