Redis学习笔记(一)

1、Redis基本概念

Redis(Remote Dictionary Server),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(Value)可以是字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等类型。

Redis的主要特点包括速度快、基于键值对的数据结构、功能丰富、支持数据持久化等。由于Redis将所有数据都存放在内存中,并使用单线程架构避免了多线程可能产生的竞争开销,因此其执行速度相对更快。此外,Redis还提供了键过期的功能,可以用来实现缓存;提供了发布订阅功能,可以用来实现简单的消息系统;支持Lua脚本,提供了简单的事务功能以及Pipeline功能等。

2、Redis是单线程的?

Redis的主要执行线程确实是单线程的,这也经常被称为Redis的单线程模型。在这种模型下,Redis使用一个线程来处理所有的网络请求,避免了多线程带来的线程切换和竞态条件的开销。这种设计使得Redis在处理大量简单的网络请求时能够保持非常高的性能。

然而,虽然主要的执行线程是单线程的,但Redis在某些情况下也会使用多个线程。例如,Redis在处理一些复杂的操作时,如数据持久化或某些类型的数据排序,可能会使用后台线程来处理,以避免阻塞主线程。此外,从Redis 6版本开始,也引入了线程池模型来处理高负载情况,实现多线程并发操作。但这种多线程的使用是在特定的情况下,并不是Redis的主要工作模式。

因此,可以说Redis主要是单线程的,但在某些情况下也会使用多线程来提高性能。这种设计使得Redis能够在处理大量网络请求时保持高效和稳定。

3、Redis为什么那么快?

  1. 基于内存的数据存储:Redis将所有数据存储在内存中,而内存的访问速度远远快于磁盘。这意味着Redis可以非常快速地读取和写入数据,而无需等待磁盘I/O操作完成。
  2. 优化的数据结构:Redis使用了一系列优化的数据结构来存储数据,如哈希表、跳表、压缩列表等。这些数据结构都是经过精心设计的,以在内存中高效地存储和访问数据。
  3. 单线程模型:Redis使用单线程模型来处理客户端的请求。这避免了多线程带来的线程切换和锁竞争等开销,使得Redis可以更加高效地处理请求。需要注意的是,尽管Redis的主要执行线程是单线程的,但它在某些情况下也会使用多个线程来处理后台任务或辅助操作。
  4. 高效的I/O多路复用技术:Redis使用I/O多路复用技术来处理多个客户端的连接和请求。这意味着Redis可以同时处理多个客户端的请求,而无需为每个客户端创建一个单独的线程或进程。这大大提高了Redis的并发处理能力。
  5. 简洁的设计和编码:Redis的代码库相对较小且简洁,这使得Redis的执行速度更快,也更容易进行维护和优化。

4、Redis的主要应用方向

  1. 缓存:Redis最常被用作缓存。由于其将数据存储在内存中,读写速度非常快,因此它经常被用来存储热点数据,如用户会话信息、数据库查询结果等,以提高系统的响应速度和性能。
  2. 数据库:虽然Redis是一个内存数据库,但它也提供了持久化功能,可以将内存中的数据定期写入磁盘,以防止数据丢失。因此,对于一些需要快速读写且数据量不是很大的应用场景,Redis也可以作为主数据库使用。
  3. 消息中间件:Redis提供了发布/订阅功能,可以实现简单的消息队列系统。此外,Redis还支持List、Set等数据结构,可以方便地实现消息的生产和消费。
  4. 计数器:Redis的原子操作功能使其成为一个优秀的计数器工具。例如,可以用Redis来实现网站的访问量统计、用户点赞数等功能。
  5. 分布式锁:Redis还可以作为分布式锁的实现工具。通过setnx、expire等命令,可以实现一个简单的分布式锁,用于保证在分布式系统中的数据一致性。
  6. 其他应用场景:除了以上几个常见应用场景外,Redis还可以用于实现排行榜、社交网络、实时分析等多种功能。

