浅显易懂——Redis、SpringDataRedis
文章目录
- redis基础认知
- 简介
- 核心特征
- 数据结构
- String(字符串)
- Hash(哈希)
- List
- Set
- Sorted Set(有序集合)
- 其它数据结构
- 常见误区
- Jedis、Lettuce
- 简介
- 示例
- Spring Data Redis
- 简介
- 示例
- Spring Data Redis 核心组件
- 开发要点
redis基础认知
简介
Redis是一个内存型数据库,专门用于高速存储和读取临时数据。与传统数据库(MySQL/Oracle )不同,Redis 把数据放在内存中操作,因此速度极快(微秒级响应)。
快递柜比喻:
- 传统数据库:你要寄快递时,需要开车去郊区的仓库(磁盘存储),路程远耗时长
- Redis:直接在小区门口设置智能快递柜(内存存储),存取物品只需30秒
核心特征
特征 | 说明 | 类比 |
---|---|---|
内存存储 | 数据主要在内存中操作,速度极快 | 快递柜就在楼下,随用随取 |
数据结构丰富 | 支持字符串、哈希、列表等5种核心结构 | 快递柜有小格(String)、大格(Hash)、冷冻柜(Sorted Set) |
持久化能力 | 可定期将内存数据保存到磁盘 | 每天凌晨把快递柜里的物品转存到仓库备份 |
数据结构
String(字符串)
场景:缓存HTML片段、用户会话;计数器;分布式锁
常用命令:
> SET user:1001 "张三" # 设置值
> GET user:1001 # 获取值
> INCR article:2023:views # 自增计数器
> SETEX token:abc 3600 "123" # 设置带过期时间的值(单位:秒)
java操作示例(先做了解~):
// 存储字符串
redisTemplate.opsForValue().set("user:1001", "张三");// 自增操作
Long views = redisTemplate.opsForValue().increment("article:2023:views");// 设置过期时间
redisTemplate.opsForValue().set("token:abc", "123", 3600, TimeUnit.SECONDS);
Hash(哈希)
场景:存储用户信息、商品属性;频繁修改部分字段的对象(如用户积分)
常用命令:
> HSET user:1001 name "李雷" age 28 # 设置多个字段
> HGET user:1001 name # 获取单个字段
> HGETALL user:1001 # 获取所有字段
> HINCRBY user:1001 score 10 # 增加数值字段
Java 操作示例:
// 存储对象
Map<String, Object> user = new HashMap<>();
user.put("name", "李雷");
user.put("age", 28);
redisTemplate.opsForHash().putAll("user:1001", user);// 获取单个字段
String name = (String) redisTemplate.opsForHash().get("user:1001", "name");// 增加数值
redisTemplate.opsForHash().increment("user:1001", "score", 10);
List
适用场景:消息队列(简易版);最新消息列表(如微博时间线);记录用户操作历史
常用命令:
> LPUSH news:latest "新闻A" # 头部插入元素
> RPUSH news:latest "新闻B" # 尾部插入元素
> LRANGE news:latest 0 4 # 获取前5条元素
> LPOP news:latest # 移除并返回头部元素
Java 操作示例:
// 头部插入元素
redisTemplate.opsForList().leftPush("news:latest", "新闻A");// 获取前5条元素
List<String> latestNews = redisTemplate.opsForList().range("news:latest", 0, 4);// 模拟队列操作(生产者-消费者)
redisTemplate.opsForList().rightPush("task_queue", "task1");
String task = redisTemplate.opsForList().leftPop("task_queue");
Set
适用场景:标签系统(文章标签);好友关系(共同好友);抽奖去重(确保用户不重复参与)
常用命令:
> SADD tags:2023 "Java" "Redis" # 添加元素
> SMEMBERS tags:2023 # 获取所有元素
> SISMEMBER tags:2023 "Java" # 检查元素是否存在
> SINTER tags:2023 tags:hot # 获取两个集合的交集
Java 操作示例:
// 添加标签
redisTemplate.opsForSet().add("tags:2023", "Java", "Redis");// 检查标签是否存在
boolean exists = redisTemplate.opsForSet().isMember("tags:2023", "Java");// 获取交集
Set<String> commonTags = redisTemplate.opsForSet().intersect("tags:2023", "tags:hot");
Sorted Set(有序集合)
适用场景:实时排行榜(游戏积分、热搜榜);延迟队列(用分数存储执行时间戳);带权重的任务调度
常用命令:
> ZADD leaderboard 95 "PlayerA" 80 "PlayerB" # 添加带分数的元素
> ZRANGE leaderboard 0 2 WITHSCORES # 获取前三名(升序)
> ZREVRANK leaderboard "PlayerA" # 获取降序排名
Java 操作示例:
// 添加玩家得分
redisTemplate.opsForZSet().add("leaderboard", "PlayerA", 95);
redisTemplate.opsForZSet().add("leaderboard", "PlayerB", 80);// 获取前3名(降序)
Set<ZSetOperations.TypedTuple<String>> top3 = redisTemplate.opsForZSet().reverseRangeWithScores("leaderboard", 0, 2);// 获取玩家排名
Long rank = redisTemplate.opsForZSet().reverseRank("leaderboard", "PlayerA");
其它数据结构
HyperLogLog
用途:基数统计(估算不重复元素数量,误差率约 0.81%)。
示例:统计网站 UV(独立访客)。
redisTemplate.opsForHyperLogLog().add("uv:20231001", "user1", "user2");
Long count = redisTemplate.opsForHyperLogLog().size("uv:20231001");
Bitmap(位图)
用途:位操作,适合二值状态统计(如用户签到)。
// 用户1001在第5天签到
redisTemplate.opsForValue().setBit("sign:1001", 5, true);
// 统计本月签到天数
Long count = redisTemplate.execute((RedisCallback<Long>) conn -> conn.bitCount("sign:1001".getBytes()));
Stream
用途:消息队列(支持消费者组、消息持久化)。
// 发送消息
Map<String, Object> message = new HashMap<>();
message.put("event", "order_paid");
message.put("orderId", "20231001123456");
redisTemplate.opsForStream().add("order_events", message);
常见误区
-
误区:Redis 是另一个 MySQL
真相:Redis 通常作为缓存层使用,MySQL 才是核心数据存储(类似快递柜不能替代仓库) -
误区:所有数据都该放 Redis
正确做法:只缓存高频访问数据(如用户会话、热门商品),冷数据仍存数据库 -
误区:Redis 数据永不丢失
实际情况:默认配置下重启会导致数据丢失,需配置持久化策略(类似快递柜断电时部分格子可能清空)
Jedis、Lettuce
简介
Jedis 和 Lettuce 都是 Java 程序与 Redis 通信的客户端库,就像是你与快递柜之间的“钥匙”或“遥控器”。它们帮助你在 Java 应用程序中方便地操作 Redis。
- Jedis:类似于传统的“钥匙”,你需要手动管理连接的创建和关闭。
- Lettuce:更像是现代的“遥控器”,支持更高级的功能(如异步操作、线程安全等),并且更适合高并发场景。
Jedis 和 Lettuce 是底层工具,直接与 Redis 进行通信。
示例
使用 Jedis
// 手动管理连接
Jedis jedis = new Jedis("localhost");
jedis.set("user:1001", "张三");
String name = jedis.get("user:1001");
jedis.close();
使用 Lettuce
// 自动管理连接,支持异步操作
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisAsyncCommands<String, String> asyncCommands = connection.async();
asyncCommands.set("user:1001", "张三").thenRun(() -> {asyncCommands.get("user:1001").thenAccept(System.out::println);
});
Spring Data Redis
简介
Spring Data Redis 是 Java 程序与 Redis 之间的翻译官。它帮你:
- 自动管理 Redis 连接池(不用手工开/关快递柜门)
- 提供简洁的 API 操作 Redis(封装了复杂的底层命令)
- 与 Spring 缓存注解无缝集成(@Cacheable等)
Spring Data Redis 是高层抽象,它基于 Jedis 或 Lettuce 提供更简单、更强大的功能。
在 Spring Boot 中,默认已集成 Lettuce。仅当需要切换为 Jedis 时,才需显式配置。
示例
redisTemplate.opsForValue().set("user:1001", "张三");
String name = (String) redisTemplate.opsForValue().get("user:1001");
Spring Data Redis 核心组件
组件 | 作用 | 类比 |
---|---|---|
RedisTemplate | 执行所有 Redis 操作的主入口 | 快递柜的总控面板 |
ConnectionFactory | 管理 Redis 服务器连接(如Jedis/Lettuce) | 快递柜的网络连接模块 |
@Cacheable | 自动缓存方法返回值 | 快递柜自动记住你常存的物品位置 |
开发要点
-
数据结构选择:根据业务场景选最合适的结构(80%性能优化来源于此)
- 需要排序 → Sorted Set
- 需要去重 → Set
- 需要快速查询单个属性 → Hash
-
内存管理:通过 maxmemory-policy 配置淘汰策略(如LRU淘汰最近最少使用的数据)
-
连接池配置:根据并发量调整连接数(类似控制快递柜同时使用的人数)
spring.redis.jedis.pool:max-active: 20 # 最大并发连接数max-idle: 10 # 最大空闲连接min-idle: 5 # 最小保持连接