中间件:SpringBoot集成Redis

一.Redis简介

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

1.Redis的基本特点

  1. 高性能:Redis将数据存储在内存中,因此具有极高的读写速度,每秒可以处理超过10万次读写操作。这使得Redis非常适合用于缓存场景。
  2. 原子性:Redis的所有操作都是原子性的,这保证了数据的一致性。
  3. 支持多种数据类型:Redis不仅支持简单的key-value类型数据,还支持字符串、哈希、列表、集合和有序集合等多种数据结构,这使得Redis可以灵活地应用于各种场景。
  4. 持久化:Redis支持RDB和AOF两种持久化方式,可以将内存中的数据保存到磁盘上,以确保数据的可靠性和安全性。
  5. 复制和集群:Redis支持主从复制和集群模式,可以实现数据的备份、读写分离和水平扩展。

2.Redis的数据类型

  1. 字符串(String):Redis最基本的数据类型,可以存储任何类型的字符串,包括二进制数据。
  2. 哈希(Hash):Redis的Hash是一个键值对的集合,其中的每个键值对都是一个字符串类型的field和value。Hash特别适合存储对象。
  3. 列表(List):Redis的List是一个字符串列表,按照插入顺序排序。它支持从列表两端进行push和pop操作。
  4. 集合(Set):Redis的Set是一个无序的字符串集合,具有唯一性。它支持集合间的交集、并集和差集等操作。
  5. 有序集合(Sorted Set):Redis的Sorted Set是一个有序且不重复的字符串集合。每个元素都会关联一个double类型的分数(score),Redis正是通过分数来为集合中的成员进行从小到大的排序。

3.Redis的应用场景

  1. 缓存:Redis最常用的场景之一,它可以作为数据库的前置缓存,减少数据库的访问压力,提高应用的响应速度。
  2. 分布式锁:Redis具有原子性操作,可以利用其特性实现分布式锁,以保证在分布式环境下的数据一致性。
  3. 消息队列:Redis的List类型可以模拟消息队列,实现生产者-消费者模式。
  4. 计数器:Redis的原子性操作使得它可以作为计数器,用于统计网站的访问量、点赞数等。
  5. 社交网络:Redis可以用于存储用户的关注关系、粉丝列表等社交数据。

4.Redis的安装与配置

Redis的安装相对简单,可以从Redis官网下载相应的安装包或源码进行安装。安装完成后,需要配置redis.conf文件以满足特定的需求,如设置内存限制、连接数限制、持久化策略等。

5.Redis的维护与监控

为了确保Redis的稳定运行,需要定期对其进行维护和监控。可以使用Redis自带的监控工具,如Redis Monitor,也可以使用第三方监控工具,如Redis Insight。这些工具可以帮助我们实时监控Redis的运行状态和数据变化,以便及时发现并解决问题。

二.Redis基本使用

Redis是一款开源的、基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等,并提供了丰富的命令来操作这些数据。以下是Redis的基本使用方法:

安装Redis

Redis支持多种操作系统,包括Linux、Windows等。安装Redis的方法因操作系统而异。

Linux系统
  1. 从Redis官网下载相应的安装包,或使用包管理器(如apt-get、yum等)安装。
  2. 解压安装包,并按照系统要求进行编译和安装。
  3. 配置Redis(可选),修改redis.conf文件以满足特定需求。
  4. 启动Redis服务,通常是通过运行redis-server命令并指定配置文件路径。
Windows系统
  1. 从Redis官网下载Windows版本的安装包。
  2. 双击安装包进行安装,按照提示完成安装过程。
  3. 启动Redis服务,可以通过双击redis-server.exe文件或使用命令行启动。

连接Redis

使用redis-cli命令连接到Redis服务器。在命令行中输入redis-cli,然后回车。如果Redis服务器设置了密码,连接时可以使用-a参数指定密码,如redis-cli -a yourpassword。

基本数据类型操作

Redis支持多种数据类型,每种数据类型都有相应的操作命令。

字符串(String)
  • 设置键值对SET key value
  • 获取指定键的值GET key
  • 删除键DEL key
列表(List)
  • 从列表左边插入元素LPUSH key value [value ...]
  • 从列表右边插入元素RPUSH key value [value ...]
  • 获取列表中的元素LRANGE key start stop
集合(Set)
  • 添加元素到集合SADD key member [member ...]
  • 移除集合中的元素SREM key member [member ...]
  • 获取集合中的所有元素SMEMBERS key
有序集合(Sorted Set)
  • 添加元素到有序集合ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
  • 移除有序集合中的元素ZREM key member [member ...]
  • 获取有序集合中的元素ZRANGE key start stop [WITHSCORES]