5、Redis如何保证与数据库数据一致?

  1. 使用事务

    • 数据库和Redis都支持事务,但它们的实现方式可能不同。
    • 对于需要同时更新Redis和数据库的操作,可以考虑使用事务来确保操作的原子性。
    • 然而,由于Redis和数据库通常是两个不同的系统,它们之间的事务并不能直接协调。因此,你可能需要在应用程序中实现一种机制来确保两者的一致性。
  2. 双写策略

    • 当更新数据库时,同时更新Redis。这可以通过在写入数据库后直接更新Redis来实现。
    • 但是,双写策略可能会导致数据竞争条件,特别是在高并发环境下。例如,一个线程可能更新了数据库但还没来得及更新Redis,而另一个线程读取了旧的Redis数据并进行了更新。
  3. 延迟双删策略

    • 为了解决双写策略中的数据不一致问题,可以采用延迟双删策略。即先删除Redis中的数据,更新数据库,然后等待一段时间(根据业务逻辑的耗时来确定),再次删除Redis中的数据。
    • 这种策略可以减少数据不一致的窗口时间,但仍然不能完全消除数据不一致的可能性。
  4. 使用消息队列(MQ)

    • 引入消息队列来异步处理Redis和数据库之间的数据同步。
    • 当需要更新数据时,将数据发送到消息队列,然后由后台任务异步处理数据库的更新和Redis的同步。
    • 这种方法可以减少应用程序的响应时间,并通过确保消息的顺序处理来维护数据的一致性。
  5. 定期同步

    • 定期从数据库同步数据到Redis,或者反过来从Redis同步数据到数据库。
    • 这种策略适用于数据更新不频繁或对数据实时性要求不高的场景。
  6. 使用分布式锁

    • 在更新Redis和数据库之前获取分布式锁,以确保同一时间只有一个操作可以更新数据。
    • 分布式锁可以使用Redis本身实现(如使用Redis的SETNX命令),也可以使用其他分布式锁服务。
  7. 选择合适的同步策略

    • 根据具体的应用场景和数据一致性要求选择合适的同步策略。例如,对于读多写少的场景,可以考虑使用缓存优先的策略;对于写多读少的场景,可以考虑使用数据库优先的策略。
  8. 监控和告警

    • 监控Redis和数据库之间的数据一致性,并在检测到不一致时触发告警。
    • 这可以帮助你及时发现和解决数据一致性问题。

6、缓存穿透的概念和解决方案

缓存穿透是指查询一个一定不存在的数据。由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。在某些情况下,攻击者可能会利用这个漏洞,对数据库造成压力,甚至压垮数据库。

解决缓存穿透的方法有多种,以下是一些常见的策略:

  1. 布隆过滤器(Bloom Filter):这是一种空间效率极高的随机数据结构,它利用位数组来表示集合,并通过哈希函数将元素映射到位数组上。在查询数据时,先判断该数据是否存在于布隆过滤器中,如果存在则直接返回结果(通常是一个空对象或者默认值),否则再从数据库中查询数据。布隆过滤器的缺点是它可能会产生误报,即认为某些不在集合中的元素是在集合中的,但这种情况可以通过调整哈希函数的数量和位数组的大小来控制。
  2. 缓存空对象:当从数据库查询不到数据时,可以将一个空对象或者默认值写入缓存,这样下次同样的查询就可以直接从缓存中获取,而不需要再次查询数据库。但这种方法需要注意缓存空对象的过期时间,以防止缓存过多无用的空对象。
  3. 设置热点数据永不过期:对于一些经常被查询但又不经常变化的数据,可以设置它们在缓存中永不过期,这样即使缓存未命中,也不会对数据库造成太大的压力。
  4. 使用分布式锁:在查询数据前先使用分布式锁进行加锁,保证只有一个线程能够访问数据库,其他线程需要等待锁释放后才能进行查询。这样可以防止大量的并发查询对数据库造成压力。但这种方法可能会降低系统的并发性能。
  5. 接口层增加校验:例如,用户鉴权校验、ID基础校验等,可以在接口层就拦截掉一些无效的查询请求,从而减轻数据库的压力。
  6. 使用数据库的缓存机制:一些数据库提供了自己的缓存机制,如MySQL的查询缓存等。开启这些缓存机制可以将一些查询结果缓存到数据库中,减少对数据库的访问次数。但需要注意的是,这些缓存机制可能会因为数据的更新而失效,因此需要合理地设置缓存的过期时间和更新策略。

