Redis 全套笔记:基础 API + 三大架构 + 缓存三大问题

基础使用

1.导入依赖

java 复制代码
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

2.基础使用

1、字符串(String)------ 最常用

java 复制代码
// 存值
redisTemplate.opsForValue().set("name", "张三");

// 取值
String name = redisTemplate.opsForValue().get("name");

// 存值并设置过期时间(秒)
redisTemplate.opsForValue().set("code", "1234", 60, TimeUnit.SECONDS);

// 不存在才设置(分布式锁常用)
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "1", 10, TimeUnit.SECONDS);

// 追加内容
redisTemplate.opsForValue().append("name", "真棒");

// 自增(点赞、计数)
Long num = redisTemplate.opsForValue().increment("click", 1);

// 自减
Long num2 = redisTemplate.opsForValue().decrement("click", 1);

// 删除key
redisTemplate.delete("name");

opsForValue().setIfAbsent:

如果 key 不存在,才设置它,并返回 true;如果 key 已经存在,就不做任何操作,并返回 false

它是实现 Redis 分布式锁的核心操作,原子性地完成了「加锁 + 设置过期时间」,避免了死锁风险。

2、哈希(Hash)------ 存对象 / 结构化数据

java 复制代码
// 存一个字段
redisTemplate.opsForHash().put("user:1", "name", "张三");
redisTemplate.opsForHash().put("user:1", "age", "20");

// 取一个字段
String name = (String) redisTemplate.opsForHash().get("user:1", "name");

// 取所有字段
Map<Object, Object> user = redisTemplate.opsForHash().entries("user:1");

// 判断字段是否存在
Boolean has = redisTemplate.opsForHash().hasKey("user:1", "age");

// 删除某个字段
redisTemplate.opsForHash().delete("user:1", "age");

// 获取所有key/value
Set<Object> keys = redisTemplate.opsForHash().keys("user:1");
List<Object> values = redisTemplate.opsForHash().values("user:1");

3、列表(List)------ 队列、栈、信息流

java 复制代码
// 左进(栈)
redisTemplate.opsForList().leftPush("list", "a");

// 右进(队列)
redisTemplate.opsForList().rightPush("list", "b");

// 左出
String left = redisTemplate.opsForList().leftPop("list");

// 右出
String right = redisTemplate.opsForList().rightPop("list");

// 获取区间 [0,2]
List<String> list = redisTemplate.opsForList().range("list", 0, 2);

// 获取长度
Long size = redisTemplate.opsForList().size("list");

4、集合(Set)------ 去重、共同好友、随机抽取

java 复制代码
// 添加元素
redisTemplate.opsForSet().add("set", "a", "b", "c");

// 获取所有
Set<String> members = redisTemplate.opsForSet().members("set");

// 判断是否存在
Boolean isMember = redisTemplate.opsForSet().isMember("set", "a");

// 删除元素
redisTemplate.opsForSet().remove("set", "a");

// 随机弹出一个
String random = redisTemplate.opsForSet().pop("set");

// 两个集合交集
Set<String> inter = redisTemplate.opsForSet().intersect("set1", "set2");

// 并集
Set<String> union = redisTemplate.opsForSet().union("set1", "set2");

5、有序集合(ZSet)------ 排行榜、热度排序

java 复制代码
// 添加(分数+值)
redisTemplate.opsForZSet().add("ranking", "user1", 90);
redisTemplate.opsForZSet().add("ranking", "user2", 100);

// 按分数从小到大取
Set<String> asc = redisTemplate.opsForZSet().range("ranking", 0, -1);

// 按分数从大到小取(排行榜常用)
Set<String> desc = redisTemplate.opsForZSet().reverseRange("ranking", 0, -1);

// 获取分数
Double score = redisTemplate.opsForZSet().score("ranking", "user1");

// 增加分数
redisTemplate.opsForZSet().incrementScore("ranking", "user1", 5);

// 删除
redisTemplate.opsForZSet().remove("ranking", "user1");

6、通用工具方法

java 复制代码
// 判断key是否存在
Boolean exists = redisTemplate.hasKey("name");

// 设置过期时间
redisTemplate.expire("name", 60, TimeUnit.SECONDS);

// 获取过期时间
Long ttl = redisTemplate.getExpire("name");

// 重命名
redisTemplate.rename("old", "new");

// 匹配key(慎用,生产别用 keys *)
Set<String> keys = redisTemplate.keys("user*");