哈希(Hash)
  • 在哈希表中设置字段的值HSET key field value
  • 获取哈希表中字段的值HGET key field
  • 移除哈希表中一个或多个字段HDEL key field [field ...]

其他常用操作

  • 查看所有键KEYS pattern(注意:在生产环境中慎用,因为它会阻塞服务器)
  • 删除一个或多个键DEL key [key ...]
  • 切换数据库SELECT index(Redis默认有16个数据库,索引从0开始)
  • 清空当前数据库FLUSHDB
  • 清空所有数据库FLUSHALL

配置和性能调优

Redis的性能和稳定性很大程度上取决于其配置。通过调整配置文件(redis.conf)中的参数,如内存限制、连接数限制、持久化策略等,可以优化Redis的性能。此外,还可以利用Redis提供的监控工具(如Redis Monitor、Redis Insight等)来实时监控Redis的运行状态和数据变化,以便及时发现并解决问题

持久化

Redis提供了两种持久化方式:RDB(快照)和AOF(追加文件)。快照方式通过定期创建数据库快照文件来保存数据,而日志方式则将每个写操作追加到日志文件中,以便恢复数据。根据实际需求选择合适的持久化方式,以确保数据的安全性和可靠性。

主从复制和集群

Redis支持主从复制模式,可以实现数据备份和读写分离。主节点负责写入数据,从节点负责读取数据。此外,Redis还支持集群模式,可以将数据分散到多个Redis节点上,以提高系统的整体性能和容错能力。

综上所述,Redis的基本使用包括安装、连接、数据类型操作、其他常用操作、配置和性能调优、持久化以及主从复制和集群等方面。通过掌握这些基本使用方法,可以更好地利用Redis来存储和访问数据。

三.Jedis操作Redis

Jedis 是 Java 实现的 Redis 客户端,提供了丰富的接口来操作 Redis 数据库。使用 Jedis,你可以在 Java 应用中方便地连接到 Redis 服务器,执行各种 Redis 命令,并处理返回的数据。

以下是如何使用 Jedis 来操作 Redis 的一些基本步骤:

添加 Jedis 依赖

首先,你需要在你的 Java 项目中添加 Jedis 的依赖。如果你使用 Maven,可以在 pom.xml 文件中添加如下依赖:

XML 复制代码
<dependency>  
    <groupId>redis.clients</groupId>  
    <artifactId>jedis</artifactId>  
    <version>最新版本</version>  
</dependency>

编写junit单元测试JedisTester:

java 复制代码
public class JedisTester {
   private Jedis jedis;
   @Before
   public void setup(){
        //连接redis服务器,127.0.0.1:6379
        jedis = new Jedis("127.0.0.1",6379);
        //权限认证,指定密码
        jedis.auth("123456");
    }
}

操作字符串:

java 复制代码
@Test
    public void testString(){
        //添加数据
        jedis.set("name","ktjiaoyu");
        System.out.println(jedis.get("name"));

        jedis.append("name","czkt");//拼接
        System.out.println(jedis.get("name"));

        jedis.del("name");//删除某个键
        System.out.println(jedis.get("name"));
        //设置多个键值对
        jedis.mset("name","ktjiaoyu","age","17","add","cz");
        jedis.incr("age");//对某个键值对进行加一操作

        System.out.println(jedis.get("name")+"-"+jedis.get("age")+"-"+jedis.get("add"));

    }

连接池

在我们实际使用过程中,不会在每次使用时创建Jedis对象,一般会使用连接池,并提供一个工具类来对外使用。

使用连接池的好处:1. 效率更高;2.线程安全。

连接池:

复制代码
public final class RedisPool {
    //Redis服务器IP
    private static String ADDR = "192.168.0.100";
    //Redis的端口号
    private static int PORT = 6379;
    //访问密码
    private static String AUTH = "123456";
    //可用连接实例的最大数目,默认值为8;
    //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
    private static int MAX_ACTIVE = 1024;
    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
    private static int MAX_IDLE = 200;
    //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
    private static int MAX_WAIT = 10000;
    private static int TIMEOUT = 10000;
    //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
    private static boolean TEST_ON_BORROW = true;
    private static JedisPool jedisPool=null;

    /**
     * 初始化Redis连接池
     */
    static {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(MAX_ACTIVE);
            config.setMaxIdle(MAX_IDLE);
            config.setMaxWaitMillis(MAX_WAIT);
            config.setTestOnBorrow(TEST_ON_BORROW);
            jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取Jedis实例
     * @return
     */
    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 释放jedis资源
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }
}

工具类:

