中间件: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) {  
        // 查询数据库等操作  
    }  
      
    // 其他方法...  
}
相关推荐
狂放不羁霸4 分钟前
idea | 搭建 SpringBoot 项目之配置 Maven
spring boot·maven·intellij-idea
newxtc5 分钟前
【国内中间件厂商排名及四大中间件对比分析】
安全·web安全·网络安全·中间件·行为验证·国产中间件
Wlq04158 分钟前
middleware中间件概述
中间件
Thuni_soft9 分钟前
华宇TAS应用中间件入围鲲鹏应用创新大赛2024全国总决赛
中间件
计算机学长felix32 分钟前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
码农派大星。44 分钟前
Spring Boot 配置文件
java·spring boot·后端
王佑辉1 小时前
【redis】redis缓存和数据库保证一致性的方案
redis·面试
江深竹静,一苇以航1 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
Karoku0661 小时前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
豪宇刘2 小时前
SpringBoot+Shiro权限管理
java·spring boot·spring