《JAVA八股真解》七、Redis
#JAVA##JAVA面经##JAVA内推#
1. Redis 为什么快?
Redis 的高性能主要得益于以下几个方面:
- 内存存储:数据存储在内存中,读写速度远高于磁盘。
- 单线程模型:避免了多线程竞争和上下文切换开销。
- I/O 多路复用:通过
epoll等机制高效处理大量并发连接。 - 数据结构优化:内置多种高效数据结构,如哈希表、跳表、压缩列表等。
- 持久化机制:支持 RDB 和 AOF,保证数据不丢失。
总结:Redis 的“快”源于其内存存储、单线程设计和高效的 I/O 模型。
2. Redis 可以用来做什么?
Redis 不仅是一个缓存工具,还可用于多种高并发场景:
- 缓存:加速数据库访问,减轻后端压力。
- 排行榜:利用有序集合(Sorted Set)实现排名功能。
- 分布式锁:基于
SETNX实现跨进程互斥控制。 - 分页处理:结合
LIST或HASH实现分页查询。 - 消息队列:使用
LIST或PUB/SUB实现异步通信。 - 会话存储:替代传统 Session,提升扩展性。
应用场景示例:
- 用户登录状态缓存
- 商品库存扣减
- 实时统计与监控
3. Redis 的持久化机制
Redis 提供两种持久化方式:RDB(快照) 和 AOF(追加日志)。
| 特性 | RDB | AOF |
|---|---|---|
| 持久化方式 | 定期生成数据快照 | 记录每条写操作命令 |
| 恢复速度 | 快 | 慢 |
| 数据安全性 | 丢失部分数据 | 低风险,可配置同步策略 |
| 资源消耗 | 高/低 | 低 |
| 启动优先级 | 优先加载 RDB 文件 | 若无 RDB,则加载 AOF |
RDB 优点:
- 备份速度快,适合全量备份。
- 占用空间小,适合灾难恢复。
AOF 优点:
- 数据更安全,可配置同步频率(如每秒一次)。
- 支持重写机制,减少日志体积。
建议:
- 生产环境推荐同时启用 RDB 和 AOF,兼顾性能与安全性。
4. Redis 常用的数据类型
Redis 支持五种基本数据类型:
| 类型 | 说明 | 常见命令 |
|---|---|---|
| String | 字符串,最基础类型,可用于缓存、计数器等 | SET, GET, INCR, DECR |
| List | 双向链表,支持从两端插入删除 | LPUSH, RPUSH, LPOP, RPOP |
| Set | 无序集合,不允许重复元素 | SADD, SREM, SMEMBERS |
| Hash | 键值对集合,适合对象存储 | HSET, HGET, HDEL |
| Sorted Set | 有序集合,每个元素关联一个分数 | ZADD, ZRANGE, ZREVRANGE |
典型应用:
- String:用户信息缓存
- List:任务队列
- Set:去重标签
- Hash:用户属性存储
- Sorted Set:排行榜
5. Redis 的缓存策略:缓存穿透、缓存击穿、缓存雪崩
缓存穿透
- 定义:查询一个不存在的数据,导致每次请求都打到数据库。
- 解决方案:
- 使用布隆过滤器(Bloom Filter)预判是否存在。
- 将空结果缓存一段时间(如 30 秒),防止频繁查询。
缓存击穿
- 定义:热点数据过期瞬间,大量请求直接访问数据库。
- 解决方案:
- 设置永不过期或自动刷新机制。
- 使用互斥锁(如 Redis 分布式锁),确保只有一个线程加载数据。
缓存雪崩
- 定义:大量缓存同时失效,引发数据库压力骤增。
- 解决方案:
- 设置不同的过期时间(随机分布)。
- 使用 Redis 集群分散风险。
- 引入本地缓存作为二级缓冲。
6. Redis 的哨兵模式(Redis Sentinel)
Sentinel 是 Redis 的高可用解决方案,提供自动故障转移和主从切换功能。
核心组件:
- Sentinel 节点:监控 Redis 主从实例。
- Redis 主节点:负责写操作。
- Redis 从节点:复制主节点数据,提供读服务。
工作流程:
- Sentinel 监控主节点健康状态。
- 当主节点宕机,Sentinel 发起选举。
- 选出新的主节点,并通知客户端更新连接。
优势:
- 自动故障转移,无需人工干预。
- 支持多个 Sentinel 实例,提高可靠性。
7. Redis 的分片集群(Redis Cluster)
Redis Cluster 是 Redis 的分布式解决方案,支持水平扩展和高可用。
架构特点:
- 分片机制:数据分布在多个节点上,每个节点负责一部分哈希槽(hash slot)。
- 哈希槽:共 16384 个槽,每个 key 根据哈希值映射到某个槽。
- 自动迁移:支持在线扩容和缩容。
部署方式:
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
优势:
- 支持大规模数据存储。
- 自动故障转移,支持高可用。
8. Redis 分布式锁如何实现?Redis 分布式锁命令使用
分布式锁实现原理:
- 使用
SETNX命令尝试获取锁。 - 设置超时时间,防止死锁。
- 使用 Lua 脚本保证原子性。
示例代码:
// 获取锁
String result = redisTemplate.execute((RedisCallback<String>) connection -> {
return connection.setNX(key.getBytes(), value.getBytes());
});
// 设置过期时间
redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
注意事项:
- 使用
SET key value NX PX milliseconds保证原子性。 - 使用 Lua 脚本释放锁,避免误删他人锁。
9. Redis(或 ElasticSearch)和 MySQL 如何保持数据一致性?
同步方案:
- 双写机制:先写数据库,再写缓存;或反之。
- 消息队列:通过 MQ 异步更新缓存,解耦业务逻辑。
异步方案:
- 定时任务:定期比对数据库与缓存,修复不一致。
- 监听变更:使用 binlog 或 CDC 工具捕获数据库变更,实时同步到缓存。
建议:
- 对于强一致性要求高的场景,采用双写或消息队列。
- 对于容忍短暂不一致的场景,可采用异步更新。
10. Redisson 是什么?怎么用?
Redisson 是一个基于 Redis 的 Java 客户端,提供了丰富的分布式数据结构和高级功能。
核心特性:
- 分布式对象:如
RMap,RSet,RLock。 - 分布式锁:支持可重入锁、公平锁、红锁。
- 分布式集合:支持高并发操作。
- 消息队列:支持发布订阅模式。
使用方式:
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
RLock lock = redisson.getLock("myLock");
lock.lock();
try {
// 业务逻辑
} finally {
lock.unlock();
}
优势:
- API 设计友好,易于集成。
- 内置多种分布式组件,简化开发。
11. Redisson 有了锁机制的管理
Redisson 提供了强大的分布式锁管理能力:
- 可重入锁:同一个线程可以多次获取同一把锁。
- 公平锁:按请求顺序排队,保证公平性。
- 红锁(RedLock):跨多个 Redis 实例的分布式锁,提升可用性。
- 联锁(MultiLock):同时锁定多个锁,保证事务一致性。
适用场景:
- 分布式系统中的资源竞争。
- 高并发下的订单扣减、库存控制等。
【八股真解】精炼最新高频面经 文章被收录于专栏
本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏
查看3道真题和解析