7、缓存雪崩的概念和解决方案

缓存雪崩是指在使用缓存系统时,由于缓存中的大量数据同时失效或者缓存系统发生故障,导致大量的请求直接访问后端存储系统,从而给后端系统造成巨大的负载压力,使得后端系统性能降低甚至瘫痪。缓存雪崩是一种严重的性能问题,需要采取适当的措施来预防和解决。

缓存雪崩的解决方案可以从以下几个方面考虑:

  1. 缓存过期时间分散:为了避免缓存同时失效,可以为每个缓存项设置不同的过期时间,使得缓存失效时间分布均匀,减少大量请求同时到达后端存储系统的情况。
  2. 数据预热:在系统上线后,将相关的缓存数据直接加载到缓存系统,避免在用户请求时先查询数据库。这样可以减少缓存失效时对数据库的压力。
  3. 互斥锁:在高并发场景下,为了避免大量的请求同时到达存储层查询数据、重建缓存,可以使用互斥锁控制。例如,根据key去缓存层查询数据,当缓存层未命中时,对key加锁,然后从存储层查询数据,将数据写入缓存层,最后释放锁。这样可以保证只有一个请求去查询数据库并重建缓存,其他请求会等待锁释放后直接从缓存中获取数据。
  4. 双层缓存策略:设置两层缓存,原始缓存和拷贝缓存。原始缓存失效时可以访问拷贝缓存,拷贝缓存失效时间设置为长期。这样可以减少缓存失效时对数据库的压力,提高系统的可用性。
  5. 限流与降级:在缓存层或存储层设置限流与降级机制,当请求量过大或系统出现故障时,可以通过限流来保护后端存储系统,同时通过降级来保障核心功能的可用性。
  6. 定期更新缓存:对于失效性要求不高的缓存,可以在容器启动初始化时加载,并采用定时任务来更新或移除缓存。这样可以避免缓存过期导致的雪崩问题。
  7. 监控与告警:建立完善的监控和告警机制,实时监测缓存系统的状态、请求量、响应时间等指标。当发现异常情况时,及时触发告警并通知相关人员处理。

8、Redis持久化方式

Redis提供了两种持久化方案:RDB(Redis DataBase)和AOF(Append Only File)。

  1. RDB持久化

    • RDB是Redis默认的持久化方案。当Redis需要持久化时,它会fork一个子进程,子进程会将父进程的内存数据写入到一个临时文件中,待持久化过程结束后,再用这个临时文件替换上次持久化好的文件。因此,RDB持久化可以看作是Redis内存数据的快照。
    • RDB持久化的优点是文件紧凑,节省磁盘空间,恢复速度快。因为直接加载RDB文件到内存即可恢复数据。但是,RDB持久化也有一些缺点,比如无法做到实时持久化,可能会丢失最近一次快照以后更改的数据;同时,因为需要fork子进程进行持久化操作,所以当数据集较大时,fork操作可能会消耗较多的时间和资源。
  2. AOF持久化

    • 与RDB不同,AOF持久化是通过记录Redis的所有写命令来保存数据。当Redis开启AOF持久化功能时,每当执行一个写命令(如SET、RPUSH等),Redis就会将该命令追加到一个AOF文件中。当需要恢复数据时,Redis会重新执行AOF文件中的所有命令来重建数据集。
    • AOF持久化的优点是可以提供更高的数据安全性,因为它记录了每一个写命令,所以即使Redis意外宕机,也可以通过重新执行AOF文件中的命令来恢复数据到最近一次操作的状态。但是,AOF持久化也有一些缺点,比如AOF文件可能会比RDB文件大得多,因为AOF文件需要记录每一个写命令;同时,Redis在加载AOF文件时需要执行所有的命令来重建数据集,这可能会比加载RDB文件慢得多。

