SpringBoot集成Redis

SpringBoot集成Redis需要的配置

RedisTemplate

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.atguigu.redis7</groupId>
   <artifactId>redis7_study</artifactId>
   <version>1.0-SNAPSHOT</version>

   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.6.10</version>
       <relativePath/>
   </parent>

   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
       <junit.version>4.12</junit.version>
       <log4j.version>1.2.17</log4j.version>
       <lombok.version>1.16.18</lombok.version>
   </properties>


   <dependencies>
       <!--SpringBoot通用依赖模块-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <!--jedis-->
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>4.3.1</version>
       </dependency>
       <!--lettuce-->
       <dependency>
           <groupId>io.lettuce</groupId>
           <artifactId>lettuce-core</artifactId>
           <version>6.2.1.RELEASE</version>
       </dependency>
       <!--SpringBoot与Redis整合依赖-->
       <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>
       <!--swagger2-->
       <dependency>
           <groupId>io.springfox</groupId>
           <artifactId>springfox-swagger2</artifactId>
           <version>2.9.2</version>
       </dependency>
       <dependency>
           <groupId>io.springfox</groupId>
           <artifactId>springfox-swagger-ui</artifactId>
           <version>2.9.2</version>
       </dependency>
       <!--通用基础配置junit/devtools/test/log4j/lombok/hutool-->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>${junit.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>${log4j.version}</version>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>${lombok.version}</version>
           <optional>true</optional>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

</project>

 

server.port=7777

spring.application.name=redis7_study
 
# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n

logging.file.name=D:/mylogs2023/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
 
# ========================swagger=====================
spring.swagger2.enabled=true
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常,
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser,
#导致出错,解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
 
# ========================redis集群=====================
spring.redis.database=0
spring.redis.host=192.168.101.100
spring.redis.port=6379
spring.redis.password=111111
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
# 获取失败 最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.cluster.nodes=192.168.101.100:6381,192.168.101.100:6382,192.168.101.101:6383,192.168.101.101:6384,192.168.101.132:6385,192.168.101.132:6386
# 以下两个配置是为了解决Redis集群中其中一个master宕机导致Java程序无法正常使用Redis的情况
#支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭
spring.redis.lettuce.cluster.refresh.adaptive=true
#定时刷新
spring.redis.lettuce.cluster.refresh.period=2000

微服务访问Redis集群有个坑:

【案例】Redis Cluster集群部署采用了3主3从拓扑结构,数据读写访问master节点, slave节点负责备份。当master宕机主从切换成功,redis手动OK,but 2个经典故障。

启动Redis集群6台实例,通过微服务访问Redis集群,一切OK!

当集群中其中一台master机器意外宕机。

Redis cluster集群能自动感知并自动完成主备切换,对应的slave会被选举为新的master节点。

故障现象:但SpringBoot客户端没有动态感知到Rediscluster的最新集群信息

image-20231218215954966

image-20231218220005490

导致原因:SpringBoot2.X版本,Redis默认的连接池采用Lettuce,当Redis集群节点发生变化后,lettuce默认是不会刷新节点拓扑的。

解决方案https://github.com/lettuce-io/lettuce-core/wiki/Redis-Cluster#user-content-refreshing-the-cluster-topology-view

  1. 排除lettuce采用jedis(不推荐)

  2. 重写连接工厂实例(极度不推荐)

  3. 刷新节点集群拓扑动态感应

    image-20231218220539962

    image-20231218220550933

     

package com.example.redistemplate.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
* ClassName: RedisConfig
*
* @Author cyh
* @Create 2023/12/17 22:54
*/
@Configuration
public class RedisConfig
{
   /**
    * redis序列化的工具配置类,下面这个请一定开启配置
    * 127.0.0.1:6379> keys *
    * 1) "ord:102" 序列化过
    * 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过
    * this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
    * this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
    * this.redisTemplate.opsForSet(); //提供了操作set的所有方法
    * this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
    * this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
    */
   @Bean
   public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
       RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();

       redisTemplate.setConnectionFactory(lettuceConnectionFactory);
       //设置key序列化方式string
       redisTemplate.setKeySerializer(new StringRedisSerializer());
       //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
       redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

       redisTemplate.setHashKeySerializer(new StringRedisSerializer());
       redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

       redisTemplate.afterPropertiesSet();

       return redisTemplate;
  }
}

 

 