java 复制代码
public class RedisUtil {
    /**
     * 设置key的有效期,单位是秒
     * @param key
     * @param exTime
     * @return
     */
    public static Long expire(String key, long exTime) {
        Jedis jedis=null;
        Long result = null;
        try {
            jedis= RedisPool.getJedis();
            result = jedis.expire(key, exTime);
        }catch (Exception e){
            e.printStackTrace();
            return result;
        }finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }

    public static String estEx(String key, long exTime, String value) {
        Jedis jedis=null;
        String result = null;
        try {
            jedis= RedisPool.getJedis();
            result = jedis.setex(key, exTime, value);
        }catch (Exception e){
            e.printStackTrace();
            return result;
        }finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }

    public static String set(String key,String value) {
        Jedis jedis=null;
        String result = null;
        try {
            jedis= RedisPool.getJedis();
            result = jedis.set(key, value);
        }catch (Exception e){
            e.printStackTrace();
            return result;
        }finally {
            RedisPool.returnResource(jedis);

        return result;
        }
    }
    public static String get(String key) {
        Jedis jedis=null;
        String result = null;
        try {
            jedis = RedisPool.getJedis();
            result = jedis.get(key);
        }catch (Exception e){
            e.printStackTrace();
            return result;
        }finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }
    public static Long del(String key) {
        Jedis jedis=null;
        Long result = null;
        try {
            jedis = RedisPool.getJedis();
            result = jedis.del(key);
        }catch (Exception e){
            e.printStackTrace();
            return result;
        }finally {
            RedisPool.returnResource(jedis);
        }
        return result;
    }
}

SpringBoot操作Redis

Spring Boot 集成 Redis 是一种常见的方式,用于在应用程序中存储和检索数据,特别是在需要快速访问和更新数据的情况下。Redis 是一个开源的、内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Spring Boot 通过 spring-boot-starter-data-redis 提供了对 Redis 的支持。

1. 添加依赖

首先,你需要在你的 Spring Boot 项目的 pom.xml(如果你使用的是 Maven)中添加 Redis 的起步依赖:

XML 复制代码
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>

2. application.properties配置相关信息

java 复制代码
spring.redis.dtabase=0
spring.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=123456
spring.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

3.测试使用

在单元测试中,注入 StringRedisTemplate和RedisTemplate
java 复制代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTemplateTester {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedisTemplate redisTemplate;
}
StringRedisTemplate和RedisTemplate区别
1. 使用范围与数据类型
  • StringRedisTemplate :专门用于操作Redis中的String类型数据,提供了一系列简化操作String类型数据的方法。其泛型参数固定为<String, String>,表示键和值都是字符串类型的数据。
  • RedisTemplate:是一个泛型类,通过指定泛型参数可以支持Redis中的多种数据类型操作(如字符串、列表、集合、有序集合、散列等)。它提供了对Redis常见数据类型的操作方法,并且支持批量插入和删除,可以一次性执行多个命令。
2. 序列化策略
  • StringRedisTemplate :在序列化和反序列化数据时,使用StringRedisSerializer,这意味着在存储字符串类型数据时,可以直接将Java字符串类型转换为Redis字符串类型,效率较高。
  • RedisTemplate :默认使用JdkSerializationRedisSerializer进行序列化和反序列化,这种方式会将Java对象序列化成字节数组存储在Redis中。虽然这种方式支持所有Java对象的序列化,但在Redis中查看时可能显示为乱码。不过,RedisTemplate的序列化策略可以根据需要进行自定义,例如使用Jackson2JsonRedisSerializer将对象序列化为JSON字符串,这样在Redis中查看时会更友好
3. 特殊方法
  • StringRedisTemplate :提供了一些专门用于操作字符串类型数据的特殊方法,如append(追加字符串)、getBit(获取字符串指定位置的位)、decrement(递减指定键的值)等。
  • RedisTemplate:虽然也支持对字符串类型数据的操作,但相对于StringRedisTemplate来说,它更侧重于提供对多种Redis数据类型的通用操作方法。
4. 依赖与集成
  • 两者都是Spring Data Redis提供的工具类,可以与Spring Boot应用程序无缝集成,通过依赖注入的方式进行使用。

四.SpringBoot集成Redis使用Cache缓存

RedisConfig配置

在config包下新建RedisConfig配置类:

java 复制代码
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public KeyGenerator keyGenerator(){
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params)
                    sb.append(obj.toString());

                return sb.toString();
            }
        };

        }
        @Bean
    public RedisTemplate<Object, Object> redisCacheManager(RedisConnectionFactory redisConnectionFactory){
            RedisTemplate<Object,Object>redisTemplate= new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer= new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }

        @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory){
            RedisSerializer<String>redisSerializer=new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper om=new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            // 配置序列化(解决乱码的问题),jackson2JsonRedisSerializer支持泛型
            RedisCacheConfiguration config=RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofDays(7)) // 设置缓存过期时间为1分钟
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                    .disableCachingNullValues();
            RedisCacheManager cacheManager=RedisCacheManager.builder(factory)
                    .cacheDefaults(config)
                    .build();
            return cacheManager;
        }
    }

