基础使用
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 同时过期 → 加随机时间、高可用