Java操作Redis

Java操作Redis

分类

  • Jedis (官方推荐)

    • 特点:轻量级、同步阻塞、直接操作 Redis 命令

    • 导入依赖

    • <dependency>
          <groupId>redis.clients</groupId>
          <artifactId>jedis</artifactId>
          <version>4.4.3</version>
      </dependency>
      
  • Lettuce (Spring 官方推荐)

    • 特点:基于 Netty 实现异步非阻塞、支持 Reactive 编程

    • 依赖

    • <dependency>
          <groupId>io.lettuce</groupId>
          <artifactId>lettuce-core</artifactId>
          <version>6.2.6.RELEASE</version>
      </dependency>
      
  • Spring Data Redis (整合框架)

    • 特点:封装了 Jedis/Lettuce,提供模板化操作

    • 依赖

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

Jedis

  • 导入依赖

  • 启动Redis服务器

  • 连接到 Redis

    • import redis.clients.jedis.Jedis;
      
      public class JedisExample {
          public static void main(String[] args) {
              // 1. 创建 Jedis 实例(默认连接本地 6379 端口)
              try (Jedis jedis = new Jedis("localhost", 6379)) {
                  // 2. 认证(如果 Redis 设置了密码)
                  jedis.auth("your_password");
      
                  // 3. 测试连接
                  System.out.println("连接成功: " + jedis.ping());
              }
          }
      }
      
  • 基本操作

    • 字符串(String)

      • jedis.set("key", "value");
        String value = jedis.get("key");
        System.out.println(value); // 输出 "value"
        
        // 设置过期时间(单位:秒)
        jedis.setex("temp_key", 60, "temp_value");
        
        // 设置键值对,并指定过期时间(60秒),仅在键不存在时设置
        SetParams params = SetParams.setParams().nx().ex(60);
        String result = jedis.set("temp_key", "temp_value", params);
        
    • 哈希(Hash)

      • jedis.hset("user:1", "name", "Alice");
        jedis.hset("user:1", "age", "30");
        
        Map<String, String> user = jedis.hgetAll("user:1");
        System.out.println(user); // {name=Alice, age=30}
        
    • 列表(List)

      • jedis.lpush("mylist", "item1", "item2");
        List<String> list = jedis.lrange("mylist", 0, -1); // 获取所有元素
        System.out.println(list); // [item2, item1]
        
    • 集合(Set)

      • jedis.sadd("myset", "a", "b", "c");
        Set<String> set = jedis.smembers("myset");
        System.out.println(set); // [a, b, c]
        
    • 有序集合(Sorted Set)

      • jedis.zadd("ranking", 100, "player1");
        jedis.zadd("ranking", 90, "player2");
        List<String> topPlayers = jedis.zrevrange("ranking", 0, 1); // 获取前两名
        System.out.println(topPlayers); // [player1, player2]
        
  • 事务(Transaction)

    • try (Jedis jedis = new Jedis("localhost")) {
          Transaction tx = jedis.multi(); // 开启事务
          tx.set("a", "1");
          tx.incr("a");
          tx.get("a");
          List<Object> results = tx.exec(); // 执行事务
      
          // 输出结果:[OK, 2, 2]
          System.out.println(results); 
      }
      
  • 连接池(JedisPool)

    • 推荐使用连接池管理资源,避免频繁创建和销毁连接:

    • import redis.clients.jedis.JedisPool;
      import redis.clients.jedis.JedisPoolConfig;
      
      public class JedisPoolDemo {
          public static void main(String[] args) {
              JedisPoolConfig config = new JedisPoolConfig();
              config.setMaxTotal(100);    // 最大连接数
              config.setMaxIdle(20);      // 最大空闲连接数
      
              try (JedisPool jedisPool = new JedisPool(config, "localhost", 6379)) {
                  try (Jedis jedis = jedisPool.getResource()) {
                      jedis.set("pool_key", "pool_value");
                      System.out.println(jedis.get("pool_key"));
                  }
              }
          }
      }
      
    • JedisPool 的构造函数支持以下参数:

      • config:连接池配置(JedisPoolConfig)。
      • host:Redis 服务器地址(如 localhost)。
      • port:Redis 服务器端口(默认 6379)。
      • timeout:连接超时时间(单位:毫秒)。
      • password:Redis 服务器密码。
  • 注意事项

    • 异常处理:所有操作都可能抛出 JedisConnectionException,需捕获处理。
    • 资源释放:使用 try-with-resources 或手动关闭 Jedis 实例。
    • 线程安全:Jedis 实例非线程安全,每个线程应使用独立实例或连接池。
    • 性能优化:合理配置连接池参数,避免资源耗尽。