Jedis

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.atguigu.redis7</groupId>
   <artifactId>redis7_study</artifactId>
   <version>1.0-SNAPSHOT</version>

   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.6.10</version>
       <relativePath/>
   </parent>

   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
       <junit.version>4.12</junit.version>
       <log4j.version>1.2.17</log4j.version>
       <lombok.version>1.16.18</lombok.version>
   </properties>

   <dependencies>
       <!--SpringBoot通用依赖模块-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <!--jedis-->
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>4.3.1</version>
       </dependency>
       <!--通用基础配置-->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>${junit.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>${log4j.version}</version>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>${lombok.version}</version>
           <optional>true</optional>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

</project>

 

package com.example.jedisclient.demo;

import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
* ClassName: JedisClientDemo
*
* @Author cyh
* @Create 2023/12/17 19:24
*/
public class JedisClientDemo {
   public static void main(String[] args) {
       Jedis jedis = new Jedis("192.168.101.100", 6379);
       jedis.auth("111111");

       System.out.println("===========key============");
       Set<String> keys = jedis.keys("*");
       for (String key : keys) {
           System.out.println(key);
      }

       System.out.println("===========String============");

       System.out.println(jedis.set("k1", "jedis111"));
       System.out.println(jedis.get("k1"));
       System.out.println("jedis.exists=====>" + jedis.exists("k4"));
       System.out.println(jedis.ttl("k1"));
       System.out.println(jedis.mset("str1","v1","str2","v2","str3","v3"));
       System.out.println(jedis.mget("str1","str2","str3"));

       System.out.println("===========list============");

       jedis.lpush("mylist","1","2","3","4","5");
       List<String> mylist = jedis.lrange("mylist", 0, -1);
       for (String s : mylist) {
           System.out.println(s);
      }

       System.out.println("===========set============");

       jedis.sadd("myset","1","1","2","2","3","4");
       jedis.sadd("myset","5");
       System.out.println(jedis.smembers("myset"));
       jedis.srem("myset","4");
       System.out.println(jedis.smembers("myset"));

       System.out.println("===========hash============");

       jedis.hset("myhash","username","lisi");
       System.out.println(jedis.hget("myhash","username"));
       HashMap<String, String> map = new HashMap<>();
       map.put("phone","13800138000");
       map.put("address","ShangHai");
       map.put("email","123@163.com");
       jedis.hmset("myhashinfo",map);
       List<String> myhashinfo = jedis.hmget("myhashinfo", "phone", "email");
       for (String s : myhashinfo) {
           System.out.println(s);
      }

       System.out.println("===========zset============");
       jedis.zadd("myzset",60,"v1");
       jedis.zadd("myzset",70,"v2");
       jedis.zadd("myzset",80,"v3");
       jedis.zadd("myzset",90,"v4");
       jedis.zadd("myzset",10,"v5");


       Set<String> myzset = jedis.zrange("myzset", 0, -1);
       myzset.forEach(System.out::println);
  }
}
server:
port: 6379
spring:
application:
  name: redis7_study

 

Lettuce

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.atguigu.redis7</groupId>
   <artifactId>redis7_study</artifactId>
   <version>1.0-SNAPSHOT</version>

   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.6.10</version>
       <relativePath/>
   </parent>

   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
       <junit.version>4.12</junit.version>
       <log4j.version>1.2.17</log4j.version>
       <lombok.version>1.16.18</lombok.version>
   </properties>

   <dependencies>
       <!--SpringBoot通用依赖模块-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <!--jedis-->
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>4.3.1</version>
       </dependency>
       <!--lettuce-->
       <dependency>
           <groupId>io.lettuce</groupId>
           <artifactId>lettuce-core</artifactId>
           <version>6.2.1.RELEASE</version>
       </dependency>
       <!--通用基础配置-->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>${junit.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>${log4j.version}</version>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>${lombok.version}</version>
           <optional>true</optional>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

</project>

 

package com.example.lettuceclient.demo;

import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* ClassName: lettuceDemo
*
* @Author cyh
* @Create 2023/12/17 20:34
*/
public class lettuceDemo {
   public static void main(String[] args) {
       // 使用构建器 RedisURI.builder()
       RedisURI uri = RedisURI.builder()
              .redis("192.168.101.100")
              .withPort(6379)
              .withAuthentication("default", "111111")
              .build();
       // 创建连接客户端
       RedisClient redisClient = RedisClient.create(uri);
       StatefulRedisConnection<String, String> connect = redisClient.connect();
       // 操作命令api
       RedisCommands<String, String> commands = connect.sync();


       System.out.println("===========key============");

       List<String> keys = commands.keys("*");
       for (String key : keys) {
           System.out.println(key);
      }


       System.out.println("commands.exists=====>" + commands.exists("k5"));
       System.out.println(commands.ttl("k1"));

       System.out.println("===========String============");

       System.out.println(commands.set("k1", "commands111"));
       System.out.println(commands.get("k1"));
       HashMap<String, String> map0 = new HashMap<>();
       map0.put("str11","v11");
       map0.put("str22","v22");
       map0.put("str33","v33");
       System.out.println(commands.mget("str1q","strw2","str33"));

       System.out.println("===========list============");

       commands.lpush("mylist","1","2","3","4","5");
       List<String> mylist = commands.lrange("mylist", 0, -1);
       for (String s : mylist) {
           System.out.println(s);
      }

       System.out.println("===========set============");

       commands.sadd("myset","1","1","2","2","3","4");
       commands.sadd("myset","5");
       System.out.println(commands.smembers("myset"));
       commands.srem("myset","4");
       System.out.println(commands.smembers("myset"));

       System.out.println("===========hash============");

       commands.hset("myhash","username","wangwu");
       System.out.println(commands.hget("myhash","username"));
       HashMap<String, String> map = new HashMap<>();
       map.put("phone","13800138000");
       map.put("address","Beijin");
       map.put("email","321@163.com");
       commands.hmset("myhashinfo",map);
       Map<String, String> myhashinfo = commands.hgetall("myhashinfo");
       for (String s : myhashinfo.keySet()) {
           System.out.println("hash k= "+ s + ", v= "+ myhashinfo.get(s));
      }

       System.out.println("===========zset============");
       commands.zadd("myzset",60.0,"v1",70.0,"v2",80.0,"v3",90.0,"v4",10.0,"v5");
       List<String> myzset = commands.zrange("myzset", 0, -1);
       myzset.forEach(System.out::println);

       // 关闭
       connect.close();
       redisClient.shutdown();
  }
}
 
posted @ 2023-12-18 22:09  小陈_winwah  阅读(21)  评论(0编辑  收藏  举报