【Redis】Redis 的 Java 客户端(Jedis、SpringDataRedis)

1. Jedis

Jedis 是 Redis 官方推荐的 Java 连接开发工具。

Jedis 的官网地址为:https://github.com/redis/jedis

1.1 使用步骤

  1. 引入依赖:

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.7.0</version>
    </dependency>
    
  2. 创建 Jedis 对象,建立连接

    private Jedis jedis;
    
    // 1. 建立连接
    jedis = new Jedis("IP",6379);
    // 2. 设置密码
    jedis.auth("1234");
    // 3. 选择库(不选默认为 0 号库)
    jedis.select(0);
    
  3. 使用 Jedis,方法名与 Redis 命令一致

    // 测试 String 类型
    // 存入数据
    String result = jedis.set("color", "red");
    System.out.println("result = " + result);
    // 获取数据
    String color = jedis.get("color");
    System.out.println(color);
    
    // 测试 hash 类型
    // 存入 hash 数据
    jedis.hset("user:1", "name", "jack");
    jedis.hset("user:1", "age", "21");
    // 取数据
    Map<String, String> map = jedis.hgetAll("user:1");
    map.forEach((k, v) ->{
          
          
        System.out.println(k + ": " + v);
    });
    
  4. 释放资源

    // 关闭资源
    if(jedis != null){
          
          
        jedis.close();
    }
    

1.2 Jedis 连接池

Jedis 本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐使用 Jedis 连接池代替 Jedis 的直连方式。

以下对 Jedis 做了一个封装:

public class JedisConnectionFactory {
    
    

    private static final JedisPool jedisPool;

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

    // 获取 Jedis 对象
    public static Jedis getJedis(){
    
    
        return jedisPool.getResource();
    }
}

2. SpringDataRedis

2.1 基本介绍

SpringData 是 Spring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 的集成模块就叫做 SpringDataRedis,官网地址为:https://spring.io/projects/spring-data-redis

SpringDataRedis 有很强大的功能:

  • 提供了对不同 Redis 客户端的整合。(Lettuce 和 Jedis)
  • 提供了 RedisTemplate 统一 API 来操作 Redis
  • 支持 Redis 的发布订阅模型
  • 支持 Redis 哨兵和 Redis 集群
  • 支持基于 Lettuce 的响应式编程
  • 支持基于 JDK、JSON、字符串、Spring 对象的数据系列化及反序列化
  • 支持基于 Redis 的 JDKCollection 实现

2.1 使用方式

SpringDataRedis 中提供了 RedisTemplate 工具类,其中封装了各种对 Redis 的操作。并且将不同数据类型的操作 API 封装到了不同的类型中:

API 返回值类型 说明
redisTemplate.opsForValue() ValueOperations 操作 String 类型数据
redisTemplate.opsForHash() HashOperations 操作 Hash 类型数据
redisTemplate.opsForList() ListOperations 操作 List 类型数据
redisTemplate.opsForSet() SetOperations 操作 Set 类型数据
redisTemplate.opsForZSet() ZSetOperations 操作 SortedSet 类型数据
redisTemplate 通用命令

SpringBoot 已经提供了对 SpringDataRedis 的支持,使用方式如下:

  1. 引入依赖

    <!-- 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>
    
  2. 配置文件(Spring 默认使用 lettuce 实现,可以直接引用,如果要选择 jedis,则要额外引入相关依赖)

    spring:
      redis:
        host: IP
        port: 6379
        password: 1234
        database: 0 # 选择0号数据库
        lettuce: # 选择 lettuce
          pool:
            max-active: 8 # 最大连接
            max-idle: 8 # 最大空闲连接
            min-idle: 0 # 最小空闲连接
            max-wait: 1000 # 连接等待时间
    
  3. 注入 RedisTemplate

    @Autowired
    private RedisTemplate redisTemplate;
    
  4. 编写测试

    @Autowired
    private RedisTemplate redisTemplate;
    
    // 写入一条 String 数据
    redisTemplate.opsForValue().set("name", "rose");
    // 获取数据
    Object name = redisTemplate.opsForValue().get("name");
    System.out.println("name = " + name);
    

2.3 SpringDataRedis 的序列化方式

RedisTemplate 可以接收任意 Object 作为值写入 Redis,只不过写入前会把 Object 序列化为字节形式,默认是采用 JDK 序列化,得到的结果为:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daFb0o9V-1660125804789)(C:/Users/bbbbbge/Pictures/接单/1660122313198.png)]

在 RedisTemplate 的源码中,我们可以发现 key 和 value 的序列化器的值为 null。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zQqql4eb-1660125804790)(C:/Users/bbbbbge/Pictures/接单/1660122592029.png)]

当默认的序列化器的值为 null 时,就会通过 JDK 的序列化器来对 key 和 value 进行序列化。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WdXDKHkE-1660125804790)(C:/Users/bbbbbge/Pictures/接单/1660122709016.png)]

而 JDK 的序列化器是通过 ObjectOutputStream 将 key 和 value 转化成字节再传递到 Redis 中的。因此会具有如下缺点:

  • 可读性差
  • 内存占用大

解决办法:

改变 RedisTemplate 的序列化方式,而 RedisTemplate 中除了可以使用 JdkSerializationRedisSerializer 外,还能够使用以下两种:

  • StringRedisSerializer:用于将 String 进行序列化的工具,适合当作 key 的序列化器。
  • GenericToStringSerializer(不推荐,原因在下一节):是转 JSON 字符串的序列化工具,适合用作含有对象的 value 进行进行序列化。

自定义 RedisTemplate 的序列化方式如下:

@Configuration
public class RedisConfig {
    
    

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
    
    
        // 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建 JSON 序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置 Key 的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置 Value 的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

注意:

使用 GenericToStringSerializer 需要引入 json 依赖(mvc 依赖中会自带):

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

2.4 StringRedisTemplate

尽管 JSON 的序列化方式可以满足我们的需求,但依然存在一些问题,如图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TYKsZxhl-1660125804791)(C:/Users/bbbbbge/Pictures/接单/1660124103339.png)]

为了在反序列化时知道对象的类型,JSON 序列化器会将类的 class 类型写入 json 结果中,再存入 Redis,会带来额外的内存开销。

解决办法:

为了节省内存空间,其实并不会使用 JSON 序列化器来处理 value,而是使用 String 序列化器,要求只能才能出 String 类型的 key 和 value。当我们需要存储 Java 对象时,手动完成对象序列化和反序列化。

Spring 默认提供了一个 StringRedisTemplate 类,它的 key 和 value 的序列化方式默认是 String 方式,省去了自定义 RedisTemplate 的过程。

使用方式如下:

@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON 工具
private static final ObjectMapper objectMapper = new ObjectMapper();


// 准备对象
User user = new User("李四", 18);
// 手动序列化
String jsonString = objectMapper.writeValueAsString(user);
// 写入数据到 redis
stringRedisTemplate.opsForValue().set("user:9", jsonString);
// 读取数据
String val = stringRedisTemplate.opsForValue().get("user:9");
// 反序列化
User user1 = objectMapper.readValue(val, User.class);
System.out.println("user1 = " + user1);

猜你喜欢

转载自blog.csdn.net/weixin_51367845/article/details/126271732