为了平衡这两种持久化方案的优缺点,Redis还提供了混合持久化的选项。混合持久化结合了RDB和AOF两种方式:在指定的时间间隔内执行一定数量的写命令后,Redis会生成一个RDB快照并追加到AOF文件中;同时,Redis也会将后续的写命令追加到AOF文件中。这样既可以保证数据的安全性又可以减少AOF文件的大小和加载时间。

9、Redis的主从、哨兵、集群模式

Redis提供了三种主要的运行模式:主从模式、哨兵模式和集群模式,用于满足不同场景下的数据存储和访问需求。下面将对这三种模式进行简要讲解。

  1. 主从模式

    • 主从模式涉及到一个主服务器(Master)和多个从服务器(Slave)。在这种模式下,主服务器可以进行读写操作,而从服务器通常是只读的,它们接收主服务器的数据更新。主从模式常用于实现数据的备份、故障转移以及提高读操作的性能。
    • 当写操作导致主服务器的数据发生变化时,主服务器会自动将这些变化同步给从服务器,确保主从数据的一致性。一个主服务器可以拥有多个从服务器,但从服务器只能有一个主服务器。
    • 主从模式的缺点包括主服务器的单点故障风险,即从服务器无法自动升级为新的主服务器;此外,如果主服务器出现故障,整个系统将无法处理写操作,只能读取数据。
  2. 哨兵模式

    • 哨兵模式是Redis的高可用性解决方案,通过引入哨兵(Sentinel)进程来监控主从服务器的状态,并在主服务器发生故障时自动进行故障转移。
    • 哨兵进程会周期性地向主从服务器发送命令(如PING)来检查它们的状态。一旦主服务器被检测为不可达,哨兵进程将根据投票算法从多个从服务器中选举出一个新的主服务器,并通过消息通知其他从服务器更新其主服务器的配置。
    • 哨兵模式可以通过部署多个哨兵进程来增强监控的健壮性,避免单个哨兵进程的故障影响整个系统的可用性。
    • 哨兵模式的缺点是它仍然存在一定的单点故障风险,特别是当多数哨兵进程出现故障时;此外,配置和维护哨兵模式需要额外的努力。
  3. 集群模式

    • Redis集群模式是Redis为了解决单机容量瓶颈、提供高可用性和线性可扩展性而推出的功能。
    • 在集群模式下,Redis的数据被划分为多个分片(shard),每个分片存储在不同的Redis实例(即节点)上。每个节点负责处理一部分数据的读写操作,实现了数据的分布式存储和访问。
    • Redis集群提供了内置的数据分片和复制机制。通过分片,可以将数据分布在多个节点上,从而实现横向扩展;而通过复制,可以确保数据的冗余备份,提高系统的可用性。
    • 集群模式下的Redis实例可以通过网络进行通信和协作,以实现数据的分布式处理和高可用性。当一个节点发生故障时,其他节点可以接管该节点的数据和处理任务,确保系统的连续运行。

综上所述,Redis的主从、哨兵和集群模式各具特点,适用于不同的场景和需求。主从模式适用于简单的数据备份和读负载均衡场景;哨兵模式适用于需要自动故障转移和高可用性保障的场景;而集群模式则适用于需要处理大规模数据、实现横向扩展和高可用性的复杂场景。

10、Redis常用数据结构

Redis支持多种数据结构,每种数据结构都有特定的使用场景和相应的增删改查操作方法。以下是Redis中一些常见的数据结构及其使用方法的例子,包含增删改查操作:

1. 字符串(Strings)

