一、常见的几种 Java 客户端

  • Jedis:Redis 命令作为方法的名称,便于学习,简单实用,但其实例是线程不安全的,多线程下需要基于连接池来使用。
  • lettce:基于 Netty 实现,支持同步、异步响应式编程方式,并且线程是安全的,支持 Redis 的多种模式。
  • Redisson:是一个基于 Redis 实现的分布式、可伸缩的 Java 数据结构集合。

        我们在之后会学习 Jedis,以及 Spring Jedis lettce 整合后的 Spring Data Redis


二、Jedis 

        ① 第一步,我们要先导入 Jedis 的对应依赖:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>

       ② 第二步,我们要创建 Jedis 的实例并设置对应参数:

//1.建立连接
jedis = new Jedis("127.0.0.1", 6379);
//2.设置密码
jedis.auth("123456");
//3.选择库
jedis.select(0);

        ③ 注意,在最后需要将连接关闭

//关闭连接
if (jedis != null) {
    jedis.close();
}

        建立连接后,我们就可以根据我们之前在 Redis 中用到的方法名来快速上手,如操作 String 类型的键值对:

        如上操作,直接调用 set get 方法即可。

        还如操作 hash 类型时:

        也是只用调用对应名称的方法即。

● Jedis 连接池

        前面说过,Jedis 是线程不安全的,所以我们需要建立连接池来确保线程的安全性。我们可以通过建立一个工具类来初始化连接池:

public class JedisConnectionFactory {
    //连接池对象
    private static final JedisPool jedisPool;

    static {
        //配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);//最大连接数
        poolConfig.setMaxIdle(8);//最大空闲连接
        poolConfig.setMinIdle(0);//最小空闲连接
        poolConfig.setMaxWaitMillis(1000);//等待时长
        //创建连接池对象
        jedisPool = new JedisPool(poolConfig,
                "127.0.0.1", 6379, 1000, "123456");
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

        此处我们使用静态代码块进行初始化,是因为静态代码块会在类执行时加载,并且只会执行一次,确保了线程安全,同时减少了资源的复用

        之后我们在使用时,只需调用该工具类中的 getJedis( ) 方法即可获取到连接池。

//1.建立连接
jedis = JedisConnectionFactory.getJedis();
//2.设置密码
jedis.auth("123456");
//3.选择库
jedis.select(0);

        其次,在我们最后关闭连接时,其 close( ) 方法底层会进行判断,若是连接池会将连接池进行归还,而并非销毁


三、SpringDataRedis

        SpringData Spring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 额集成模块就是 SpringDataRedis。其封装了各种对 Redis 的操作,并且对不同数据类型的操作封装到了不同的类型。

        ① 第一步,引入依赖。springboot 已默认整合了 SpringDataRedis 。

<!-- 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>

        ② 配置 SpringDataRedis 的配置文件 application.yaml

spring:
  data:
    redis:
      host: 127.0.0.1
      port: 6379
      password: 123456
      jedis:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: 100ms

        其中可以自己选择使用 jedis 或是 lettuce,但因其默认使用 lettuce 所以不用导 lettuce 的依赖,而 jedis 需要手动导入依赖。jedis 的连接池也只在配置后才会生效。

        ③ 注入 RedisTemplate

@Autowired
private RedisTemplate redisTemplate;

        注入后调用其中方法可以看到将不同数据类型的操作进行了分离。

        测试后可以正常输出获取的值,运行成功。

        而其会将数据存为如下格式,这是因为其会将传入的内容作为对象进行序列化处理。

        在底层存在 key、value、hashKey、hashValue 四种类型的序列化器。

        且默认使用 jdk 的序列化器,导致出现了这种可读性差占用空间大的问题。

        所以我们需要改变这种序列化方式,修改 RedisTemplate 即可:

        引入 jackson 的依赖:

<!-- jackson -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

        注册一个配置类并声明一个 Bean 如下进行配置:

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        //1.创建RedisTemplate对象
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        //2.设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //3.创建Java序列化工具
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //4.设置key的序列化器
        redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(genericJackson2JsonRedisSerializer);
        //5.设置value的序列化器
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        //6.返回对象
        return redisTemplate;
    }
}

        将自动注入的 RedisTemplate 加上泛型后即可

       再次运行后可以看到已经恢复了正常。

        但在我们写入的是一个对象时,会将其自动序列化为一个 json 格式。但其将 User 类的字节码同样写入了进去,这样会占用额外的内存,浪费空间

        想要解决这个问题,我们只能统一的使用 String 序列化器,缺点是只能存储 String 类型的 key value,想要存储对象只能手动的完成对象的序列化反序列化

        但 Spring 默认提供了一个 StringRedisTemplate  类,它的 key value 的序列化方式默认就是 String 方式,所以我们可以直接使用它而不用再手动编写。

@Autowired
private StringRedisTemplate redisTemplate;

        再次传入对象时,可以看到以及不会再出现问题。


【完】

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