Redis C++ 客户端使用指南-List 篇

Redis C++ 客户端使用指南-List 篇

八月 15, 2025 次阅读

Redis++(C++)List 类型常用接口详解

在 C++ 后端开发中,redis++ 提供了丰富的 List 类型操作接口,支持高效的头尾插入、弹出、阻塞弹出等功能。下面结合实际代码示例,详细介绍常用接口的函数原型和用法。


lpush、lrange

函数原型:

long long lpush(const StringView &key, const StringView &val);
template <typename Output>
void lrange(const StringView &key, long long start, long long stop, Output output);

示例:


// 清空Redis数据库
redis.flushall();

// 从列表左侧插入元素(插入顺序为value1→value2→value3→value4)
// 最终列表顺序为[value4, value3, value2, value1]
redis.lpush("mylist", "value1");
redis.lpush("mylist", "value2"); 
redis.lpush("mylist", "value3");
redis.lpush("mylist", "value4");

// 查询列表全部元素(0表示第一个元素,-1表示最后一个元素)
std::cout << "List contents after lpush:" << std::endl;
std::vector<std::string> values;
redis.lrange("mylist", 0, -1, std::back_inserter(values));
for (const auto &value : values) {
    std::cout << value << std::endl;
}

结果输出:

List contents after lpush:
value4
value3
value2
value1

rpush、lpop、rpop

函数原型:

long long rpush(const StringView &key, const StringView &val);
OptionalString lpop(const StringView &key);
OptionalString rpop(const StringView &key);

示例:


// 清空Redis数据库
redis.flushall();

// 从列表右侧插入元素(插入顺序为value1→value2→value3)
// 最终列表顺序为[value1, value2, value3]
redis.rpush("mylist", "value1");
redis.rpush("mylist", "value2");
redis.rpush("mylist", "value3");

// 查询列表全部元素
std::cout << "List contents after rpush:" << std::endl;
std::vector<std::string> values;
redis.lrange("mylist", 0, -1, std::back_inserter(values));
for (const auto &value : values) {
    std::cout << value << std::endl;
}

// 从左侧弹出元素(移除并返回第一个元素)
auto lpop_value = redis.lpop("mylist");
std::cout << "LPOP value: " << lpop_value.value_or("nil") << std::endl;

// 从右侧弹出元素(移除并返回最后一个元素)
auto rpop_value = redis.rpop("mylist");
std::cout << "RPOP value: " << rpop_value.value_or("nil") << std::endl;

// 查询弹出后的列表内容
std::cout << "List contents after pop:" << std::endl;
values.clear();
redis.lrange("mylist", 0, -1, std::back_inserter(values));
for (const auto &value : values) {
    std::cout << value << std::endl;
}

结果输出:

List contents after rpush:
value1
value2
value3
LPOP value: value1
RPOP value: value3
List contents after pop:
value2

blpop(阻塞弹出)

函数原型:

template <typename Rep, typename Period>
Optional<std::pair<std::string, std::string>> blpop(std::initializer_list<StringView> keys, const std::chrono::duration<Rep, Period> &timeout);

示例:


// 清空Redis数据库
redis.flushall();

// 创建两个线程模拟生产者
std::thread t1([]() {
    // 每个线程创建自己的Redis连接实例(重要!)
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    
    // 线程1在2秒后向mylist1插入数据
    std::this_thread::sleep_for(2s);
    redis.rpush("mylist1", "value1"); 
});

std::thread t2([]() {
    // 线程2在1秒后向mylist2插入数据
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    std::this_thread::sleep_for(1s);
    redis.rpush("mylist2", "value2");
});

// 主线程循环阻塞弹出
while (true) {
    // 阻塞弹出(最多等待10秒),监听mylist1和mylist2
    auto blpop_value = redis.blpop({"mylist1", "mylist2"}, 10s);

    if (blpop_value) {
        // 返回值为pair<list_name, value>
        std::cout << blpop_value->first << ": BLPOP value: " 
                  << blpop_value->second << std::endl;
    } else {
        std::cout << "BLPOP timed out" << std::endl;
        break;
    }
}

// 等待线程结束
t1.join();
t2.join();

结果输出:

mylist2: BLPOP value: value2
mylist1: BLPOP value: value1
BLPOP timed out

重点说明

你可能会疑惑,为什么没有将 redis 实例直接共享给 t1t2
实际上,redis++ 的 Redis 实例不是线程安全的,如果多个线程共享同一个 Redis 连接,会导致连接状态混乱,尤其在有阻塞操作(如 blpop)时,极易出现 UNBLOCKED force unblock from blocking operation 这类异常。

正确做法是:每个线程都创建自己的 Redis 连接实例。
这样可以避免主从切换、连接被强制中断等问题,保证阻塞操作的正常执行。


llen

函数原型:

long long llen(const StringView &key);

示例:


// 清空Redis数据库
redis.flushall();

// 向列表插入三个元素
redis.rpush("mylist", "value1");
redis.rpush("mylist", "value2");
redis.rpush("mylist", "value3");

// 获取列表长度
auto llen = redis.llen("mylist");
std::cout << "Length of mylist: " << llen << std::endl;

// 获取不存在的列表长度
auto non_exist_len = redis.llen("non_exist_list");
std::cout << "Length of non_exist_list: " << non_exist_len << std::endl;

结果输出:

Length of mylist: 3
Length of non_exist_list: 0

通过这些接口,C++ 后端可以高效地操作 Redis 的 List 类型数据结构。注意多线程场景下每个线程应独立创建 Redis 连接,避免线程安全问题和阻塞操作异常。