【redis知识点整理】 --- springboot2.X使用lettuce连接池集成redis

本文代码对应的github地址:https://github.com/nieandsun/redis-study

不出意外的话,很多公司操作redis应该还是使用的jedis。


当然应该也有公司比较能耐,直接把操作redis的所有方法进一步封装成API或Utils类,然后打成jar包,做成服务供多个部门使用 —》 然后开发者就不必关心真正与redis交互的细节了。— 其实我们公司就是这种姿势!!!
不知道其他公司到底是怎么个套路,我觉得这种方式对公司挺好,但是对于我们开发者自身来说,可能就缺少了直面问题 + 解决问题的机会。


其实说实话,我们组也在做一些基础性的服务,从这个角度来讲,貌似每个部门(或许更应该说是每一个coder吧)都希望自己可以直面问题,直面挑战,然后让别人使用自己提供的服务!!!
不知道是不是每个人都是这么想的,但至少我感觉貌似我身边的好些人都表现出了这种姿态!!!



1 jedis和lettuce简单比较

  • Jedis在实现上是直接连接Redis服务器,在多个线程间共享一个Jedis 实例时是线程不安全的,如果想要在多线程场景下使用Jedis,需要使用连接池,每个线程都使用自己的Jedis实例,当连接数量增多时,会消耗较多的物理资源。

  • 与Jedis相比,lettuce 则完全克服了其线程不安全的缺点:lettuce 是一个可伸缩的线程安全的 Redis客户端,支持同步、异步和响应式模式。多个线程可以共享一个连接实例, 而不必担心多线程并发问题。它基于优秀Netty NIO框架构建,支持Redis的更多高级功能。


2 springboot集成redis


2.1 添加依赖

maven依赖:

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

 <!-- lettuce连接池需要依赖下面的jar包 -->
 <dependency>
     <groupId>org.apache.commons</groupId>
     <artifactId>commons-pool2</artifactId>
 </dependency>

2.2 数据源配置

spring:
  redis:
    database: 0 #使用第几个数据库
    host: 192.168.65.135 #redis服务器地址
    port: 6379 #端口号
    password: 123456 #redis服务器连接密码
    timeout: 10000ms  # 连接超时时间(毫秒)
    lettuce:
      pool:
        ##下面的值其实是lettuce连接池的默认配置,有兴趣的可以点进源码看一下
        max-active: 8 #连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms  #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 8 #连接池中的最大空闲连接
        min-idle: 0 #连接池中的最小空闲连接

2.3 配置类

实际上完成2.2就可以了,但是由于springboot默认提供的redis操作模版类 —RedisTemplate实际上为<Object,Object>类型,但是相信大家都知道,我们平常使用redis,key都会使用一个相对简单的字符串,因此我们需要自己配置一个RedisTemplate,具体原理可以看一下下面的文章,这里我不过多叙述 —》但是那篇文章数据源那一块是有问题的

https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html#!comments

扫描二维码关注公众号,回复: 11282945 查看本文章
@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        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);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

3 简单测试

测试程序如下:

package com.nrsc.redis.learning.simple;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class RedisSimpleDemo {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    public void test1() {
        redisTemplate.multi();
        redisTemplate.opsForValue().set("k1", "Hello Redis1....");
        int i = 100 / 0;
        redisTemplate.opsForValue().set("k2", "Hello Redis2....");
        redisTemplate.exec();
    }


    @Test
    public void test2() {
        stringRedisTemplate.multi();
        stringRedisTemplate.opsForValue().set("k1", "Hello Redis1....");
        int i = 100 / 0;
        stringRedisTemplate.opsForValue().set("k2", "Hello Redis2....");
        stringRedisTemplate.exec();
    }
}

可以得到的结论:
(1)test1方法运行之后,数据库里什么值都插入不进去,但test2运行后可以插入k1对应的值 —》 说明:

  • 我们配置的事务生效了。
  • 当然如果想让StringRedisTemplate可以开启事务,我们可以按照RedisTemplate一样配置一个我们自己的StringRedisTemplate

(2)无论是RedisTemplate还是StringRedisTemplate,都使用了我们配置的连接池信息,有兴趣的可以通过打断点的方式看一下RedisTemplate或StringRedisTemplate实例中的connectionFactory,举例如下:
在这里插入图片描述


end !

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/106363601