1 jedis的简单介绍

1.1 Jedis是什么

    直观来说,jedis就是redis-cli    

1.2 引入jedis的依赖包

     <!-- 引入jedis的依赖包 -->
    <dependency>  
      <groupId>redis.clients</groupId>  
      <artifactId>jedis</artifactId>  
      <version>2.9.3</version>  
      <type>jar</type>  
      <scope>compile</scope>  
    </dependency>   

1.3 jedis直连

  1. 生成一个Jedis对象,这个对象负责和指定Redis节点进行通信
    Jedis jedis = new Jedis(“127.0.0.1”,6379);

  2. jedis执行set操作
    jedis.set(“hello”,“world”);

  3. jedis执行get操作,value=“world”
    String value = jedis.get(“hello”);

Jedis构造函数的简单介绍

    Jedis构造方法的参数  
    Jedis(String host,int port,int connectionTimeout,int soTimeout);  
    host:Redis节点的所在机器的IP;  
    port:Redis节点的端口;  
    connectionTimeout:客户端连接超时;  
    soTimeout:客户端读写超时;    

1.4 Jedis直连和连接池的对比


2 redis的具体实现

2.1 慢查询

  • 生命周期
  • 三个命令
  • 两个配置
  • 运维经验

2.1.1 生命周期

    两点说明:  
    (1)慢查询发生在第三阶段  
    (2)客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素

2.1.2 慢查询的两个配置

1. slowlog-log-slower-than

    1. 慢查询阈值(单位:微秒)  
    2. slowlog-log-slower-than=0:记录所有命令    
    3. slowlog-log-slower-than<0:不记录任何命令

2. slowlog-max-len

    1. 先进先出  
    2. 固定长度  
    3. 保存在内存中    

2.1.3 配置方法

1. 默认值

  • config get slowlog-max-len = 128
  • config get slowlog-log-slower-than = 10000(阈值)

2. 修改配置文件重启

3. 动态配置

  • config set slowlog-max-len 1000
  • config set slowlog-log-slower-than 1000

2.1.4 慢查询的命令

1. slowlog get[n]:获取慢查询队列

2. slowlog len:获取慢查询队列长度

3. slowlog reset:清空慢查询队列

2.1.5 慢查询的运维经验

  1. slowlog-max-len不要设置过大,默认10ms,通常设置1ms。
  2. slowlog-log-slower-than不要设置过小,通常设置1000左右。
  3. 理解命令生命周期。
  4. 定期持久化慢查询。



3 SpringBoot整合Redis项目实战

3.1 创建分布式项目

  • 项目结构图如下


3.1.1 parent导入的依赖

    <dependencies>

    <!-- 配置web启动器-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 配置mybatis-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.15</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.2.0</version>
    </dependency>

    <!-- 配置数据库连接池 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <exclusions> <!--不依赖Redis的异步客户端lettuce-->
            <exclusion>
                <groupId>io.lettuce</groupId>
                <artifactId>lettuce-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--引入Redis的客户端驱动jedis-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>


    注意:parent的项目打包方式是pom,其他项目依赖于该项目  

3.1.2 创建springboot的配置文件application.properties

创建该文件需要注意一下几点
* 关于springMVC、redis的配置文件必须根据全称去写如spring.mvc.view.suffix=.jsp不得随意更改=左边的值
* 该文件必须存放于classpath下也就是resources根目录下
* 命名为application.properties