Spring Data Redis

  • 启动Redis服务

  • 添加依赖

    • <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
      
  • 配置 Redis 连接

    • spring:
        redis:
          host: localhost
          port: 6379
          password: your_password
          timeout: 2000ms
      
  • Spring Data Redis 的核心组件包括:

    • RedisTemplate:用于操作 Redis 的模板类,支持多种数据类型的操作。
    • StringRedisTemplate:专门用于操作字符串类型的模板类。
    • RedisRepository:用于实现 Redis 数据访问的仓库接口。
  • 配置 RedisTemplate

    • 在 Spring Boot 中,默认会自动配置 RedisTemplateStringRedisTemplate。如果需要自定义配置,可以手动定义 Bean

    • @Configuration
      public class RedisConfig {
      
          @Bean
          public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
              RedisTemplate<String, Object> template = new RedisTemplate<>();
              template.setConnectionFactory(connectionFactory);
      
              // 设置键和值的序列化器
              template.setKeySerializer(new StringRedisSerializer());
              template.setValueSerializer(new StringRedisSerializer());
      
              return template;
          }
      }
      
  • Lettuce 是一个基于 Netty 的高性能 Redis 客户端,它本身是线程安全的,默认情况下不需要连接池,因为它的连接是异步的且可以共享。

  • Spring Boot:自动配置连接池(如果需要),具体行为取决于使用的客户端(Lettuce 或 Jedis)。

  • 如果没有特殊需求,直接使用 Spring Boot 的默认配置即可,它会处理好连接池的问题。如果需要优化性能或调整连接池参数,可以通过配置文件或代码进行自定义配置。