数据结构:简单的键-值对。

  • SET key value:设置键值对。

  • GET key:获取键对应的值。

  • SET key newvalue:修改键对应的值(实际上也是增操作,因为如果不存在会创建)。
  • INCR key:将键对应的值增加1(仅适用于整数值)。

  • DEL key:删除键及其对应的值。

2. 哈希(Hashes)

数据结构:键值对的集合,其中值本身也是键值对(字段-值)。

增/改

  • HSET key field value:设置哈希表中的字段和值,如果字段已存在则修改其值,不存在则新增。

  • HGET key field:获取哈希表中指定字段的值。
  • HGETALL key:获取哈希表中所有字段和值。

  • HDEL key field [field ...]:删除哈希表中一个或多个字段及其值。

3. 列表(Lists)

数据结构:有序的字符串列表。

  • LPUSH key value [value ...]:在列表左侧插入一个或多个值。
  • RPUSH key value [value ...]:在列表右侧插入一个或多个值。

  • LRANGE key start stop:获取列表中指定范围内的元素。
  • LINDEX key index:获取列表中指定索引的元素。

  • LSET key index value:设置列表中指定索引的元素值。

  • LPOP key:移除并返回列表左侧的元素。
  • RPOP key:移除并返回列表右侧的元素。
  • LREM key count value:移除列表中与指定值相等的元素。

4. 集合(Sets)

数据结构:无序的字符串集合,每个字符串在集合中是唯一的。

  • SADD key member [member ...]:向集合中添加一个或多个成员。

  • SMEMBERS key:获取集合中的所有成员。
  • SISMEMBER key member:检查成员是否存在于集合中。

:实际上集合没有直接的修改操作,因为成员是唯一的,添加已存在的成员不会有任何效果。

  • SREM key member [member ...]:移除集合中一个或多个成员。

5. 有序集合(Sorted Sets)

数据结构:类似于集合,但每个字符串都关联着一个浮点数分数,用于排序。

  • ZADD key score member [score member ...]:向有序集合中添加一个或多个成员及其分数。

  • ZRANGE key start stop [WITHSCORES]:获取有序集合中指定范围内的成员(可带分数)。
  • ZRANK key member:获取成员在有序集合中的排名(按分数从小到大)。

  • ZINCRBY key increment member:增加有序集合中指定成员的分数。

  • ZREM key member [member ...]:移除有序集合中一个或多个成员。

这些示例展示了Redis不同数据结构的基本增删改查操作。在实际应用中,你可能需要结合多种数据结构来实现复杂的功能。

11、Redis常用框架

  1. Jedis:Jedis是Redis的Java实现客户端,提供了比较全面的Redis命令的支持。它支持基本的数据类型如:String、Hash、List、Set、Sorted Set等。Jedis的API与Redis的命令非常相似,因此易于学习和使用。
  2. Lettuce:Lettuce是一个高级Redis客户端,用于线程安全同步、异步和响应使用。它支持集群、Sentinel、管道和编码器。Lettuce的API是线程安全的,因此可以操作单个Lettuce连接来完成各种操作。这使得Lettuce非常适合在分布式环境中使用。
  3. Redisson:Redisson实现了分布式和可扩展的Java数据结构,不仅提供了同步方式的访问,还提供了异步方式、反应式以及RxJava2的访问方式。此外,Redisson还实现了Redis的发布/订阅、事务、脚本、分布式锁、分布式对象等功能。这使得Redisson在需要复杂数据结构和分布式功能的场景中非常有用。

1、Jedis使用举例

在Spring Boot中使用Jedis作为Redis的客户端,你需要首先添加相关的依赖到你的pom.xml文件中,然后配置Redis的连接信息,并创建一个配置类来设置JedisPool。下面是一个简单的例子来说明如何在Spring Boot中使用Jedis。

  1. 添加依赖

pom.xml文件中添加Jedis和Spring Boot Data Redis的依赖:

