redis的学习
致敬作者:
1.Redis概述:
Redis是一个开源的内存数据结构存储系统,也被称为键值存储系统。它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等,并提供了丰富的操作命令,可以对这些数据结构进行快速的读写操作。Redis具有高性能、高可用性和可扩展性的特点,常用于缓存、消息队列、实时统计等场景。
- 特点:
- 基于内存: Redis 数据存储在内存中,因此具有非常高的读写性能。
- 持久化: Redis 支持多种持久化方式,可以将数据保存到磁盘中,以防止数据丢失。
- 数据结构丰富: Redis 支持丰富的数据结构,如字符串、哈希、列表、集合、有序集合等,使得它不仅仅是一个简单的键值对存储系统,还能支持更复杂的数据操作。
- 分布式: Redis 支持主从复制和集群模式,可以实现数据的自动分片和负载均衡,以提高系统的容量和可用性。
- 主要用途:
- 缓存: 作为高性能的缓存系统,用于存储频繁访问的数据,加速应用程序的读取速度。
- 会话存储: 用于存储用户会话相关的数据,如用户登录状态、购物车信息等。
- 消息队列: 可以通过 Redis 的发布订阅功能实现简单的消息队列系统,用于解耦应用程序的组件。
- 计数器/排行榜: Redis 的原子递增和有序集合功能,可以用于实现计数器和排行榜等功能。
- 数据持久化:
- Redis 提供了两种持久化方式:快照(RDB)和追加式文件(AOF)。
- RDB 持久化会定期将内存中的数据保存到磁盘上,适合用于备份和恢复。
- AOF 持久化会记录每条写命令,在服务器重启时重新执行这些命令来恢复数据。
- 高可用和集群:
- Redis 支持主从复制,一个主节点可以拥有多个从节点,实现数据的备份和读写分离。
- Redis 集群模式可以将数据分片存储在多个节点上,以提高系统的容量和可用性。
- 语言支持:
- Redis 客户端支持多种编程语言,如 Java、Python、Node.js 等,可以轻松与各种应用程序集成。
2.Redis数据结构:
-
字符串(String)
-
字符串是 Redis 中最基本的数据类型,它可以存储任意类型的数据,如数字、文本、二进制数据等。
-
用法示例:
SET key value # 设置键值对 GET key # 获取键对应的值 INCR key # 将键对应的值递增 1
-
-
哈希(Hash)
-
哈希是一种 key-value 结构,其中 key 是一个字符串,value 是一个键值对集合。
-
用法示例:
HSET key field value # 设置哈希表中的字段值 HGET key field # 获取哈希表中指定字段的值 HGETALL key # 获取哈希表中所有字段和值
-
-
列表(List)
-
列表是一组按顺序排列的字符串元素,可以在列表头或列表尾添加或删除元素。
-
用法示例:
LPUSH key value1 value2 # 在列表头添加元素 RPUSH key value1 value2 # 在列表尾添加元素 LPOP key # 删除并获取列表头元素 RPOP key # 删除并获取列表尾元素
-
-
集合(Set)
-
集合是一组无序、不重复的字符串元素,支持求交、并、差等操作。
-
用法示例:
SADD key member1 member2 # 向集合中添加元素 SREM key member1 # 从集合中删除元素 SMEMBERS key # 获取集合中所有元素
-
-
有序集合(Sorted Set)
-
有序集合是一组有序的字符串元素,每个元素都关联着一个分数,可以按照分数进行排序。
-
用法示例:
ZADD key score1 member1 # 向有序集合中添加元素 ZRANGE key start end # 获取有序集合中指定范围内的元素 ZREVRANGE key start end # 获取有序集合中指定范围内的元素(倒序)
-
3.Redis基本操作:
- 键值对操作
- 设置键值对:
SET key value
- 获取键对应的值:
GET key
- 删除键值对:
DEL key
- 设置键值对:
- 哈希操作
- 设置哈希表中的字段值:
HSET key field value
- 获取哈希表中指定字段的值:
HGET key field
- 获取哈希表中所有字段和值:
HGETALL key
- 设置哈希表中的字段值:
- 列表操作
- 在列表头添加元素:
LPUSH key value
- 在列表尾添加元素:
RPUSH key value
- 删除并获取列表头元素:
LPOP key
- 在列表头添加元素:
- 集合操作
- 向集合中添加元素:
SADD key member
- 从集合中删除元素:
SREM key member
- 获取集合中所有元素:
SMEMBERS key
- 向集合中添加元素:
- 有序集合操作
- 向有序集合中添加元素:
ZADD key score member
- 获取有序集合中指定范围内的元素:
ZRANGE key start end
- 获取有序集合中指定范围内的元素(倒序):
ZREVRANGE key start end
- 向有序集合中添加元素:
4.Redis雪崩,击穿,穿透
- Redis 雪崩
- Redis 雪崩是指缓存中大量的键同时过期失效,导致大量请求直接打到数据库上,导致数据库短时间内承受不了大量的请求而崩溃。
- 解决方案:
- 设置不同的过期时间,避免缓存同时失效。
- 使用 Redis 高可用方案,如 Redis Sentinel、Redis Cluster 等,保证 Redis 的高可用性。
- 在应用程序中实现限流措施,避免瞬间大量的请求打到数据库上。
- 对于必须从数据库中获取的数据,在 Redis 缓存失效时,直接从数据库中获取,并在重新写入缓存时设置较短的过期时间,避免缓存同时失效。
- Redis 击穿
- Redis 击穿是指缓存中不存在的键或者已经过期的键,导致请求直接打到数据库上,导致数据库短时间内承受不了大量的请求而崩溃。
- 解决方案:
- 在查询缓存之前,先判断键是否存在,如果不存在,直接返回空值,避免请求直接打到数据库上。
- 使用互斥锁(如分布式锁)或者信号量等机制,避免多个请求同时从数据库中获取同一个数据。
- 将热点数据预先加载到缓存中,避免缓存失效时直接打到数据库上。
- Redis 穿透
- Redis 穿透是指请求的键在缓存中不存在,每次请求都打到数据库上,导致数据库短时间内承受不了大量的请求而崩溃。
- 解决方案:
- 在查询缓存之前,先将键进行合法性校验,如对于非法的键(如负数),直接返回空值,避免请求直接打到数据库上。
- 对于缓存中不存在的键,返回默认值,并将默认值写入缓存中,避免缓存穿透问题。
- 使用布隆过滤器(Bloom Filter)等技术,过滤掉一部分肯定不存在的请求。
5.Redis发布订阅:
Redis 的发布订阅机制包括以下几个主要组件:
-
发布者(Publisher)
- 发布者向 Redis 服务器发送一个消息,并指定一个频道(Channel)。
- 发布者可以向多个频道发布消息。
-
订阅者(Subscriber)
- 订阅者可以订阅一个或多个频道,以接收发布者发送的消息。
- 订阅者可以随时取消订阅某个频道。
-
频道(Channel)
- 频道是消息的分类,发布者向指定的频道发送消息,订阅者只接收指定频道的消息。
- Redis 中的频道是动态创建的,没有预定义的频道。
-
消息(Message)
- 消息是发布者发送给订阅者的信息,可以是任何类型的数据。
Redis 的发布订阅机制的工作流程如下:
- 发布者向 Redis 服务器发送消息,并指定一个频道。
- Redis 服务器将消息发送给所有订阅了该频道的订阅者。
- 订阅者接收到消息后,可以进行相应的处理。在 Java 中使用 Redis 的发布订阅机制需要借助 Jedis 或者 Redisson 等第三方库来操作 Redis。下面我将分别用 Jedis 和 Redisson 两种方式来演示 Redis 的发布订阅机制。
使用 Jedis 操作 Redis 发布订阅机制示例:
首先,确保你已经引入了 Jedis 相关的依赖。
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
以下是一个简单的示例代码:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class RedisPubSubExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost", 6379);
// 订阅者
new Thread(() -> {
jedis.subscribe(new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println("Received message from channel [" + channel + "]: " + message);
}
}, "news");
}).start();
// 发布者
new Thread(() -> {
try {
Thread.sleep(1000); // 等待一秒钟再发布消息
jedis.publish("news", "Hello, this is a news");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
在上面的示例中,我们使用 Jedis 创建了一个订阅者线程和一个发布者线程。订阅者通过 jedis.subscribe()
方法来订阅频道,并通过 onMessage()
方法接收到消息。发布者通过 jedis.publish()
方法向指定频道发布消息。
使用 Redisson 操作 Redis 发布订阅机制示例:
同样地,在使用 Redisson 之前,需要确保你已经引入了 Redisson 的依赖。以下是一个使用 Redisson 的示例代码:
import org.redisson.Redisson;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
public class RedissonPubSubExample {
public static void main(String[] args) {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
// 订阅者
RTopic newsTopic = redisson.getTopic("news");
newsTopic.addListener((channel, message) -> {
System.out.println("Received message from channel [" + channel + "]: " + message);
});
// 发布者
new Thread(() -> {
try {
Thread.sleep(1000); // 等待一秒钟再发布消息
newsTopic.publish("Hello, this is a news");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
6.Redis事务:
Redis 支持的事务主要包括 MULTI、EXEC、DISCARD 和 WATCH 四种事务操作。下面我将详细说明每种事务的作用和用法:
- MULTI: MULTI 命令用于标记事务的开始,表示接下来的命令将作为一个事务进行处理。在 MULTI 执行后,所有接下来的命令都会被放入队列中等待执行,直到 EXEC 命令被调用。
- EXEC: EXEC 命令用于触发之前加入队列的事务中的所有命令执行。如果在执行事务期间出现错误,所有命令会被回滚,否则会一次性执行事务中的所有命令。
- DISCARD: DISCARD 命令用于取消事务,清空事务队列中的所有命令,恢复正常的非事务状态。可以在 MULTI 后、EXEC 前使用 DISCARD 来取消事务。
- WATCH: WATCH 命令用于在事务执行之前监视一个或多个键,并在事务执行时检查这些键是否被其他客户端修改。如果任何被监视的键被修改,事务将被取消,客户端需要重新执行事务。WATCH 可以保证事务执行过程中数据的一致性。
使用 Redis 的事务可以确保一系列命令在一个原子操作中执行,保证了这些命令的连贯性和一致性。事务还可以提高性能,减少网络开销,并减少并发操作时的竞争情况。
下面是一个简单的示例代码演示 Redis 事务的使用:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class RedisTransactionExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost", 6379);
// 开启事务
Transaction tx = jedis.multi();
// 将多个命令放入事务队列
tx.set("key1", "value1");
tx.set("key2", "value2");
// 执行事务
tx.exec();
// 关闭连接
jedis.close();
}
}
在上面的示例中,我们首先通过 jedis.multi()
开启一个事务,并将多个命令放入事务队列中。最后通过 tx.exec()
执行事务。如果需要取消事务,可以使用 tx.discard()
方法。这样就实现了简单的 Redis 事务操作。
7.Redis持久化:
Redis 提供了两种持久化方式来保证数据不会因为进程退出而丢失,分别是快照(snapshotting)和日志(append-only file)。
- 快照持久化(Snapshotting):
- Redis 会周期性地将内存中的数据生成一个快照文件(RDB 文件),这个快照文件是一个经过压缩的二进制文件,它包含了某个时间点上的 Redis 数据集。
- 快照持久化是通过
SAVE
或BGSAVE
命令来触发的。SAVE
命令会在执行期间阻塞 Redis 服务器,而BGSAVE
命令会在后台异步进行快照持久化,不会阻塞服务器。 - 当 Redis 服务器重启时,可以通过加载最近一次生成的 RDB 文件来恢复数据。
- 日志持久化(Append-Only File):
- Redis 的日志持久化是通过将所有写命令追加到一个文件中(AOF 文件)来实现的。这个文件包含了可以重建数据集的操作命令。
- Redis 服务器在启动时会通过重新执行 AOF 文件中的命令来恢复数据。在运行时,Redis 会将写命令追加到 AOF 文件的末尾,确保写操作的持久化。
- Redis 还提供了 AOF 文件的重写功能,通过重新生成一份更小的 AOF 文件来减少文件的体积。
选择适合的持久化方式:
- 如果对数据的完整性要求比较高,可以开启 AOF 持久化,以保证每条写命令都会被持久化到文件中,但需要注意 AOF 文件可能会比 RDB 文件大。
- 如果对数据的完整性要求不是非常严格,可以选择 RDB 持久化,因为 RDB 文件比 AOF 文件小,恢复数据也更快速。
8.Redis集群和主从复制:
Redis 集群: Redis 集群是为了解决单节点 Redis 的性能和容量限制而设计的分布式方案。它具有以下主要特点:
- 数据分片: Redis 集群将数据分散存储在多个节点上,每个节点负责存储部分数据。Redis 使用哈希槽(hash slot)来将数据分片到不同的节点上。默认情况下,集群有 16384 个哈希槽,每个节点负责一部分槽。
- 自动数据迁移: 当添加或删除节点时,Redis 集群会自动对数据进行重新分片和迁移,以达到均衡数据负载的目的。这意味着你可以动态地扩展或缩小集群的规模,而无需手动迁移数据。
- 故障转移: 当主节点发生故障时,Redis 集群会自动进行主从切换,将一个从节点提升为新的主节点。这个过程称为故障转移,旨在保证系统的高可用性。集群使用投票机制来选择新的主节点。
- 节点间通信和协调: Redis 集群使用 Cluster Bus 进行节点间的通信和协调工作。Cluster Bus 是一个基于 gossip 协议的轻量级通信机制,用于传播节点信息、集群状态变化、故障检测等。
- 客户端路由: 客户端发送的请求会根据键名计算哈希槽,并将请求发送到对应的节点。集群会维护一个槽与节点的映射表,以便正确地路由请求。
主从复制: Redis 主从复制是一种简单而有效的方式,用于提供数据的冗余备份和读取性能的提升。它具有以下主要特点:
- 主从关系: Redis 主从复制中有一个主节点(Master)和一个或多个从节点(Slave)。主节点负责处理写操作,并将写操作的日志传播给从节点。而从节点只负责接收主节点的写操作日志并进行复制。
- 数据复制: 主节点会将自己的数据复制到从节点,以确保数据的冗余备份。从节点会定期向主节点发送同步请求,获取最新的数据更新。
- 读写分离: 从节点可以用于处理读操作,从而减轻主节点的负载。客户端可以直接向从节点发送读请求,提高系统的读取性能。
- 故障恢复: 当主节点发生故障时,可以将一个从节点提升为新的主节点,以继续提供服务。Redis 主从复制具备自动故障转移的能力,能够在主节点故障后快速切换到新的主节点。
- 数据一致性: Redis 主从复制采用异步复制方式,从节点在接收到主节点的写操作之前可能存在一定的延迟。因此,在主节点故障恢复后,从节点的数据可能会与主节点略有不一致。
综上所述,Redis 集群和主从复制是两种不同的分布式方案,用于解决不同的需求。Redis 集群适合处理大规模数据和高并发访问的场景,提供自动分片和故障转移等功能;而主从复制适合提供冗余备份和读取性能优化的场景。根据实际需求,可以选择适合的方案或结合两者来使用。
9.redis哨兵:
Redis 哨兵(Sentinel)是 Redis 提供的一种高可用性解决方案,用于监控 Redis 主从复制集群中主服务器的状态,并在主服务器发生故障时自动进行故障转移,将一个从服务器升级为新的主服务器,以确保系统的持续稳定运行。以下是关于 Redis 哨兵的详细解释:
工作原理:
- 监控主服务器:哨兵通过定期向主服务器发送 PING 命令来监控主服务器的存活状态,如果主服务器无响应,则认为主服务器已下线。
- 选举领导者:当哨兵发现主服务器下线后,多个哨兵节点会进行选举,选择出一个哨兵节点作为领导者(leader)负责进行故障转移操作。
- 故障转移:领导者哨兵会与其他从服务器协商,选出一个从服务器作为新的主服务器,并将其他从服务器切换到新的主服务器上。
- 通知客户端:哨兵会向客户端发送通知,告知主从集群发生故障转移,客户端可以更新连接信息以连接到新的主服务器。
相关问题:
- 多哨兵部署:通常会部署多个哨兵节点,以防止单点故障和提高故障检测的准确性。
- 配置参数:需要在 Redis 配置文件中配置哨兵相关参数,如监控间隔、投票时间、故障转移超时等。
- 主从切换延迟:由于哨兵需要进行选举和协商过程,故障转移可能存在一定的延迟,需要根据业务需求来权衡。
- 健康检查:哨兵会定期检查主从服务器的健康状态,确保数据同步正常,避免出现数据不一致的情况。
通过部署 Redis 哨兵,可以有效提高 Redis 集群的可用性和稳定性,确保主从集群在主服务器故障时能够自动完成故障转移,减少系统宕机时间。在使用 Redis 哨兵时,需要注意配置参数、多哨兵部署和故障转移延迟等问题,以保证系统的正常运行和数据的安全性。
10.Redis缓存应用:
1. 高性能的读写操作: Redis 存储在内存中,因此读取和写入操作非常快速。这使得 Redis 成为一个优秀的缓存解决方案,能够显著减少应用程序对后端存储(如数据库)的访问次数,提高系统的响应速度。
2. 数据结构丰富: Redis 支持丰富的数据结构,包括字符串、哈希、列表、集合、有序集合等。这些数据结构的灵活性使得 Redis 能够适用于各种不同类型的缓存需求。
3. 缓存数据的过期和淘汰策略: Redis 允许为缓存数据设置过期时间,在数据过期后自动从内存中删除,这有助于节约内存空间。此外,Redis 也支持基于 LRU(Least Recently Used,最近最少使用)算法的内存淘汰策略,确保内存中始终存储着最有用的数据。
4. 发布与订阅: Redis 支持发布与订阅模式,允许客户端订阅特定的频道,并在频道上发布消息。这使得 Redis 不仅可以作为简单的键值存储,还可以用于实时消息传递和事件通知,适用于一些特定的缓存场景。
5. 分布式缓存: 通过 Redis 集群或者 Redis Sentinel(哨兵)来构建分布式缓存,以扩展缓存容量和提高可用性,同时保持良好的性能。
缓存应用场景:
- 页面缓存: 将经常访问但不经常变化的页面内容缓存到 Redis 中,以减轻对数据库的访问压力,提高页面加载速度。
- 会话缓存: 将用户会话信息、认证状态等存储在 Redis 中,以提升网站或应用的性能和可伸缩性。
- 对象缓存: 将数据库查询结果、常用对象等缓存到 Redis 中,避免重复查询和计算,提高数据访问速度。
11.Redis分布式锁:
1:实现原理: Redis 分布式锁的实现原理主要基于以下两个关键组件:
- SETNX(SET if Not eXists)命令: SETNX 命令在 Redis 中用于设置键值对,但只有在键不存在时才会进行设置。通过 SETNX 命令,可以保证只有一个客户端能够成功地将键设置为指定的值,即获取到了锁。
- 过期时间(Expiration): 为了避免锁一直被占用而导致死锁,我们可以为获取到锁的客户端设置一个过期时间(expiration time)。客户端在释放锁之前需要在指定的时间内完成任务,否则锁会自动释放,其他客户端可以获取到锁。
2:使用方法: 以下是使用 Redis 分布式锁的一般步骤:
- 客户端尝试执行以下操作:
- 使用 SETNX 命令尝试在 Redis 中设置一个特定的键作为锁。
- 如果 SETNX 返回 1(表示成功获取到锁),则客户端获得了锁,可以开始执行任务。
- 如果 SETNX 返回 0(表示锁已被其他客户端占用),则客户端没有获得锁,需要等待一段时间后重试或采取其他策略。
- 客户端执行任务:
- 客户端在获取到锁之后,开始执行需要互斥访问的任务。
- 注意:客户端应在规定的时间内完成任务,以免锁过期而被其他客户端获取。
- 客户端释放锁:
- 任务执行完成后,客户端通过删除锁的方式来释放锁,即使用 DEL 命令将锁对应的键从 Redis 中删除。
- 注意:客户端只能删除自己获取到的锁,以确保不会释放其他客户端持有的锁。
注意事项: 在使用 Redis 分布式锁时,还需要注意以下几点:
- 锁的持有时间应该合理设置,既要保证任务能在规定时间内完成,又要避免锁长时间占用而影响其他进程的执行。
- 获取锁和释放锁的过程应该是原子操作,可以使用 Redis 的 Lua 脚本来实现原子性。
- 需要处理异常情况,例如获取锁时客户端发生故障,锁未被正确释放的情况。
- 可以为锁添加唯一标识,以便识别不同的锁,并提供更多的操作,例如延长锁的持有时间。
3:演示
首先,你需要在项目中引入 Jedis 依赖,如果使用 Maven,可以在 pom.xml 中添加以下依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
接下来,我们通过 Java 代码来演示如何实现分布式锁:
import redis.clients.jedis.Jedis;
public class RedisDistributedLockDemo {
private static final String LOCK_KEY = "distributed_lock";
private static final int LOCK_EXPIRE_TIME = 10000; // 锁的过期时间,单位毫秒
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost"); // 连接本地的 Redis 服务
try {
// 尝试获取锁
if (acquireLock(jedis)) {
// 成功获取到锁,执行任务
System.out.println("成功获取到锁,开始执行任务...");
// 模拟执行任务
Thread.sleep(5000);
// 任务执行完毕,释放锁
releaseLock(jedis);
System.out.println("任务执行完毕,释放锁");
} else {
// 未获取到锁
System.out.println("未获取到锁,执行其他逻辑");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
jedis.close(); // 关闭连接
}
}
// 尝试获取锁
private static boolean acquireLock(Jedis jedis) {
long result = jedis.setnx(LOCK_KEY, "locked");
if (result == 1) {
// 设置锁的过期时间,防止死锁
jedis.pexpire(LOCK_KEY, LOCK_EXPIRE_TIME);
return true;
} else {
return false;
}
}
// 释放锁
private static void releaseLock(Jedis jedis) {
jedis.del(LOCK_KEY);
}
}
在上面的示例中,我们使用 Jedis 客户端连接到本地的 Redis 服务,并定义了 acquireLock
方法用于尝试获取锁,以及 releaseLock
方法用于释放锁。在 main
方法中,我们首先尝试获取锁,如果成功获取到锁,则执行模拟的任务并在任务完成后释放锁;如果未能获取到锁,则执行其他逻辑。
12.Redis与Spring整合:
将 Redis 与 Spring 框架整合通常使用 Spring Data Redis 这个模块来实现,Spring Data Redis 提供了一种简单而强大的方式来操作 Redis 数据库。下面是将 Redis 与 Spring 整合的详细步骤,并列出每一步所需的 Java 代码:
步骤一:添加依赖
在 Maven 项目中,需要在 pom.xml 文件中添加 Spring Data Redis 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
步骤二:配置 Redis 连接信息
在 Spring Boot 项目中,可以在 application.properties 或 application.yml 文件中配置 Redis 的连接信息:
application.properties:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=123
步骤三:创建 Redis 配置类
创建一个配置类,用于配置 RedisTemplate 和连接工厂:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
}
步骤四:使用 RedisTemplate 操作 Redis 数据
在 Spring 中,可以通过注入 RedisTemplate 对象来操作 Redis 数据库,以下是一个简单的示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void setValue(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void setValue(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String getValue(String key) {
return redisTemplate.opsForValue().get(key);
}
}
13:关于缓存的四个注解
-
@Cacheable:用于标记方法的结果可以被缓存,当下次使用相同的参数调用该方法时,会直接从缓存中获取结果,而不再执行方法体。
@Cacheable(cacheNames = "books") public Book getBookById(String id) { // 从数据库或其他数据源中获取书籍信息 return book; }
-
@CachePut:用于标记方法的结果应该被缓存,它会执行方法体,并将结果存储到缓存中,适用于更新缓存数据的场景。
@CachePut(cacheNames = "books", key = "#book.id") public Book updateBook(Book book) { // 更新数据库或其他数据源中的书籍信息 return book; }
-
@CacheEvict:用于标记方法执行后将缓存中的数据清除,适用于删除或修改缓存数据的场景。
@CacheEvict(cacheNames = "books", key = "#id") public void deleteBook(String id) { // 删除数据库或其他数据源中的书籍信息 }
-
@Caching:用于同时应用多个缓存注解,可以在一个方法中设置多个缓存操作。
@Caching( cacheable = @Cacheable(cacheNames = "books", key = "#id"), put = @CachePut(cacheNames = "books", key = "#result.id"), evict = @CacheEvict(cacheNames = "allBooks", allEntries = true) ) public Book getAndCacheBook(String id) { // 从数据库或其他数据源中获取书籍信息 return book; }