Redis:不只是缓存那么简单(十)

专栏:Redis 修行录

个人主页:手握风云

目录

[一、String 类型核心操作](#一、String 类型核心操作)

[1.1. 批量操作](#1.1. 批量操作)

[1.2. 内容追加](#1.2. 内容追加)

[1.3. 截取与替换](#1.3. 截取与替换)

[1.4. 防覆盖设置](#1.4. 防覆盖设置)

[1.5. 毫秒级过期](#1.5. 毫秒级过期)

[1.6. 原子数值增减](#1.6. 原子数值增减)

[二、List 类型核心操作](#二、List 类型核心操作)

[2.1. 基础左右增删](#2.1. 基础左右增删)

[2.2. 范围查询](#2.2. 范围查询)

[2.3. 阻塞弹出](#2.3. 阻塞弹出)

[2.4. 索引与插入](#2.4. 索引与插入)

[2.5. 长度统计](#2.5. 长度统计)


一、String 类型核心操作

Jedis 针对 Redis String 类型提供了一组常用字符串操作 API,覆盖批量读写、内容追加、截取替换、防覆盖设置、过期控制、原子数值增减等核心场景。

1.1. 批量操作

  • mset:一次性设置多个 key-value 键值对。
  • mget:一次性获取多个 key 对应的 value,返回值列表。
java 复制代码
public static void test1(Jedis jedis) {
    System.out.println("批量操作: mset / mget");
    jedis.flushDB();

    // 一次性设置多个 key-value
    jedis.mset("user1", "Alice", "user2", "Bob");
    System.out.println("设置多个 key-value 成功");

    // 一次性获取多个 key 对应的 value
    List<String> values = jedis.mget("user1", "user2", "user3");
    System.out.println("获取结果: " + values);

    System.out.println("======");
}

1.2. 内容追加

  • append:向指定 key 的字符串末尾追加内容,获取后得到拼接后的完整字符串。
java 复制代码
public static void test2(Jedis jedis) {
    System.out.println("内容追加: append");
    jedis.flushDB();

    jedis.set("greeting", "Hello");
    System.out.println("出事字符串: " + jedis.get("greeting"));

    // 向末尾追加内容
    long newLen = jedis.append("greeting", "World!");
    System.out.println("追加后的长度: " + newLen);
    System.out.println("追加后的内容: " + jedis.get("greeting") + "\n");

    System.out.println("======");
}

1.3. 截取与替换

  • getrange:按闭区间截取字符串的指定子串。
  • setrange:从指定下标位置开始,替换字符串的部分内容。
java 复制代码
public static void test3(Jedis jedis) {
    System.out.println("截取与替换: getrange / setrange");
    jedis.flushDB();

    jedis.set("title", "RedisStringTutorial");

    // 闭区间 [start, end] 截取
    String subString = jedis.getrange("title", 0, 4);
    System.out.println("截取的子串结果: " + subString);

    // 从指定下标开始替换内容
    jedis.setrange("title", 5, "Hash");
    System.out.println("替换后的内容: " + jedis.get("title"));

    System.out.println("======");
}

1.4. 防覆盖设置

  • setnx:仅当 key 不存在时才设置值,设置成功返回 1,已存在则返回 0(不覆盖)。
java 复制代码
public static void test4(Jedis jedis) {
    System.out.println("防覆盖设置: setnx");
    jedis.flushDB();

    // 第一次设置,key 不存在
    long ret1 = jedis.setnx("lock_resource", "locked_by_thread_1");
    System.out.println("首次 setnx 结果: " + ret1 + " (1 表示成功设置)");

    // 第二次设置,key 已存在
    long ret2 = jedis.setnx("lock_resource", "locked_by_thread_2");
    System.out.println("再次 setnx 结果: " + ret2 + " (0 表示 key 已存在,未覆盖)");

    System.out.println("======");
}

1.5. 毫秒级过期

  • psetex:设置键值的同时,指定毫秒级过期时间。
  • pttl:查询 key 剩余的过期时间(毫秒)。
java 复制代码
public static void test5(Jedis jedis) {
    System.out.println("毫秒级过期: psetex / pttl");
    jedis.flushDB();

    // 设置键值对,并指定 5000 ms 后过期
    jedis.psetex("temp_token", 5000L, "token_abc123");

    // 查询剩余毫秒级过期时间
    long pttl = jedis.pttl("temp_token");
    System.out.println("剩余过期时间: " + pttl + "\n");

    System.out.println("======");
}

1.6. 原子数值增减

  • incr/decr:对数值型字符串执行 ±1 原子操作。
  • incrby/decrby:按指定步长,对数值型字符串执行 ± 指定数值 原子操作。
java 复制代码
public static void test6(Jedis jedis) {
    System.out.println("原子数值增减: incr / decr / incrby / decrby");
    jedis.flushDB();

    jedis.set("page_view", "100");

    // 自增 1
    jedis.incr("page_view");
    System.out.println("自增 1 之后: " + jedis.get("page_view"));

    // 自减 1
    jedis.decr("page_views");
    System.out.println("自减 1 之后: " + jedis.get("page_views"));

    // 自增指定数值
    jedis.incrBy("page_views", 20);
    System.out.println("自增 20 之后: " + jedis.get("page_views"));

    // 自减指定数值
    jedis.decrBy("page_views", 30);
    System.out.println("自减 20 之后: " + jedis.get("page_views"));

    System.out.println("======");
}

二、List 类型核心操作

Redis 列表为双向链表结构,基于 Jedis 实现的列表操作围绕左 / 右增删、范围查询、阻塞弹出、索引定位、指定位置插入、长度统计展开,核心方法及功能如下:

2.1. 基础左右增删

  • lpush / lpop:lpush 从列表左侧批量添加元素,返回元素总数;lpop 从列表左侧弹出元素,列表为空时返回 null。
  • rpush / rpop:rpush 从列表右侧批量添加元素,返回元素总数;rpop 从列表右侧弹出元素,列表为空时返回 null。
java 复制代码
public static void test1(Jedis jedis) {
    System.out.println("基础左右增删: lpush / lpop 和 rpush / rpop 操作");
    jedis.flushDB();

    String key = "list:basic";

    // 从左侧批量添加
    long lpushCount = jedis.lpush(key, "val1", "val2", "val3");
    System.out.println("列表里面元素总数: " + lpushCount);

    // 从左侧弹出元素
    String lpopRet = jedis.lpop(key);
    System.out.println("列表从左侧弹出元素: " + lpopRet);

    // 从右侧批量添加
    long rpushCount = jedis.rpush(key, "val4", "val5");
    System.out.println("列表里面元素总数: " + rpushCount);

    // 从右侧弹出元素
    String rpopRet = jedis.rpop(key);
    System.out.println("列表从右侧弹出元素: " + rpopRet);

    System.out.println("======");
}

2.2. 范围查询

lrange:按闭区间索引获取列表元素,0 为起始、-1 为末尾,可查询全量数据。

java 复制代码
public static void test2(Jedis jedis) {
    System.out.println("范围查询: lrange 操作");
    jedis.flushDB();

    String key = "list:range";

    jedis.rpush(key, "a", "b", "c", "d", "e");

    // 查询全部数据
    List<String> rangeList = jedis.lrange(key, 0, -1);
    System.out.println("查询结果: " + rangeList);

    System.out.println("======");
}

2.3. 阻塞弹出

blpop / brpop:阻塞式左 / 右弹出,超时时间设为 0 表示无限等待;返回 [key, value] 二元组,需通过新 Jedis 连接插入数据才能触发返回。

java 复制代码
public static void test3(Jedis producerJedis) {
    System.out.println("阻塞弹出: blpop / brpop");
    producerJedis.flushDB();

    String key = "list:blocking";

    // 模拟延迟 1 秒后,通过新的 Jedis 连接插入数据
    Thread t1 = new Thread(() -> {
        try {
            Thread.sleep(1_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("生产者正在通过新连接 rpush 插入新数据...");
        producerJedis.rpush(key, "wake_up");
    });

    JedisPool pool = new JedisPool("tcp://127.0.0.1:8888");

    try (Jedis consumerJedis = pool.getResource()) {
        consumerJedis.flushDB();

        t1.start();
        System.out.println("消费者正在通过新连接 blpop 阻塞弹出数据...");
        List<String> ret = consumerJedis.blpop(0, key);

        System.out.println("消费者阻塞弹出的数据: " + ret);
        System.out.println("======");
    }
}

2.4. 索引与插入

  • lindex:获取列表指定索引的元素。
  • linsert:在指定元素前(BEFORE)/ 后(AFTER)插入新元素,需通过 ListPosition 枚举指定位置。
java 复制代码
public static void test4(Jedis jedis) {
    System.out.println("索引与插入: lindex 与 linsert");
    jedis.flushDB();

    String key = "list:index_insert";
    jedis.rpush(key, "item1", "item2", "item3");

    // 获取指定索引的元素
    String indexRet = jedis.lindex(key, 1);
    System.out.println("索引为 1 的元素: " + indexRet);

    // 在 "item2" 之前添加 "new_item1"
    jedis.linsert(key, ListPosition.BEFORE, "item2", "new_item1");

    // 在 "item2" 之后添加 "new_item2"
    jedis.linsert(key, ListPosition.AFTER, "item2", "new_item2");

    List<String> ret = jedis.lrange(key, 0, -1);
    System.out.println("插入新数据后的结果: " + ret);

    System.out.println("======");
}

2.5. 长度统计

  • llen:查询列表的元素总个数。
java 复制代码
public static void test5(Jedis jedis) {
    System.out.println("长度统计: llen");
    jedis.flushDB();

    String key = "list:length";
    jedis.rpush(key, "A", "B", "C", "D", "E");

    long len = jedis.llen(key);
    System.out.println("当前元素个数: " + len);

    System.out.println("======");
}
相关推荐
一写代码就开心14 小时前
redis-cli 客户端查询set集合里面的具体数据
数据库·redis·缓存
S1998_1997111609•X15 小时前
针对犯罪集团etc/all,pid,IP的规划及量化逻辑原理
网络·安全·百度·缓存·量子计算
Irissgwe17 小时前
redis之典型应用-缓存cache
数据库·redis·缓存·缓存击穿·缓存雪崩·redis淘汰策略
无盐海21 小时前
Foundatio,内存,Redis 缓存
数据库·redis·缓存
shark-chili1 天前
基于claude code的redis慢查询指令复刻实践
数据库·redis·缓存
xu_ws1 天前
spring通过三级缓存解决循环依赖
java·spring·缓存·循环依赖
IronMurphy1 天前
Redis拷打第二讲
数据库·redis·缓存
手握风云-1 天前
Redis:不只是缓存那么简单(八)
redis·缓存
phltxy1 天前
Redis Set:原理、命令与实战场景详解
数据库·redis·缓存