北京JAVA基础面试30天打卡07
1. 缓存三大问题及解决方案
问题 | 场景 | 后果 | 常用解决方案 |
---|---|---|---|
缓存穿透 | 请求的数据在缓存和数据库中都不存在(恶意攻击或查询异常 ID) | 每次请求都会打到数据库,导致 DB 压力骤增 | - 缓存空值(短期缓存不存在的 key) - 布隆过滤器(提前判断 key 是否存在) - 接口参数校验、限流 |
缓存击穿 | 热点 key 过期瞬间,大量请求同时访问 | 同一时间大量请求打到数据库,可能压垮 DB | - 互斥锁 / 分布式锁(第一个请求构建缓存,其它等待) - 逻辑过期(业务侧判断过期,异步更新) - 提前刷新缓存 |
缓存雪崩 | 大量 key 在同一时间过期(比如统一设置了相同 TTL) | 瞬时缓存失效,所有请求直达 DB,造成雪崩 | - 过期时间随机化(TTL + 随机值) - 多级缓存(本地缓存 + 分布式缓存) - 限流 + 服务降级 |
2. 如何保证 Redis 的高并发
Redis 本身是单线程处理命令(IO 多路复用 + 内存操作快),但要在高并发场景下保持性能,需要从以下几方面优化:
网络层优化
使用 pipeline 批量发送命令减少 RTT
合理配置连接池,避免频繁建立连接
数据结构选择
选择合适的 Redis 数据类型(如 hash 存储对象、zset 排序等)减少 key 数量
避免大 key(拆分成多个小 key)
分片与集群
使用 Redis Cluster 做数据分片,分摊 QPS 压力
业务端可做读写分离(主写,从读)
热点 key 优化
本地缓存(Caffeine / Guava)+ Redis 二级缓存
预热热点数据,减少直接访问 DB
持久化与备份
结合 RDB + AOF(混合持久化)减少阻塞
合理调优 save、appendfsync 等参数
3. Redis 如何保证原子性
Redis 的原子性是依赖其单线程命令执行模型,以及事务机制:
单命令天然原子性
Redis 单线程按顺序执行命令,不会被中断
例如 INCR key、HSET key field value 是天然原子操作
事务(MULTI/EXEC)
将多个命令放到事务中执行,保证要么全执行,要么都不执行(但事务内命令不会回滚)
Lua 脚本
使用 EVAL 在服务端执行一段 Lua 脚本,脚本中所有操作是原子性的
常用于复杂的原子性业务逻辑(如扣库存 + 记录日志)加粗样式