目录
[Redis 键空间 & 五大类型](#Redis 键空间 & 五大类型)
[1. String(字符串)](#1. String(字符串))
[2. List(链表,双端队列)](#2. List(链表,双端队列))
[3. Hash(哈希)](#3. Hash(哈希))
[4. Set(无序集合,去重)](#4. Set(无序集合,去重))
[5. ZSet(有序集合,排行榜)](#5. ZSet(有序集合,排行榜))
[6. 键空间运维](#6. 键空间运维)
[Spring Boot 集成 Redis(五大类型练习)](#Spring Boot 集成 Redis(五大类型练习))
环境与工具
在 WSL2 中用 Docker 拉起 redis:latest,映射 6379 和数据卷。
用 redis-cli 连上本地 Redis,完成 PING → PONG。
新建 Spring Boot 空项目,加入 spring-boot-starter-data-redis 依赖,跑通最简单的 StringRedisTemplate 读写。
具体实现:
一、环境准备
- 确认 WSL2 + Docker 安装
Windows 开启 WSL2,并安装 Ubuntu。
安装 Docker Desktop,设置后台引擎为 WSL2 集成。
在 WSL2 里输入:
bash
docker --version
确认能用
二、Docker 拉起 Redis
- 拉取官方镜像:
bash
docker pull redis:latest
- 启动容器(映射 6379 端口 & 挂载数据卷):
bash
docker run -d \
--name myredis \
-p 6379:6379 \
-v ~/redis-data:/data \
redis:latest \
redis-server --appendonly yes
-p 6379:6379 → 把容器端口映射到宿主机
-v ~/redis-data:/data → 把持久化数据挂载到宿主机
redis-server --appendonly yes → 开启 AOF 持久化
- 查看运行情况:
bash
docker ps
三、使用 redis-cli 测试
- 进入容器内运行 redis-cli:
bash
docker exec -it myredis redis-cli
- 测试连接:
bash
127.0.0.1:6379> PING
PONG
说明 Redis 已经启动成功。
Redis 键空间 & 五大类型
什么是键空间(Keyspace)
在 Redis 里,所有数据都是以键值对 (key-value) 的形式存储的。
键(key)= 唯一的名字(字符串)
值(value)= 可以是任意一种数据结构
Redis 内部就像有一个 巨大的字典(hash table),里面装满了这些 key-value
这个全局字典就叫做键空间
简单理解:
MySQL 有很多数据库,每个数据库里有很多表,每张表里有行。
Redis 有一个键空间,所有的 key 都放在这里,每个 key 指向一种数据类型的值
所以键空间意思就是所有键的存放空间
1. String(字符串)
bash
SET name "alice" # O(1)
GET name # "alice"
INCR counter # 自增(不存在时会设为 0 再 +1)
INCR counter # 再加 1 → counter = 2
EXPIRE counter 10 # 设置 10 秒过期
TTL counter # 查看剩余寿命
GETRANGE name 0 2 # 截取子串 → "ali"
MSET a 100 b 200 # 一次设置多个键
MGET a b # 一次获取多个键
INCR全称 INCRement,含义自增
EXPIRE 全称 EXPIRE(动词,过期),含义为某个键设置生存时间(TTL)
语义是告诉 Redis 这个键在 N 秒后过期
TTL全称是 Time To Live(生存时间),含义是返回某个键剩余还能活多久(单位秒)
GETRANGE 全称是GET RANGE,含义是获取字符串值的指定范围子串
参数:起始下标、结束下标(包含)
MSET: Multi SET(一次设置多个键值对)
MGET: Multi GET(一次获取多个键值)
前缀 M 表示批量操作
2. List(链表,双端队列)
bash
LPUSH nums 1 2 3 # 左插入 → nums = [3,2,1]
RPUSH nums 4 5 # 右插入 → nums = [3,2,1,4,5]
LRANGE nums 0 -1 # 遍历 → ["3","2","1","4","5"]
LPOP nums # 从左取一个 → "3"
BLPOP nums 5 # 阻塞式取(等待 5 秒)
LPUSH
L = Left(左边) PUSH = 入栈 / 插入
含义是从 左边(头部)插入一个或多个元素到列表。
LPUSH nums 1 2 3 把 1,2,3 依次插入左边,结果是 [3,2,1]
RPUSH
R = Right(右边)
PUSH = 插入
含义是从 右边(尾部)插入一个或多个元素
RPUSH nums 4 5 在右边插入,结果是 [3,2,1,4,5]
LRANGE
L = List
RANGE = 范围
含义是获取列表中指定范围的元素
参数是起始索引和结束索引,支持负数索引(-1 表示最后一个)
LRANGE nums 0 -1 → 取出整个列表
LPOP
L = Left(左边)
POP = 出栈 / 移除并返回
含义是从左边弹出一个元素,并返回该值
LPOP nums → 返回 "3",列表变成 [2,1,4,5]
BLPOP
B = Blocking(阻塞式)
LPOP = 左出栈
含义是从左边弹出一个元素,如果列表为空,就阻塞等待一段时间(直到有元素被插入,或超时)
BLPOP nums 5 → 如果 5 秒内有人 LPUSH 新值,就会立即返回,否则超时
3. Hash(哈希)
bash
HSET user:1 name "alice" age 20
HGET user:1 name
HGETALL user:1
HINCRBY user:1 age 1 # 年龄 +1 → age=21
HEXISTS user:1 email # 检查 email 是否存在
HSET
H = Hash
SET = 设置
含义是往哈希表里设置某个字段的值
HGET
H = Hash
GET = 获取
含义是获取哈希表里某个字段的值
HGETALL
ALL = 全部
含义是一次性取出哈希表里的所有字段和值
HINCRBY
INCRBY = increase by(增加多少)
含义是让某个字段的数值加上指定增量
HEXISTS
EXISTS = 是否存在
含义是检查某个字段是否存在
4. Set(无序集合,去重)
bash
SADD tags redis nosql cache
SMEMBERS tags # 查看所有成员
SISMEMBER tags redis # 是否存在 → 1
SADD tags2 redis db
SINTER tags tags2 # 交集 → redis
SCARD tags # 集合大小
SADD
S = Set
ADD = 添加
含义是向集合中添加一个或多个元素(自动去重)
SADD tags redis nosql cache = 向 tags 集合里加入 3 个元素
SMEMBERS
S = Set
MEMBERS = 成员们
含义是返回集合里的所有成员
SMEMBERS tags = 列出集合 tags 的全部元素
SISMEMBER
S = Set
ISMEMBER = 是否是成员
含义是判断某个值是不是集合中的元素(返回 1 表示存在,0 表示不存在)
SISMEMBER tags redis = 检查 redis 是否在集合里
SINTER
S = Set
INTER = Intersection(交集)
含义是返回多个集合的交集
SINTER tags tags2 = tags ∩ tags2
SCARD
S = Set
CARD = Cardinality(集合基数 = 元素个数)
含义是返回集合里元素的数量
SCARD tags 集合里有多少元素
5. ZSet(有序集合,排行榜)
bash
ZADD scores 100 "Alice" 200 "Bob" 150 "Cindy"
ZRANGE scores 0 -1 WITHSCORES # 按分数升序
ZREVRANGE scores 0 -1 WITHSCORES # 按分数降序(排行榜)
ZINCRBY scores 10 "Alice" # Alice 分数+10
ZREMRANGEBYRANK scores 0 0 # 删除排名最末 1 个
Redis 的 ZADD 命令要求严格按照 score member(分数在前,成员在后) 的顺序成对传入参数
ZADD
Z = ZSet (Sorted Set)
ADD = 添加
含义是往有序集合里添加一个或多个元素,并指定分数(score)
ZADD scores 100 "Alice" → 插入 "Alice",分数 = 100
ZRANGE
Z = ZSet
RANGE = 范围
含义是按分数升序,取指定下标范围的成员
ZRANGE scores 0 -1 → 获取所有元素,按分数从小到大排序
ZREVRANGE
Z = ZSet
REV = Reverse(反向)
RANGE = 范围
含义是按分数降序,取指定下标范围的成员
ZREVRANGE scores 0 -1 → 排行榜模式,从高分到低分
WITHSCORES 用于同时返回成员的分数
ZINCRBY
Z = ZSet
INCRBY = Increase by(增加多少)
含义是给某个成员的分数加上指定值
ZINCRBY scores 10 "Alice" → "Alice" 的分数 +10
ZREMRANGEBYRANK
Z = ZSet
REM = Remove(删除)
RANGE = 范围
BYRANK = 根据排名
含义是删除按排名排序后处于某个范围的元素
ZREMRANGEBYRANK scores 0 0 → 删除分数最低的 1 个
要删除分数最高的 3 个的成员,可以这样写:
bash
ZREMRANGEBYRANK key 0 2 # 错误:这会删除分数最低的3个
# 正确做法(删除分数最高的3个):
ZREMRANGEBYRANK key -3 -1
支持负数索引(-1 表示分数最高的成员)
6. 键空间运维
bash
SCAN 0 MATCH "user:*" COUNT 10 # 分批扫描键
DEL name # 删除
UNLINK nums # 异步删除(避免阻塞)
1. SCAN 0 MATCH "user:*" COUNT 10
作用:扫描键空间,分批返回 key,避免一次性返回太多阻塞 Redis。
参数:
0 → 游标位置,初始必须从 0 开始。返回结果里会带一个新的游标,下次继续扫描时用。直到返回 0 说明扫描完了。
MATCH "user:*" → 匹配模式,这里就是扫描所有以 user: 开头的键。
COUNT 10 → 建议每次返回 10 个 key
这个 COUNT 10 的意思是:我建议 Redis 每次最多返回 10 个 key
但 Redis 不会严格保证一定就是 10 个。可能返回 3 个、也可能 15 个
为什么要用 SCAN 而不是 KEYS *?
KEYS * 会一次性返回所有 key,可能导致 Redis 阻塞(特别是 key 很多时)
SCAN 是 渐进式迭代,对性能更安全。
2. DEL name
DEL = delete
作用:立即删除 key name 以及对应的 value。
特点:
同步删除(马上执行)
如果 value 特别大(比如一个包含百万条元素的 List),会阻塞 Redis 一段时间
3. UNLINK nums
UNLINK = unlink(断开链接)
作用:把 key nums 标记为删除,但实际释放内存的操作交给后台线程异步执行。
好处:不会阻塞主线程,适合删除大对象。
区别:
DEL → 立即释放内存(同步,可能卡顿)
UNLINK → 异步释放内存(更安全)
总结
SCAN:安全地扫描所有 key(代替 KEYS)
DEL:立即删除 key(小对象可用)
UNLINK:异步删除 key(大对象推荐)
Spring Boot 集成 Redis(五大类型练习)
- 用 [Spring Initializr](https://start.spring.io/) 创建项目:
Project: Maven / Gradle
Language: Java
Spring Boot: 最新稳定版
Dependencies: Spring Web, Spring Data Redis
- Maven 依赖(pom.xml):
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置 Redis 连接
在 application.yml 中写:
XML
spring:
data:
redis:
port: 6379
host: localhost
注入 StringRedisTemplate 和 RedisTemplate
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
@RestController
@RequestMapping("/redis")
public class RedisDemoController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// String 示例
@GetMapping("/string")
public String stringOps() {
stringRedisTemplate.opsForValue().set("name", "alice");
return stringRedisTemplate.opsForValue().get("name");
}
// List 示例
@GetMapping("/list")
public List<String> listOps() {
stringRedisTemplate.opsForList().leftPushAll("nums", "1", "2", "3");
return stringRedisTemplate.opsForList().range("nums", 0, -1);
}
// Hash 示例
@GetMapping("/hash")
public Map<Object, Object> hashOps() {
stringRedisTemplate.opsForHash().put("user:1", "name", "bob");
stringRedisTemplate.opsForHash().put("user:1", "age", "20");
return stringRedisTemplate.opsForHash().entries("user:1");
}
// Set 示例
@GetMapping("/set")
public Set<String> setOps() {
stringRedisTemplate.opsForSet().add("tags", "redis", "nosql", "cache");
return stringRedisTemplate.opsForSet().members("tags");
}
// ZSet 示例
@GetMapping("/zset")
public Set<String> zsetOps() {
stringRedisTemplate.opsForZSet().add("scores", "Alice", 100);
stringRedisTemplate.opsForZSet().add("scores", "Bob", 200);
return stringRedisTemplate.opsForZSet().reverseRange("scores", 0, -1);
}
}
启动项目 & 测试接口
Spring Boot 项目跑在 http://localhost:8080:
GET http://localhost:8080/redis/string → "alice"
GET http://localhost:8080/redis/list → ["3","2","1"]
GET http://localhost:8080/redis/hash → {"name":"bob","age":"20"}
GET http://localhost:8080/redis/set → ["redis","nosql","cache"]
GET http://localhost:8080/redis/zset → ["Bob","Alice"]
Template = Spring 的操作模板工具类,封装常用 API,简化操作,类似 JdbcTemplate、RestTemplate
String = 说明 key 和 value 都用字符串序列化,存进去/取出来都是明文
所以 StringRedisTemplate = 专门操作字符串类型的 Redis 工具类模板
ops = operations(操作入口)value = Redis 的 String 类型(键值对里的值)
opsForValue() = 获取操作 String 类型数据的工具
ops = operations(操作入口)List = Redis 的 List 类型(链表)
opsForList() = 获取操作 Redis List 的工具
leftPushAll对应 Redis 的 LPUSH 命令,往列表左边批量插入多个元素range对应 Redis 的 LRANGE 命令,按下标区间获取列表元素
put 对应 Redis 的 HSET 命令entries 对应 Redis 的 HGETALL 命令