<dependencies>
    <!-- Spring Boot Data Redis Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- Jedis Client -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.7.0</version> <!-- 请检查是否有更新的版本 -->
    </dependency>
</dependencies>
  1. 配置Redis连接信息

application.propertiesapplication.yml文件中配置Redis的连接信息:

# application.properties
spring.redis.host=localhost
spring.redis.port=6379

或者

# application.yml
spring:
  redis:
    host: localhost
    port: 6379
  1. 创建Jedis配置类

创建一个配置类来设置JedisPool,并提供一个Jedis的Bean供其他类使用:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Bean
    public JedisPool jedisPool() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(1000); // 控制一个pool可分配多少个jedis实例
        poolConfig.setMaxWaitMillis(10000); // 最大建立连接等待时间
        // 其他配置可以根据需要进行设置...
        return new JedisPool(poolConfig, host, port);
    }

    @Bean
    public Jedis jedis() {
        return jedisPool().getResource();
    }
}

注意:在实际生产环境中,通常不会直接提供一个Jedis的Bean,因为这样会导致每次注入时都获取一个新的Jedis实例,而不是复用已经存在的实例。相反,你会更倾向于注入JedisPool并在需要时从中获取和释放资源。这里为了简化示例,我直接提供了一个Jedis的Bean。但在实际应用中,请考虑使用JedisConnectionFactoryRedisTemplateStringRedisTemplate等更高级的抽象来处理Redis操作。

  1. 使用Jedis进行操作

现在你可以在其他类中注入Jedis并使用它来执行Redis操作了:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

@Service
public class RedisService {

    private final Jedis jedis;

    @Autowired
    public RedisService(Jedis jedis) {
        this.jedis = jedis;
    }

    public void setKeyValue(String key, String value) {
        jedis.set(key, value);
    }

    public String getKeyValue(String key) {
        return jedis.get(key);
    }
    
    // 其他Redis操作...
}

注意:在实际应用中,请确保在使用完Jedis实例后正确关闭它,以避免资源泄漏。如果你使用的是JedisPool,则应该调用jedis.close()来释放资源回池。如果你使用的是Spring提供的更高级别的抽象(如RedisTemplate),则通常不需要手动管理这些资源。

2、Lettuce使用举例

在Spring Boot中使用Lettuce作为Redis的客户端是非常常见的做法,因为Lettuce是一个线程安全的、高性能的Redis客户端,它支持同步、异步和响应式操作模式。Spring Boot Data Redis Starter默认就包含了Lettuce的依赖,所以你通常不需要额外添加Lettuce的依赖。

下面是一个使用Lettuce在Spring Boot中进行Redis操作的例子:

  1. 添加依赖

pom.xml文件中添加Spring Boot Data Redis Starter的依赖(如果你还没有添加的话):

<dependencies>
    <!-- Spring Boot Data Redis Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- 其他依赖... -->
</dependencies>
  1. 配置Redis连接信息

application.propertiesapplication.yml文件中配置Redis的连接信息:

# application.properties
spring.redis.host=localhost
spring.redis.port=6379

或者

# application.yml
spring:
  redis:
    host: localhost
    port: 6379
    # 如果设置了密码
    password: yourpassword
    # 其他可选配置,比如连接池、超时设置等
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: -1ms
  1. 使用StringRedisTemplateRedisTemplate进行操作