RedisTemplate

  • RedisTemplate 是 Spring Data Redis 提供的一个核心工具类,用于与 Redis 进行交互。它封装了 Redis 的常用操作,并提供了丰富的 API 来操作各种数据类型(如字符串、哈希、列表、集合、有序集合等)。

  • RedisTemplate 的基本配置

    • 在使用 RedisTemplate 之前,通常需要对其进行配置,包括设置连接工厂和序列化器。

    • RedisTemplate 默认使用 JdkSerializationRedisSerializer,这会将对象序列化为字节数组。这种序列化方式可能会导致存储的数据不易读,并且在跨语言环境中不兼容。

    • 序列化后的数据体积较大,可能会影响性能。

    • @Configuration
      public class RedisConfig {
      
          @Bean
          public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
              RedisTemplate<String, Object> template = new RedisTemplate<>();
              template.setConnectionFactory(connectionFactory);
      
              /* 设置键和值的序列化器
              template.setKeySerializer(new StringRedisSerializer()); 设置的是 Redis 中所有普通键(key)的序列化器。这里的“普通键”指的是 Redis 中最常见的键类型,比如字符串、列表、集合、有序集合等数据结构的键。*/
              template.setKeySerializer(new StringRedisSerializer());
              template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
      
              // 设置哈希键和值的序列化器
              /*
              哈希类型(hash)在 Redis 中是一种特殊的数据结构,它包含键值对。因此,RedisTemplate 提供了 setHashKeySerializer 和 setHashValueSerializer 来分别处理哈希键和哈希值的序列化。
              */
              template.setHashKeySerializer(new StringRedisSerializer());
              template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
      
              return template;
          }
      }
      
    • StringRedisSerializer:用于序列化键和哈希键,确保键以字符串形式存储。

    • GenericJackson2JsonRedisSerializer:用于序列化值和哈希值,支持将对象序列化为 JSON 格式。

  • RedisTemplate 的常用操作

    • 操作键(Key)

      • RedisTemplate 提供了直接操作键的方法。

      • public void keyOperations() {
            // 设置键值对
            redisTemplate.opsForValue().set("key1", "value1");
        
            // 检查键是否存在
            boolean exists = redisTemplate.hasKey("key1");
            System.out.println("Key exists: " + exists);
        
            // 设置键的过期时间
            redisTemplate.expire("key1", 60, TimeUnit.SECONDS);
        
            // 获取键的剩余过期时间
            Long ttl = redisTemplate.getExpire("key1");
            System.out.println("TTL: " + ttl);
        
            // 删除键
            redisTemplate.delete("key1");
        }
        
    • 操作字符串(String)

      • 字符串是 Redis 中最基本的数据类型,RedisTemplate 提供了 opsForValue() 方法来操作字符串。

      • @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        
        public void stringOperations() {
            // 设置值
            redisTemplate.opsForValue().set("name", "Alice");
        
            // 获取值
            String name = (String) redisTemplate.opsForValue().get("name");
            System.out.println("Name: " + name);
        
            // 删除键
            redisTemplate.delete("name");
        
            // 检查键是否存在
            boolean exists = redisTemplate.hasKey("name");
            System.out.println("Key exists: " + exists);
        }
        
    • 操作哈希(Hash)

      • 哈希用于存储字段和值的映射,RedisTemplate 提供了 opsForHash() 方法来操作哈希。

      • public void hashOperations() {
            String key = "user:1";
        
            // 设置哈希字段
            redisTemplate.opsForHash().put(key, "name", "Bob");
            redisTemplate.opsForHash().put(key, "age", 25);
        
            // 获取哈希字段
            String name = (String) redisTemplate.opsForHash().get(key, "name");
            int age = (int) redisTemplate.opsForHash().get(key, "age");
            System.out.println("Name: " + name + ", Age: " + age);
        
            // 获取所有字段和值
            Map<Object, Object> user = redisTemplate.opsForHash().entries(key);
            System.out.println("User: " + user);
        
            // 删除哈希字段
            redisTemplate.opsForHash().delete(key, "age");
        }
        
    • 操作列表(List)

      • 列表是一个有序的字符串集合,RedisTemplate 提供了 opsForList() 方法来操作列表。

      • public void listOperations() {
            String key = "tasks";
        
            // 从左侧插入元素
            redisTemplate.opsForList().leftPush(key, "Task 1");
            redisTemplate.opsForList().leftPush(key, "Task 2");
        
            // 从右侧插入元素
            redisTemplate.opsForList().rightPush(key, "Task 3");
        
            // 获取列表范围
            List<Object> tasks = redisTemplate.opsForList().range(key, 0, -1);
            System.out.println("Tasks: " + tasks);
        
            // 从左侧弹出元素
            String task = (String) redisTemplate.opsForList().leftPop(key);
            System.out.println("Popped task: " + task);
        }
        
    • 操作集合(Set)

      • 集合是一个无序的字符串集合,且元素唯一,RedisTemplate 提供了 opsForSet() 方法来操作集合。

      • public void setOperations() {
            String key = "tags";
        
            // 添加元素
            redisTemplate.opsForSet().add(key, "Java", "Redis", "Spring");
        
            // 获取所有元素
            Set<Object> tags = redisTemplate.opsForSet().members(key);
            System.out.println("Tags: " + tags);
        
            // 检查元素是否存在
            boolean exists = redisTemplate.opsForSet().isMember(key, "Java");
            System.out.println("Java exists: " + exists);
        
            // 删除元素
            redisTemplate.opsForSet().remove(key, "Spring");
        }
        
    • 操作有序集合(ZSet)

      • 有序集合是一个有序的字符串集合,每个元素关联一个分数,RedisTemplate 提供了 opsForZSet() 方法来操作有序集合。

      • public void zSetOperations() {
            String key = "rank";
        
            // 添加元素
            redisTemplate.opsForZSet().add(key, "Alice", 100);
            redisTemplate.opsForZSet().add(key, "Bob", 90);
            redisTemplate.opsForZSet().add(key, "Charlie", 80);
        
            // 获取元素排名(按分数从低到高)
            Long rank = redisTemplate.opsForZSet().rank(key, "Bob");
            System.out.println("Bob's rank: " + rank);
        
            // 获取元素分数
            Double score = redisTemplate.opsForZSet().score(key, "Alice");
            System.out.println("Alice's score: " + score);
        
            // 获取范围内的元素(按分数从低到高)
            Set<Object> topUsers = redisTemplate.opsForZSet().range(key, 0, 1);
            System.out.println("Top users: " + topUsers);
        }
        
  • 事务支持

    • RedisTemplate 支持事务操作,可以通过 multi()exec() 方法实现。

    • public void transactionOperations() {
          redisTemplate.execute(new SessionCallback<Object>() {
              @Override
              public Object execute(RedisOperations operations) throws DataAccessException {
                  operations.multi(); // 开启事务
                  operations.opsForValue().set("key1", "value1");
                  operations.opsForValue().set("key2", "value2");
                  return operations.exec(); // 提交事务
              }
          });
      }
      

