Redis 核心概念与 Spring Boot 整合实战
本文档详细记录了 Redis 的安装、核心概念、常用命令以及在 Spring Boot 项目中的整合与使用方式。
1. 环境安装与启动
1.1 安装 Redis (MacOS)
使用 Homebrew 进行安装:
bash
brew install redis
1.2 启动服务
-
临时启动 (终端关闭后服务停止):
bashredis-server -
后台启动 (推荐,支持开机自启):
bashbrew services start redis
2. 核心概念
2.1 什么是 Redis?
Redis (Remote Dictionary Server) 是一个开源的、基于内存的非关系型数据库 (NoSQL)。
- 核心特点 :
- 基于内存:读写速度极快,适合处理高并发请求。
- 键值存储 :数据以
Key-Value形式存储,Key 也就是字符串,Value 支持多种数据结构。 - 应用场景:缓存(热点数据)、消息队列、分布式锁、排行榜等。
2.2 五大常用数据类型
Redis 的 Value 通常支持以下五种数据结构:
| 数据结构 | 英文名称 | 核心特点 | 典型应用场景 |
|---|---|---|---|
| 字符串 | String | 最基础类型,可存储字符串、数字,支持自增/自减。 | 缓存用户信息、计数器(阅读量)、分布式 Session、分布式锁。 |
| 哈希 | Hash | 键值对的集合(类似 Java 的 HashMap),适合存储对象。 |
存储对象详情(如用户:姓名、年龄、手机号)。 |
| 列表 | List | 有序字符串集合(双向链表),支持两端操作。 | 简单消息队列、最新动态列表(朋友圈)、任务排队。 |
| 集合 | Set | 无序且唯一的字符串集合,支持交集、并集运算。 | 去重(点赞用户)、共同好友、抽奖(随机获取)。 |
| 有序集合 | ZSet | 有序且唯一,每个元素关联一个 score (分数) 用于排序。 |
排行榜(游戏战力、热搜)、带权重的队列。 |

图 1:Redis 五种基本数据类型示意图
3. 常用命令详解
3.1 字符串 (String)
redis
# 设置 key 的值
SET key value
# 获取 key 的值
GET key
# 设置 key 的值,并指定过期时间 (单位: 秒)
# 场景: 验证码、缓存数据
SETEX key seconds value
# 只有在 key 不存在时设置值 (Set If Not Exists)
# 场景: 分布式锁
SETNX key value
3.2 哈希 (Hash)
Hash 特别适合用于存储对象。
redis
# 设置哈希表 key 中的字段 field 的值为 value
HSET key field value
# 获取哈希表 key 中指定字段 field 的值
HGET key field
# 删除哈希表 key 中的一个或多个字段
HDEL key field
# 获取哈希表中所有的字段名
HKEYS key
# 获取哈希表中所有的字段值
HVALS key
3.3 列表 (List)
简单的字符串列表,按照插入顺序排序。
redis
# 将一个或多个值插入到列表头部 (左侧)
LPUSH key value1 [value2]
# 获取列表指定范围内的元素 (0 -1 表示获取所有)
LRANGE key start stop
# 移除并获取列表最后一个元素 (右侧弹出)
RPOP key
# 获取列表长度
LLEN key
# 移出并获取列表的最后一个元素,如果列表为空则阻塞等待直到超时
# 场景: 阻塞队列
BRPOP key1 [key2] timeout
3.4 集合 (Set)
无序集合,成员唯一。
redis
# 向集合添加一个或多个成员
SADD key member1 [member2]
# 返回集合中的所有成员
SMEMBERS key
# 获取集合的成员数
SCARD key
# 返回给定所有集合的交集
SINTER key1 [key2]
# 返回所有给定集合的并集
SUNION key1 [key2]
# 移除集合中一个或多个成员
SREM key member1 [member2]
3.5 有序集合 (Sorted Set / ZSet)
不允许重复成员,通过 score 排序。
redis
# 向有序集合添加成员,同时指定分数
ZADD key score1 member1 [score2 member2]
# 通过索引区间返回有序集合中指定区间内的成员
# WITHSCORES: 同时返回分数
ZRANGE key start stop [WITHSCORES]
# 对指定成员的分数加上增量 increment
ZINCRBY key increment member
# 移除有序集合中的一个或多个成员
ZREM key member [member ...]
3.6 通用命令
不区分数据类型,全局可用。
redis
# 查找所有符合给定模式的 key (* 代表所有)
# 注意: 生产环境慎用,可能会阻塞服务器
KEYS pattern
# 检查给定 key 是否存在
EXISTS key
# 返回 key 所储存的值的类型
TYPE key
# 删除 key
DEL key
🔗 更多命令参考 :Redis 中文网
4. Spring Boot 整合 Redis
在 Java 开发中,我们通常使用 Spring Data Redis ,它对底层的 Jedis 或 Lettuce 进行了高度封装,提供了 RedisTemplate 来简化操作。
4.1 引入依赖
在 pom.xml 中添加 Starter 依赖。
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
4.2 配置数据源
在 application.yml 或 application.properties 中配置连接信息。

