分布式系统考察重点
模块1:Redis
一、Redis缓存穿透、击穿、雪崩分别是什么?怎么解决?
1. 缓存穿透:查询不存在的数据,绕过缓存直接打穿到DB,比如恶意查id=-1
解决:布隆过滤器拦截不存在key、缓存空值并设置短过期时间、参数合法性校验。
2. 缓存击穿:热点key过期瞬间,大量并发请求打到数据库
解决:互斥锁抢占重建缓存、热点key永不过期、过期时间随机打散。
3. 缓存雪崩:大量key同一时间集体过期,流量全部压垮DB
解决:过期时间随机加偏移量、Redis集群高可用、多级缓存、服务限流熔断。
2. Redisson分布式锁为什么要实现可重入?底层怎么实现可重入?
- 可重入意义:同一个线程内多次加锁不会死锁,比如A方法加锁后调用内部B方法,B方法再次加锁可以正常执行。
- 底层实现:Redis的Hash结构,key=锁名称,field=线程唯一标识,value=重入次数;
加锁:线程不存在则设置次数为1,已存在则次数+1;解锁:次数-1,减到0才删除锁。
3. Redisson看门狗机制是如何实现的?作用是什么?
- 作用:防止业务执行时间超过锁过期时间,锁提前释放导致并发安全问题,自动给锁续期。
- 实现原理:获取锁成功后,开启一个后台定时任务,默认每隔 lock过期时间/3 (默认30s锁,10s执行一次),给锁重置过期时长;
只有未手动解锁、线程正常持有锁时才会续期,锁释放后定时任务停止。
4. Redis持久化RDB和AOF区别,生产环境怎么选型?
RDB:二进制快照,体积小恢复快,会丢失最后一次快照后的数据;
AOF:日志追加形式,数据安全性高,文件体积大恢复慢;
生产一般混合使用,AOF保证数据不丢失,RDB用于快速冷启动恢复。
模块2:分布式锁
1. 原生setnx分布式锁存在什么缺陷?Redisson做了哪些优化?
原生缺陷:不可重入、锁超时无法自动续期、宕机死锁、非原子解锁容易误删别人锁;
Redisson优化:可重入Hash结构、看门狗续期、Lua脚本保证加解锁原子性、支持公平锁/读写锁、锁超时自动释放。
2. Redis分布式锁如何保证主从切换时锁不丢失?
Redis主从异步复制,主节点加锁成功后宕机,从节点还未同步锁数据,新主节点无锁,会出现并发问题;
解决方案:使用RedLock红锁算法、等待从节点同步完成(WAIT指令)、优先ZooKeeper实现强一致性锁。
模块3:RocketMQ
一、RocketMQ事务消息底层执行流程(半消息机制)
1. 生产者发送半消息(Half Message)到MQ,消息对消费者不可见;
2. MQ确认收到半消息后,回调生产者执行本地事务;
3. 本地事务成功,提交消息,消费者可见;失败则回滚删除消息;
4. 长时间无状态响应,MQ开启定时回查任务,回调生产者查询本地事务状态,兜底决策提交/回滚。
二、 RocketMQ如何保证消息不丢失、不重复消费?
消息丢失分层解决:生产者确认机制、Broker刷盘策略、消费者手动ACK;
重复消费规避:业务侧实现幂等性(唯一索引、Redis幂等标记、状态机判断)。
三、 顺序消息实现原理,全局顺序和局部顺序区别
原理:指定相同MessageQueue,消息发送到同一个队列,消费者单线程消费保证顺序;
全局顺序:整个Topic单队列,性能极低;局部顺序:业务分区(订单id哈希)分到同一个队列,兼顾顺序与性能。
模块4:Java并发 & JDK21虚拟线程
一、Synchronized锁升级机制是什么?
无锁→偏向锁→轻量级自旋锁→重量级锁,JDK1.6之后自适应自旋优化,降低内核态切换开销。
二、 为什么Synchronized会阻塞虚拟线程?有什么替代方案?
Synchronized是基于操作系统内核的阻塞锁,虚拟线程被它阻塞时,载体线程会被占用无法复用,丧失虚拟线程轻量调度优势;
替代方案:使用JUC的ReentrantLock、读写锁,虚拟线程阻塞时可以释放载体线程。
三、 虚拟线程和传统平台线程核心区别?
1. 传统线程是操作系统内核线程,创建销毁开销大,数量受系统限制;虚拟线程是JVM用户态轻量级线程,开销极低可海量创建;
2. 传统线程池池化复用管控数量,虚拟线程无需池化,由JVM自动调度;
3. 平台线程阻塞会占用载体资源,虚拟线程阻塞时可以挂载释放载体线程。
四、线程池七大核心参数、四种拒绝策略分别是什么?
参数:核心线程数、最大线程数、空闲存活时间、阻塞队列、拒绝策略、线程工厂、预启动策略;
拒绝策略:Abort丢弃抛异常、Discard丢弃队首、DiscardOldest丢弃队尾、CallerRuns让调用者线程执行。
模块5:MySQL基础原理
1. MySQL分页越往后越慢(深分页)底层原因?
limit offset,size,offset很大时,MySQL需要遍历offset行数据再丢弃,回表开销极大;
优化:主键分页回溯、覆盖索引、业务限制分页上限、ES替代大分页查询。
2. UUID作为主键相比自增id有什么问题?
UUID无序,会导致主键索引页分裂、磁盘碎片多,插入性能差,占用索引空间更大;
优化:有序UUID(UUID v7)、雪花算法、业务分段有序id。
3. InnoDB事务四大隔离级别,分别解决什么问题?
读未提交、读已提交(解决脏读)、可重复读(MySQL默认,解决不可重复读)、串行化(解决幻读);
MVCC多版本并发控制实现RC、RR隔离级别。