StringRedisTemplate

  • StringRedisTemplate 是 Spring Data Redis 提供的一个专门用于处理字符串数据的 RedisTemplate 实现。它是 RedisTemplate 的一个子类,专门针对键和值都是字符串的场景进行了优化和简化。

  • 特点

    • 键和值都是字符串StringRedisTemplate 默认将键(key)和值(value)都序列化为字符串。它使用 StringRedisSerializer 作为默认的序列化器。
    • 简化配置:相比于通用的 RedisTemplateStringRedisTemplate 不需要手动配置序列化器,开箱即用。默认全部都为字符串序列化器
      • 当直接尝试使用 StringRedisTemplate 将一个对象作为值存入 Redis 时,由于 StringRedisTemplate 期望的是字符串类型的值,而传入的是对象,会导致 ClassCastExceptionSerializationException
    • 适用于字符串操作:适合处理 Redis 中的字符串数据,比如简单的键值对、计数器等。
      • StringRedisTemplate 虽然主要处理字符串类型的数据,但它能够进行递增操作,这是因为 Redis 本身支持对存储为字符串形式的数字进行原子性的递增和递减操作。
      • 要确保存储在 Redis 中的值是可以被解析为数字的字符串,否则会抛出异常。例如,如果键 "counter" 存储的是 "abc",执行递增操作时 Redis 会报错,因为 "abc" 无法被解析为数字。
  • 初始化方式

    • // 通过 Spring Boot 自动配置
      @Autowired
      private StringRedisTemplate stringRedisTemplate;
      
      // 手动创建
      StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory);
      
  • 主要操作方法

    • 值操作 (ValueOperations)

      • // 设置值
        stringRedisTemplate.opsForValue().set("key", "value");
        
        // 获取值
        String value = stringRedisTemplate.opsForValue().get("key");
        
        // 设置带过期时间
        stringRedisTemplate.opsForValue().set("key", "value", 10, TimeUnit.SECONDS);
        
        // 递增
        Long newValue = stringRedisTemplate.opsForValue().increment("counter");
        
    • 列表操作 (ListOperations)

      • // 左推
        stringRedisTemplate.opsForList().leftPush("listKey", "value1");
        
        // 右推
        stringRedisTemplate.opsForList().rightPush("listKey", "value2");
        
        // 获取范围
        List<String> range = stringRedisTemplate.opsForList().range("listKey", 0, -1);
        
    • 集合操作 (SetOperations)

      • // 添加元素
        stringRedisTemplate.opsForSet().add("setKey", "value1", "value2");
        
        // 获取所有成员
        Set<String> members = stringRedisTemplate.opsForSet().members("setKey");
        
    • 哈希操作 (HashOperations)

      • // 设置哈希字段
        stringRedisTemplate.opsForHash().put("hashKey", "field", "value");
        
        // 获取哈希字段
        String hashValue = (String) stringRedisTemplate.opsForHash().get("hashKey", "field");
        
    • 有序集合操作 (ZSetOperations)

      • // 添加元素
        stringRedisTemplate.opsForZSet().add("zsetKey", "member", 10.0);
        
        // 获取范围
        Set<String> range = stringRedisTemplate.opsForZSet().range("zsetKey", 0, -1);
        
  • 事务支持

    • stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
          @Override
          public List<Object> execute(RedisOperations operations) throws DataAccessException {
              operations.multi();
              operations.opsForValue().set("key1", "value1");
              operations.opsForValue().set("key2", "value2");
              return operations.exec();
          }
      });
      
posted @ 2025-03-26 18:40  QAQ001  阅读(95)  评论(0)    收藏  举报