Spring Boot提供了StringRedisTemplateRedisTemplate类来简化Redis操作。这些类封装了底层的Redis客户端(在这个例子中是Lettuce),并提供了方便的方法来执行常见的Redis命令。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class RedisService {

    private final StringRedisTemplate stringRedisTemplate;

    @Autowired
    public RedisService(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public void setKeyValue(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    public String getKeyValue(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    // 其他Redis操作...
}

在这个例子中,RedisService类注入了StringRedisTemplate,它用于操作字符串类型的Redis键值对。你可以使用opsForValue()方法来获取一个操作字符串值的操作对象,然后调用其方法来执行各种Redis命令。

  1. 启动应用程序并测试

现在你可以启动你的Spring Boot应用程序,并使用RedisService来执行Redis操作了。例如,在一个控制器中注入RedisService,并提供一个端点来测试设置和获取键值对:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/redis")
public class RedisController {

    private final RedisService redisService;

    @Autowired
    public RedisController(RedisService redisService) {
        this.redisService = redisService;
    }

    @GetMapping("/set")
    public String setKeyValue(@RequestParam String key, @RequestParam String value) {
        redisService.setKeyValue(key, value);
        return "Key-value pair set successfully!";
    }

    @GetMapping("/get")
    public String getKeyValue(@RequestParam String key) {
        String value = redisService.getKeyValue(key);
        return "Value for key '" + key + "': " + value;
    }
}

现在,你可以通过HTTP请求来测试你的Redis操作了。例如,发送一个GET请求到/redis/set?key=mykey&value=myvalue来设置一个键值对,然后发送一个GET请求到/redis/get?key=mykey来获取该键的值。

3、Redisson使用举例

在Spring Boot中使用Redisson作为Redis的Java客户端时,你将享受到Redisson提供的功能强大的Redis操作和连接管理能力。Redisson在Redis的基础上提供了很多分布式服务和Java对象的映射。

以下是如何在Spring Boot项目中使用Redisson的简单例子:

  1. 添加依赖

pom.xml中添加Redisson的依赖:

<dependencies>
    <!-- Redisson -->
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>最新版本</version>
    </dependency>
    <!-- 其他依赖... -->
</dependencies>

注意替换<version>最新版本</version>为Redisson的最新版本号。

  1. 配置Redisson

application.ymlapplication.properties文件中配置Redisson:

# application.yml
spring:
  redis:
    host: localhost
    port: 6379

redisson:
  address: "redis://${spring.redis.host}:${spring.redis.port}"
  password: yourpassword # 如果有设置密码的话
  database: 0 # 默认使用的数据库编号
  # 其他Redisson特定配置

或者使用application.properties

# application.properties
spring.redis.host=localhost
spring.redis.port=6379

redisson.address=redis://${spring.redis.host}:${spring.redis.port}
redisson.password=yourpassword
redisson.database=0

请注意,这里使用了redisson.address属性来指定Redis的地址,其中${spring.redis.host}${spring.redis.port}是之前定义的Spring属性占位符。

  1. 创建Redisson配置类

接下来,你需要创建一个配置类来配置和初始化Redisson客户端:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

    @Value("${redisson.address}")
    private String address;

    @Value("${redisson.password}")
    private String password;

    @Value("${redisson.database}")
    private int database;

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress(address)
                .setPassword(password)
                .setDatabase(database);

        // 创建Redisson实例
        RedissonClient redisson = Redisson.create(config);

        // 关闭Redisson时要调用的shutdown方法
        Runtime.getRuntime().addShutdownHook(new Thread(redisson::shutdown));

        return redisson;
    }
}

在这个配置类中,我们通过读取配置文件中的属性值来设置Redisson的配置,并且创建了一个RedissonClient Bean供应用程序其他部分使用。

  1. 使用Redisson

现在,你可以在应用程序中使用RedissonClient了:

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class RedisLockService {

    private final RedissonClient redissonClient;

    @Autowired
    public RedisLockService(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public void lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        // 执行业务逻辑...
        lock.unlock();
    }
}

在上面的RedisLockService类中,我们使用RedissonClient来获取一个Redis分布式锁(RLock),并且提供了lock方法来获取和释放锁。

注意,lock()方法应该在try-finally块中使用以确保锁在出现异常时仍然能被释放,或者在try-with-resources语句中使用RLock以自动管理锁的释放。这里为了简单起见省略了这些处理。

以上就是在Spring Boot中使用Redisson的基本步骤。根据实际需求,你可以使用Redisson提供的更多分布式对象和服务,如分布式集合、映射、发布订阅等。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值