《JAVA八股真解》七、Redis

#JAVA##JAVA面经##JAVA内推#

1. Redis 为什么快?

Redis 的高性能主要得益于以下几个方面:

  • 内存存储:数据存储在内存中,读写速度远高于磁盘。
  • 单线程模型:避免了多线程竞争和上下文切换开销。
  • I/O 多路复用:通过 epoll 等机制高效处理大量并发连接。
  • 数据结构优化:内置多种高效数据结构,如哈希表、跳表、压缩列表等。
  • 持久化机制:支持 RDB 和 AOF,保证数据不丢失。

总结:Redis 的“快”源于其内存存储、单线程设计和高效的 I/O 模型。

2. Redis 可以用来做什么?

Redis 不仅是一个缓存工具,还可用于多种高并发场景:

  • 缓存:加速数据库访问,减轻后端压力。
  • 排行榜:利用有序集合(Sorted Set)实现排名功能。
  • 分布式锁:基于 SETNX 实现跨进程互斥控制。
  • 分页处理:结合 LISTHASH 实现分页查询。
  • 消息队列:使用 LISTPUB/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 的高可用解决方案,提供自动故障转移和主从切换功能。 alt

核心组件:

  • Sentinel 节点:监控 Redis 主从实例。
  • Redis 主节点:负责写操作。
  • Redis 从节点:复制主节点数据,提供读服务。

工作流程:

  1. Sentinel 监控主节点健康状态。
  2. 当主节点宕机,Sentinel 发起选举。
  3. 选出新的主节点,并通知客户端更新连接。

优势

  • 自动故障转移,无需人工干预。
  • 支持多个 Sentinel 实例,提高可靠性。

7. Redis 的分片集群(Redis Cluster)

Redis Cluster 是 Redis 的分布式解决方案,支持水平扩展和高可用。 alt

架构特点:

  • 分片机制:数据分布在多个节点上,每个节点负责一部分哈希槽(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):同时锁定多个锁,保证事务一致性。

适用场景

  • 分布式系统中的资源竞争。
  • 高并发下的订单扣减、库存控制等。
#JAVA##java##面经#

本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏

全部评论
接好运
点赞 回复 分享
发布于 今天 12:58 广东
专栏目录https://www.nowcoder.com/share/jump/1772859327707
点赞 回复 分享
发布于 今天 12:58 广东
本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏。
点赞 回复 分享
发布于 昨天 15:51 广东

相关推荐

评论
3
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务