最简单记忆法

  • 存简单值:opsForValue
  • 存对象:opsForHash
  • 存队列 / 列表:opsForList
  • 去重:opsForSet
  • 排行榜:opsForZSet

八股:

一、Redis 主从 / 哨兵 / 集群(三大架构)

1. 主从复制(Master + Slave)

干什么?
  • 主节点(Master)负责写
  • 从节点(Slave)负责读
  • 从节点自动复制主节点的数据
解决什么问题?
  • 读写分离:读请求分摊到从库,减轻主库压力
  • 数据备份:主库挂了,从库还有数据
  • 高并发读:支持大量查询请求
缺点
  • 主节点挂掉 不能自动恢复
  • 需要人工手动切换主从
  • 只解决读压力,不解决写压力
  • 异步复制,会短暂数据不一致

2. 哨兵(Sentinel)

干什么?
  • 监控主节点和从节点是否正常
  • 主节点挂了 自动选举从节点变成新主节点
  • 自动故障转移,通知应用新主节点地址
解决什么问题?
  • 高可用(HA)
  • 主库挂了不影响服务
  • 不需要人工干预
缺点
  • 只解决高可用问题
  • 不解决海量存储
  • 不解决高并发写

3. 集群(Cluster)

干什么?
  • 多主多从架构
  • 数据分成 16384 个槽(slot)
  • 每台主节点只存一部分数据
  • 客户端自动路由到对应节点
解决什么问题?
  • 海量数据存储(单机存不下)
  • 高并发写(多主同时写)
  • 自带高可用,不需要哨兵
缺点
  • 同一个 key 永远只在一台主节点
  • 解决不了单热点 key 高并发
  • 架构复杂,运维成本高

1. 缓存穿透

是一直打空,绕开缓存(查不存在的数据)

现象
  • 查询根本不存在的数据
  • 缓存永远不命中
  • 所有请求直接打数据库

例:查询 id = -1 的用户

危害

数据库压力巨大,可被攻击直接打崩

解决方案
  • 缓存空值(null)
  • 布隆过滤器(不存在直接返回)

2. 缓存击穿

大量并发像子弹一样,瞬间穿透了缓存,直接打穿到数据库

现象
  • 一个热点 key 突然过期
  • 大量并发请求同时查询这个 key
  • 全部请求打到数据库

例:热门商品缓存过期,瞬间一万请求查库

危害

数据库压力突增,导致卡顿、宕机

解决方案
  • **分布式锁(互斥锁)**只让一个线程去查库更新缓存
  • 热点 key 永不过期

3. 缓存雪崩

是整个缓存层大面积失效,全面崩溃

现象
  • 大量 key 同一时间集体过期
  • Redis 宕机
  • 所有请求瞬间打到数据库 → 直接崩掉
危害

最严重,可导致整个系统瘫痪

解决方案
  • 过期时间加随机值,避免集体过期
  • Redis 哨兵 / 集群高可用,防止宕机
  • 多级缓存(本地缓存 + Redis)
  • 限流、降级

最终终极背诵版(最强)

  • 主从:读写分离,分担读
  • 哨兵:主挂了自动切换
  • 集群:存得多、写得快
  • 穿透:查不存在的数据 → 缓存空值 / 布隆
  • 击穿:热点 key 过期 → 分布式锁
  • 雪崩:大量 key 同时过期 → 加随机时间、高可用
相关推荐
zzb15801 小时前
Fragment 生命周期深度图解:从 onAttach 到 onDetach 完整流程(面试必备)
android·java·面试·安卓
银色火焰战车2 小时前
浅析golang中的垃圾回收机制(GC)
java·jvm·golang
zhangjw342 小时前
第4篇:Java数组与字符串:从基础用法到面试高频考点
java·java基础知识
俺爱吃萝卜2 小时前
Spring Boot 3 + JDK 17:新一代微服务架构最佳实践
java·spring boot·架构
曹牧2 小时前
Spring :component-scan
java·后端·spring
风吹迎面入袖凉2 小时前
【Redis】Redis缓存击穿
数据库·redis·缓存
下地种菜小叶2 小时前
定时任务系统怎么设计?一次讲清任务注册、分布式调度、幂等执行与失败补偿
java·开发语言·数据库·oracle·rabbitmq
做个文艺程序员2 小时前
Spring Boot 项目集成 OpenClAW【OpenClAW + Spring Boot 系列 第1篇】
java·人工智能·spring boot·开源
withelios2 小时前
Java泛型全面理解指南
java