Appearance
分布式组件
分布式系统离不开这些基础组件:分布式锁、分布式 ID、分布式会话。面试考的是实现细节和坑。
Q1: 分布式锁有哪些实现方式? 「🟡 中级」
考察点:分布式锁的选型与正确性。
参考答案:
- 数据库:唯一索引或
FOR UPDATE行锁。简单但性能差,依赖 DB。 - Redis:
SET key value NX EX+ Lua 脚本删除。高性能,注意锁过期、主从切换问题(Redisson 看门狗续期)。 - ZooKeeper:临时有序节点 + Watch 机制。强一致,但性能不如 Redis。
- 选型:追求性能用 Redis(配合业务幂等);追求强一致用 ZK/Etcd。
追问延伸:
- Redis 主从切换丢锁怎么解决?(RedLock,但有争议)
- ZooKeeper 分布式锁的羊群效应是什么?
Q2: 分布式 ID 生成方案有哪些? 「🟡 中级」
考察点:全局唯一 ID 的设计能力。
参考答案:
- UUID:简单但无序、长(36 字符),不适合做数据库主键。
- 数据库自增:单点瓶颈;号段模式(每次取一段到内存)可缓解。
- 雪花算法(Snowflake):64 位 = 时间戳 + 机器 ID + 序列号,趋势递增,性能高。需解决时钟回拨问题。
- Redis INCR:原子自增,依赖 Redis 可用性。
- Leaf(美团):号段模式 + Snowflake 双实现,高可用。
追问延伸:
- 雪花算法的时钟回拨怎么处理?
- 为什么数据库主键推荐趋势递增?
Q3: 分布式会话怎么实现? 「🟡 中级」
考察点:微服务架构下的会话管理。
参考答案:
- Session 复制:每台机器都存所有会话,浪费内存,扩展性差。
- Session 粘滞:负载均衡把同一用户路由到同一节点,节点挂了会话丢失。
- Session 集中存储:用 Redis 集中存储会话,各节点从 Redis 读取。主流方案。
- Token 方案(JWT):无状态,服务端不存会话;缺点是无法主动失效、Token 较大。
追问延伸:
- JWT 的续签怎么做?
- Redis 集中存储会话的过期策略怎么设计?
Q4: 什么是限流?有哪些算法? 「🟡 中级」
考察点:高可用设计的基础。
参考答案:
- 固定窗口:单位时间内允许 N 个请求。缺点:窗口边界突发流量。
- 滑动窗口:把窗口细分成多个小格,更平滑。
- 漏桶算法:固定速率处理请求,平滑流量但无法应对突发。
- 令牌桶算法:固定速率生成令牌,有令牌才能处理请求;允许一定程度的突发(桶满时)。Guava RateLimiter 用此算法。
追问延伸:
- 限流在网关层做还是在服务层做?
- 分布式限流怎么实现?(Redis + Lua)
Q5: 什么是熔断和降级? 「🟡 中级」
考察点:服务容错的核心机制。
参考答案:
- 熔断:下游服务故障时,快速失败不再调用,避免雪崩。状态:关闭 → 打开(熔断)→ 半开(探测恢复)。代表:Hystrix、Sentinel、Resilience4j。
- 降级:服务不可用时返回兜底数据(缓存、默认值、友好提示),保证核心流程可用。
- 关系:熔断是手段,降级是目的;熔断触发后通常伴随降级。
追问延伸:
- 熔断和超时重试的关系?
- 什么场景需要熔断?
Q6: 什么是服务注册与发现? 「🟡 中级」
考察点:微服务架构的基础组件。
参考答案:
- 服务提供者启动时向注册中心注册自己的地址;服务消费者从注册中心拉取可用实例列表并负载均衡调用。
- 注册中心:ZooKeeper、Eureka(已停更)、Consul、Nacos、Etcd。
- 健康检查:心跳机制,注册中心剔除不健康实例。
- 客户端发现 vs 服务端发现:客户端直连(如 Dubbo)vs 经过负载均衡器(如 Kubernetes Service)。
追问延伸:
- Nacos 的 AP 和 CP 模式怎么切换?
- 服务下线后消费者怎么感知?