Cache注解

Cache注解在Spring Boot中主要用于方法级别的缓存控制,通过注解可以方便地将方法的返回结果缓存起来,以提高应用程序的性能。Spring Boot提供了多个与缓存相关的注解,这些注解通常与缓存管理器一起使用,如Redis、Ehcache、Caffeine等。以下是几个常用的Cache注解及其详细解释:

1. @EnableCaching

  • 作用:在Spring Boot的启动类上使用此注解,以开启缓存支持。它告诉Spring Boot应用程序将使用缓存。
java 复制代码
@SpringBootApplication  
@EnableCaching  
public class DemoApplication {  
    public static void main(String[] args) {  
        SpringApplication.run(DemoApplication.class, args);  
    }  
}

2. @Cacheable

  • 作用:用于标记一个方法,其返回值需要被缓存。当方法被调用时,Spring会先检查缓存中是否存在相应的数据,如果存在,则直接返回缓存中的数据,而不需要执行方法体。如果不存在,则执行方法体,并将结果缓存起来。
  • 属性
    • value:指定缓存的名称。
    • key:指定缓存的键,用于唯一标识缓存中的数据。支持Spring EL表达式。
    • condition:指定缓存的条件,只有当条件满足时,才会进行缓存。
java 复制代码
@Cacheable(value="users", key="#id")  
public User getUserById(Long id) {  
    // 查询数据库等操作  
    return user;  
}

3. @CachePut

  • 作用:与@Cacheable类似,但@CachePut每次都会执行方法体,并将结果缓存起来。它通常用于更新操作,确保缓存中的数据始终是最新的。
  • 属性:与@Cacheable类似,也有value、key和condition等属性。
java 复制代码
@CachePut(value="users", key="#user.id")  
public User updateUser(User user) {  
    // 更新数据库等操作  
    return user;  
}

4. @CacheEvict

  • 作用:用于标记一个方法,该方法执行时会触发缓存的清除操作。它通常用于删除操作,以确保缓存中的数据与数据库中的数据保持一致。
  • 属性
    • value:指定要清除的缓存的名称。
    • key:指定要清除的缓存的键。
    • allEntries:是否清除指定缓存中的所有数据。当设置为true时,会忽略key属性。
    • beforeInvocation:是否在方法执行前清除缓存。默认为false,即在方法执行后清除缓存。
java 复制代码
@CacheEvict(value="users", key="#id")  
public void deleteUserById(Long id) {  
    // 删除数据库中的用户等操作  
}  
  
@CacheEvict(value="users", allEntries=true)  
public void deleteAllUsers() {  
    // 删除数据库中的所有用户等操作  
}

5. @CacheConfig

  • 作用:用于配置该类中会用到的一些共用的缓存配置。当类中的多个方法需要相同的缓存配置时,可以使用@CacheConfig来避免重复配置。
  • 属性
    • cacheNames:指定该类中方法默认使用的缓存名称。
java 复制代码
@CacheConfig(cacheNames = "myCache")  
public class MyService {  
      
    @Cacheable  
    public String findById(Long id) {  
        // 查询数据库等操作  
    }  
      
    // 其他方法...  
}
相关推荐
纪元A梦9 小时前
Redis最佳实践——安全与稳定性保障之高可用架构详解
redis·安全·架构
召摇9 小时前
Spring Boot 内置工具类深度指南
java·spring boot
Moshow郑锴11 小时前
SpringBootCodeGenerator使用JSqlParser解析DDL CREATE SQL 语句
spring boot·后端·sql
小沈同学呀17 小时前
创建一个Spring Boot Starter风格的Basic认证SDK
java·spring boot·后端
凤山老林20 小时前
SpringBoot 轻量级一站式日志可视化与JVM监控
jvm·spring boot·后端
无敌的神原秋人20 小时前
关于Redis不同序列化压缩性能的对比
java·redis·缓存
Chan1620 小时前
JVM从入门到实战:从字节码组成、类生命周期到双亲委派及打破双亲委派机制
java·jvm·spring boot·后端·intellij-idea
恣艺1 天前
Redis列表(List):实现队列/栈的利器,底层原理与实战
数据库·redis·list
科兴第一吴彦祖1 天前
在线会议系统是一个基于Vue3 + Spring Boot的现代化在线会议管理平台,集成了视频会议、实时聊天、AI智能助手等多项先进技术。
java·vue.js·人工智能·spring boot·推荐算法