Redis 入门教程:从基础命令到 Spring Boot 实战
本文面向 Redis 初学者,带你完成从安装启动、核心命令到 Java 项目实战的完整闭环,读完即可在 Spring Boot 项目中稳定使用 Redis。
⚡ 快速参考(先给答案)
- 适用场景:缓存热点数据、验证码、会话、排行榜、店铺营业状态等轻量共享状态
- 核心结论 :Redis 是内存型 key-value 数据库,快但内存宝贵;选对数据结构比"会命令"更重要;Java 项目建议优先使用
Spring Data Redis - 最短步骤 :安装并启动 Redis -> 用
redis-cli验证 -> 在 Spring Boot 注入RedisTemplate/StringRedisTemplate - 常用命令/代码 :
SET/GET、HSET/HGET、LPUSH/LRANGE、SADD/SMEMBERS、ZADD/ZRANGE - 避坑提醒 :生产环境避免滥用
KEYS *;注意序列化方案;所有 key 必须做业务前缀命名
📚 学习目标
- 理解 Redis 与关系型数据库的定位差异,以及常见业务场景。
- 掌握 5 种核心数据类型和高频命令,能独立完成命令行调试。
- 能在 Spring Boot 中完成 Redis 接入,并落地一个真实业务案例。
一、基础概念(是什么)
1.1 Redis 是什么
Redis(Remote Dictionary Server)是一个基于内存的键值型 NoSQL 数据库,特点是读写快、数据结构丰富、生态成熟。
- 键值模型 :所有数据都以
key -> value形式保存 - 高性能:核心操作在内存中完成,延迟低
- 多数据结构 :
string、hash、list、set、zset - 可持久化:支持把内存数据落盘
1.2 Redis 与 MySQL 的定位对比
| 维度 | Redis | MySQL |
|---|---|---|
| 数据模型 | key-value,结构灵活 | 表结构,约束严格 |
| 访问速度 | 非常快(内存) | 较快(磁盘+缓存) |
| 典型用途 | 缓存、状态、计数、排行榜 | 交易、订单、主数据 |
| 事务能力 | 支持但不以复杂事务为核心 | 强事务(ACID) |
实战建议:Redis 不是替代 MySQL,而是高频读写场景下的性能补充。
1.3 什么时候优先用 Redis
- 热点数据缓存(商品详情、首页配置)
- 临时数据(验证码、短信频控、登录态)
- 轻量状态(营业中/打烊中、开关配置)
- 实时统计(点赞数、在线人数、排行榜)
二、原理详解(为什么这样做)
2.1 Redis 为什么快
- 数据在内存中,减少磁盘随机 I/O。
- 命令执行路径短,数据结构针对场景优化。
- 单线程命令执行模型避免了复杂锁竞争(Redis 6+ 网络层有多线程,但命令执行仍是核心单线程模型)。
2.2 选错数据结构的代价
- 用
string硬存对象,字段更新不灵活,容易反复序列化。 - 用
set存有序数据,后续做排序会非常痛苦。 - 用
list当消息队列却不做阻塞消费或确认机制,可能丢数据或堆积。
2.3 Key 命名规范(强烈推荐)
统一使用分层命名,格式:
text
项目名:业务域:实体:标识
示例:
sky:shop:statussky:user:1001sky:product:2008
这样做的好处是:可读、可检索、可批量治理。
三、完整实战代码(怎么做)
3.1 环境准备
-
系统:Windows 10 / Linux(生产建议 Linux)
-
Redis:6.x 及以上
-
Java:8+
-
Spring Boot:2.x/3.x 均可
Redis安装包分为windows版和Linux版:
-
Windows版下载地址:https://github.com/microsoftarchive/redis/releases
-
Linux版下载地址: https://download.redis.io/releases/
启动后先验证连通性:
bash
redis-cli -h 127.0.0.1 -p 6379
ping
如果返回 PONG,说明连接正常。
3.2 Redis 常用命令速练(可直接复制)
Step 1:字符串 string
bash
SET name "redis"
GET name
SETEX code:login:13800138000 60 123456
SETNX lock:order:1001 1
说明:SETEX 常用于验证码,SETNX 常用于"仅第一次成功"的抢占逻辑。
Step 2:哈希 hash(对象字段)
bash
HSET user:1 name "Tom" age 20
HGET user:1 name
HGETALL user:1
HDEL user:1 age
说明:对象按字段存储时,hash 通常比整对象字符串更灵活。
Step 3:列表 list(有序可重复)
bash
LPUSH queue:task t1 t2 t3
LRANGE queue:task 0 -1
RPOP queue:task
LLEN queue:task
Step 4:集合 set(去重)
bash
SADD tag:java u1 u2 u3
SMEMBERS tag:java
SISMEMBER tag:java u2
SCARD tag:java
Step 5:有序集合 zset(排行榜)
bash
ZADD rank:score 100 tom 88 jack 95 lucy
ZRANGE rank:score 0 -1 WITHSCORES
ZINCRBY rank:score 10 jack
ZREVRANGE rank:score 0 2 WITHSCORES
3.3 Spring Boot 接入 Redis
1) 引入依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2) 配置连接信息
yaml
spring:
redis:
host: localhost
port: 6379
password: 123456
database: 0
3) 配置 RedisTemplate(避免默认 JDK 序列化不可读)
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
4) 测试写入
java
@SpringBootTest
class RedisDemoTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void testRedis() {
redisTemplate.opsForValue().set("tutorial:redis:name", "hello redis");
Object v = redisTemplate.opsForValue().get("tutorial:redis:name");
System.out.println(v);
}
}
3.4 业务小实战:店铺营业状态
需求:后台可设置"营业中/打烊中",用户端和管理端都能读取到同一状态。
设计:用 Redis string 存一个全局 key,例如 SHOP_STATUS,1 表示营业,0 表示打烊。
java
@RestController
@RequestMapping("/admin/shop")
public class ShopController {
private static final String KEY = "SHOP_STATUS";
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@PutMapping("/{status}")
public Result setStatus(@PathVariable Integer status) {
redisTemplate.opsForValue().set(KEY, status);
return Result.success();
}
@GetMapping("/status")
public Result<Integer> getStatus() {
Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
return Result.success(status);
}
}
这个案例简单但很典型:状态数据不复杂、读多写少、要求跨服务共享,非常适合 Redis。
四、场景应用(用在哪里)
场景 1:验证码与登录频控
- 需求:发送验证码后 60 秒有效,防止重复发送
- 方案:
SETEX sms:code:{phone} 60 {code},并配合计数器做频控 - 收益:实现简单、性能高、天然支持过期清理
场景 2:商品热榜
- 需求:展示"今日销量 TopN"
- 方案:使用
zset,商品 ID 为 member,销量为 score,定时刷新或实时累加 - 收益:查询 TopN 成本低,天然支持排序
五、开发避坑总结(高频错误)
5.1 典型问题清单
-
生产环境频繁使用
KEYS *原因:全量扫描会阻塞,key 多时影响性能。
解决:改用
SCAN分批遍历,并控制频率。 -
默认序列化导致 Redis 中数据乱码
原因:
RedisTemplate默认 JDK 序列化。解决:显式配置
StringRedisSerializer+ JSON 序列化器。 -
key 没有统一命名规范
原因:多人开发随意命名。
解决:统一
项目:业务:实体:ID命名,发布前做 key 规范检查。 -
忘记设置过期时间造成内存上涨
原因:临时数据永久驻留。
解决:验证码、token、临时缓存统一带 TTL。
5.2 最佳实践
- 缓存数据按业务分层命名,并设置合理 TTL。
- 命中率低的缓存先排查"key 设计"和"过期策略",再谈扩容。
- 把 Redis 当"高性能状态层",不要让它承担复杂关系查询。
六、面试考点(能说出来)
6.1 高频问题
-
Q1:Redis 为什么快?
A:核心是内存访问、数据结构优化和单线程命令执行模型,减少了锁竞争和上下文切换。
-
Q2:
string和hash存对象怎么选?A:对象整体读写多用
string;字段级更新频繁用hash,避免整对象反序列化开销。 -
Q3:生产为什么不建议
KEYS?A:
KEYS会遍历所有 key,阻塞风险高;线上用SCAN增量游标遍历更安全。
6.2 进阶追问
- Redis 持久化 RDB 和 AOF 的区别? -> 一个是快照,一个是追加日志,恢复速度与数据完整性侧重点不同。
- Redis 如何做缓存与数据库一致性? -> 常见策略是先更新数据库再删除缓存,配合重试/延迟双删降低不一致窗口。
七、总结(复盘与下一步)
- 本文解决了:Redis 从入门到 Java 落地的关键路径。
- 你现在可以:独立完成 Redis 安装、命令调试、Spring Boot 接入与基础业务实践。
- 下一篇建议:深入 Redis 高级特性(持久化、主从复制、哨兵与分片集群)。
本文为MY_TRUCK原创实战学习笔记,持续更新Java后端与AI应用领域干货,问题欢迎评论区交流。