图 2:Redis 连接配置示例 (建议将敏感信息放在 dev 配置文件中)
yaml
spring:
redis:
host: localhost
port: 6379
password: yourpassword # 如果没有密码则留空
database: 0 # 指定数据库索引
4.3 配置 RedisTemplate (关键步骤)
默认的 RedisTemplate 使用 JDK 序列化,会导致 Redis 中存储的 Key 和 Value 出现乱码(二进制字符),不便于查看。我们需要配置序列化器。 value不进行序列化,因为value可能是多种不同的数据类型

图 3:未配置序列化器时,Redis 中的乱码现象
配置类实现:
java
@Configuration
@Slf4j
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
log.info("开始创建 Redis 模版对象...");
RedisTemplate redisTemplate = new RedisTemplate();
// 1. 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 2. 设置序列化器 (解决乱码问题)
// Key 使用 String 序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
// Value 也使用 String 序列化器 (也可以使用 Jackson2JsonRedisSerializer 转 JSON)
//redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}

图 4:Redis 配置类结构
5. 代码操作实战
通过单元测试演示 RedisTemplate 对五种数据类型的操作。

图 5:单元测试结构
5.1 操作字符串 (String)
java
@Test
public void testString(){
// opsForValue() 获取操作 String 类型的接口
// 1. set: 设置值
redisTemplate.opsForValue().set("city", "北京");
// 2. get: 获取值
Object city = redisTemplate.opsForValue().get("city");
System.out.println(city);
// 3. setex: 设置值并指定过期时间 (3分钟)
redisTemplate.opsForValue().set("code", "1234", 3, TimeUnit.MINUTES);
// 4. setnx: 如果 key 不存在才设置 (常用于分布式锁)
redisTemplate.opsForValue().setIfAbsent("lock", 1);
redisTemplate.opsForValue().setIfAbsent("lock", 2); // key 已存在,设置失败
}
5.2 操作哈希 (Hash)
java
@Test
public void testHash(){
// opsForHash() 获取操作 Hash 类型的接口
HashOperations hashOperations = redisTemplate.opsForHash();
// 1. hset: 存入字段
hashOperations.put("user:100", "name", "tom");
hashOperations.put("user:100", "age", "20");
// 2. hget: 获取指定字段
Object name = hashOperations.get("user:100", "name");
System.out.println(name);
// 3. hkeys: 获取所有 Key
Set keys = hashOperations.keys("user:100");
System.out.println(keys);
// 4. hvals: 获取所有 Value
List values = hashOperations.values("user:100");
System.out.println(values);
// 5. hdel: 删除字段
hashOperations.delete("user:100", "age");
}
5.3 操作列表 (List)
java
@Test
public void testList(){
// opsForList() 获取操作 List 类型的接口
ListOperations listOperations = redisTemplate.opsForList();
// 1. lpush: 从左侧存入多个值
listOperations.leftPushAll("mylist", "a", "b", "c");
listOperations.leftPush("mylist", "d"); // 结果: d, a, b, c
// 2. lrange: 获取范围内的元素 (0 到 -1 代表所有)
List mylist = listOperations.range("mylist", 0, -1);
System.out.println(mylist);
// 3. rpop: 从右侧弹出一个元素
listOperations.rightPop("mylist");
// 4. llen: 获取列表长度
Long size = listOperations.size("mylist");
System.out.println(size);
}
5.4 操作集合 (Set)
java
@Test
public void testSet(){
// opsForSet() 获取操作 Set 类型的接口
SetOperations setOperations = redisTemplate.opsForSet();
// 1. sadd: 添加元素 (自动去重)
setOperations.add("set1", "a", "b", "c", "d");
setOperations.add("set2", "a", "b", "x", "y");
// 2. smembers: 获取所有成员
Set members = setOperations.members("set1");
System.out.println(members);
// 3. scard: 获取集合大小
Long size = setOperations.size("set1");
System.out.println(size);
// 4. sinter: 求交集 (a, b)
Set intersect = setOperations.intersect("set1", "set2");
System.out.println(intersect);
// 5. sunion: 求并集
Set union = setOperations.union("set1", "set2");
System.out.println(union);
// 6. srem: 移除元素
setOperations.remove("set1", "a", "b");
}
5.5 操作有序集合 (ZSet)
java
@Test
public void testZset(){
// opsForZSet() 获取操作 ZSet 类型的接口
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
// 1. zadd: 添加元素并指定分数
zSetOperations.add("zset1", "a", 10);
zSetOperations.add("zset1", "b", 12);
zSetOperations.add("zset1", "c", 9);
// 2. zrange: 获取所有元素 (默认按分数升序)
Set zset1 = zSetOperations.range("zset1", 0, -1);
System.out.println(zset1);
// 3. zincrby: 增加指定元素的分数
zSetOperations.incrementScore("zset1", "c", 10); // c 变为 19
// 4. zrem: 移除元素
zSetOperations.remove("zset1", "a", "b");
}
5.6 通用命令操作
java
@Test
public void testCommon(){
// 1. keys: 获取所有匹配的 key (生产环境慎用)
Set keys = redisTemplate.keys("*");
System.out.println(keys);
// 2. hasKey: 判断 key 是否存在
Boolean hasName = redisTemplate.hasKey("name");
Boolean hasSet1 = redisTemplate.hasKey("set1");
// 3. type: 获取 key 的类型
for (Object key : keys) {
DataType type = redisTemplate.type(key);
System.out.println("Key: " + key + ", Type: " + type.name());
}
// 4. delete: 删除 key
redisTemplate.delete("mylist");
}