文件内容如下

                    # 配置视图解析
                    spring.mvc.view.prefix=/WEB-INF/views/
                    spring.mvc.view.suffix=.jsp

                    # 配置数据库连接参数
                    spring.datasource.driverClassName =com.mysql.cj.jdbc.Driver
                    spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
                    spring.datasource.username=root
                    spring.datasource.password=123456
                    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
                    # 指定mapper文件的位置
                    mybatis.mapper-locations=classpath:mapper/*.xml

                    # 配置Jedis
                    #redis jedis配置
                    # Redis数据库索引(默认为0)
                    spring.redis.database=0
                    # Redis服务器地址
                    spring.redis.host=127.0.0.1
                    # Redis服务器连接端口
                    spring.redis.port=6379
                    # Redis服务器连接密码(默认为空)
                    #spring.redis.password=
                    # 连接池最大连接数(使用负值表示没有限制)
                    spring.redis.jedis.pool.max-active=5000
                    # 连接池最大阻塞等待时间(使用负值表示没有限制)
                    spring.redis.jedis.pool.max-wait=-1
                    # 连接池中的最大空闲连接
                    spring.redis.jedis.pool.max-idle=8
                    # 连接池中的最小空闲连接
                    spring.redis.jedis.pool.min-idle=0
                    # 连接超时时间(毫秒)
                    spring.redis.timeout=1000
                    #spring-session 使用
                    spring.session.store-type=none

                    # 定义存放图片的key
                    redis.key=bigImg

                    # 配置静态资源放行
                    spring.resources.static-locations=classpath*:/static/    

3.2 创建Redis的连接类RedisConfig.java

在创建该类时需要了解以下几点
1. @EnableCaching的作用:开启缓存注解; 2. Cacheable作用:把方法的返回值添加到Ehcache中做缓存Value属性:指定一个Ehcache配置文件中的缓存策略,如果么有给定value,name则表示使用默认的缓存策略。
3. @CacheEvict作用:清除缓存
4. @Configuration:具体作用请看博客:@Configuration详解

  1. 在SpringBoot2.x之后的版本中官网推荐使用的是lettuce连接池整合Redis,并且删除了一些整合Jedis的方法,因此这里使用Jedis整合Redis时需要重写这些方法,如CacheManager cacheManager(RedisConnectionFactory connectionFactory)方法。

3.2.1 创建该类的内容如下

            /**
             * @author fyzn12
             * @version 1.0
             * @date 2020/7/10 9:35
             * @description:TODO
             */
            @Configuration
            @EnableCaching
            public class RedisConfig {

                @Bean
                    //如使用注解的话需要配置cacheManager
                    //此处为与1.x最大的不同
                CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
                    //初始化一个RedisCacheWriter
                    RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
                    RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
                    //设置默认超过期时间是1天
                    defaultCacheConfig.entryTtl(Duration.ofDays(1));
                    //初始化RedisCacheManager
                    RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
                    return cacheManager;
                }

                // 以下两种redisTemplate自由根据场景选择
                @Bean
                public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
                    RedisTemplate<Object, Object> template = new RedisTemplate<>();
                    template.setConnectionFactory(connectionFactory);

                    //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
                    Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

                    ObjectMapper mapper = new ObjectMapper();
                    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
                    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
                    serializer.setObjectMapper(mapper);

                    template.setValueSerializer(serializer);
                    //使用StringRedisSerializer来序列化和反序列化redis的key值
                    template.setKeySerializer(new StringRedisSerializer());
                    template.afterPropertiesSet();
                    return template;
                }

                @Bean
                public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
                    StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
                    stringRedisTemplate.setConnectionFactory(factory);
                    return stringRedisTemplate;
                }
            }   

3.2.2 创建测试类

        /**
         * @author fyzn12
         * @version 1.0
         * @date 2020/7/10 12:25
         * @description:TODO
         */


        @RunWith(SpringRunner.class)
        @SpringBootTest
        public class RedisTest {

            Logger log = LoggerFactory.getLogger(RedisTest.class);
            @Autowired
            RedisTemplate redisTemplate;
            @Test
            public void contextLoads() {
                //这里相当于redis对String类型的set操作
                redisTemplate.opsForValue().set("test","helloworld");
                //这里相当于redis对String类型的get操作
                String test = (String)redisTemplate.opsForValue().get("test");
                System.out.println(test);
            }
        }  

3.3 项目运行过程中遇到的bug总结

3.3.1 springboot创建分布式项目时,前端访问页面显示下图

分析上图中的error如下讨论

  • 产生404错误的原因有
    1. 配置的视图解析没有工作;但在该图中,很明显视图解析到了/WEB-INF/views/下,说明视图解析已经成功。
    2. 文件的访问路径与控制器的路径不匹配(在上图中也可以排除)
    3. springboot的启动器没有包含controller,或者与controller处于同级目录;

  • 以上几种原因在该项目中很明显都不是。

产生这个原因是因为分布式项目在解析控制器路径时产生的问题,具体原因我也尚未弄清楚,但目前知道有两种方式可以解决

方法一:
  • 1. 找到项目右侧的 Maven,如图所示

  • 2. 点检Maven之后展开项目,在Plugins下会找到一个spring-boot,将其展开,选择下面的spring-boot:run启动项目

方法二:

改变springboot的启动器的配置
1. 选择Edit Configurations 找到Environment,如下图所示

  1. 展开Environment之后,选择下面的Working directory,并在其右侧输入: $MODULE_WORKING_DIR$
  2. 保存点击ok,再次启动项目,访问即可成功