【redis初阶】redis客户端

目录

一、基本介绍

二、认识RESP(redis自定的应用层协议名称)

三、访问github的技巧

四、安装redisplusplus

4.1 安装 hiredis**

4.2 下载 redis-plus-plus 源码

4.3 编译/安装 redis-plus-plus

五、编写运行helloworld

六、redis命令演示

6.1 通用命令的使用

6.2 string的使用

6.3 list的使用

6.4 set的使用

6.5 hash的使用

6.6 zset的使用


redis学习🥳

一、基本介绍

在前面的学习中主要是学习 redis 的各种基本操作/命令,都是在 redis 命令行客户端中手动执行 redis各种命令,但这种操作方式不是我们日常开发中的主要形式;更多的时候,我们是使用 redis 的 api 来实现定制化的 redis 客户端程序,进一步操作 redis 服务器;

不管是 redis 提供的命令行客户端,还是第三方的图形化客户端,他们本质上都属于是“通用的客户端程序”。但相比之下,我们在工作中更希望使用到的是“专用的”“定制化”的客户端程序;

二、认识RESP(redis自定的应用层协议名称)

我们为什么能编写出一个自定义的redis客户端呢?

我们知道在网络通信过程中,会使用到很多的“协议”

应用层往下的协议是固定好的,是在系统内核或者驱动程序中实现的,我们是不可修改的,但是对于应用层来说,虽然业界有很多成熟的应用层协议,比如 http 等,但是此处更多的时候,都会“自定义”应用层协议,redis 此处应用层协议,就是自定义的应用层协议,客户端按照 resp 协议发送请求,服务器按照这个协议进行解析,在按照这个协议构造响应,客户端在解析这个响应,完成客户端和服务器的通信;

因此:resp 就是 redis 自定义的客户端和服务器用于通信的应用层协议;

resp协议特点:

  • 简单好实现;
  • 快速进行解析;
  • 肉眼可读;
  • 基于传输层的tcp,但是与tcp又没有强耦合;
  • 请求和响应之间的通信是一问一答的形式(客户端给服务器发起一个请求,服务器返回一个响应);
  • 客户端给redis服务器发送命令时:是以bulk string数组的形式发送的redis命令,对于不同的redis命令,服务器返回的结果是不一样的(ok、整个数组...);

在RESP中,第一个字节决定了数据类型:

  • 对于Simple Strings,回复的第一个字节是“+” eg:"+OK\r\n"
  • 对于Errors,回复的第一个字节是“-”   eg:"-Error message\r\n"
  • 对于Integers,回复的第一个字节是“:”   eg:":1000\r\n"
  • 对于Bulk Strings,回复的第一个字节是“$”   eg:"$5\r\nhello\r\n"
  • 对于Arrays,回复的第一个字节是“*”   eg:"*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n"

在进行通信的时候,服务器就把构造好的字符串,写入到 tcp socket 中;

Simple Strings 和 Bulk Strings 的区别:Simple String 只能用来传输文本,Bulk String 可以传输二进制数据;

上述这套协议公开已久,已经有很多大佬,实现了这套协议的解析/构造,在写代码的时候,我们不需要按照上述的协议,解析/构造字符串,只要使用这些大佬们提供的库,就可以比较简单方便的来完成和 redis 服务器通信的操作了;

三、访问github的技巧

翻墙 or 下载游戏加速器,推荐:watt toolkit

选中gitup,一键加速

四、安装redisplusplus

C++ 操作 redis 的库有很多,咱们此处使用 redis-plus-plus.

这个库的功能强大,使用简单.

Github 地址:  https://github.com/sewenew/redis-plus-plus

4.1 安装 hiredis**

redis-plus-plus 是基于 hiredis 实现的.

hiredis 是一个 C 语言实现的 redis 客户端.

因此需要先安装 hiredis. 直接使用包管理器安装即可.

在 Ubuntu 镜像下:

apt install libhiredis-dev

4.2 下载 redis-plus-plus 源码

git clone https://github.com/sewenew/redis-plus-plus.git

4.3 编译/安装 redis-plus-plus

redis-plus-plus 是使用 cmake 构建工具进行构建的,cmake 相当于是 Makefile 的升级版,Makefile 本身功能比较简陋,比较原始,写起来也比较麻烦实际开发中很少会手写 makefile,cmake 就是通过程序来生成 makefile 的 工具;

在 Ubuntu 镜像下:

使用 cmake 构建:

cd redis-plus-plus

# 创建一个 build 目录是习惯做法,并非必须。目的是为了让编译生成的临时文件都放到 build 下,避免污染源代码目录
mkdir build
cd build

# 这个操作是生成makefile,此处..指向的是刚才 CMakeLits.txt 文件所在的目录
cmake3 ..

make    # 进行编译
sudo make install # 将编译生成的 .a .so 等系列库拷贝到系统目录

make 后结果:

make install 后结果:

构建成功后,会在 /usr/local/include/ 中多出 sw 目录,并且内部包含 redis-plus-plus 的一系列头文件;

会在 /usr/local/lib/ 中多出一系列 libredis 库文件.

五、编写运行helloworld

创建代码目录:

编写 hello.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <sw/redis++/redis++.h>

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;

int main() {
    // 创建 Redis 对象的时候,需要在构造函数中指定 redis 服务器地址和端口;
    sw::redis::Redis redis("tcp://127.0.0.1:6379");

    // 使用 ping 方法,让客户端给服务器发送了一个 PING,然后服务器就会返回一个 PONG,通过返回值获取的
    string result = redis.ping();
    cout << result << endl;
}

编写 makefile 文件:

hello:hello.cpp
    g++ -std=c++17 -o $@ $^ /usr/local/lib/libredis++.a /usr/lib/x86_64-linux-gnu/libhiredis.a -pthread

    # /usr/local/lib/libredis++.a               redis自己的静态库
    # /usr/lib/x86_64-linux-gnu/libhiredis.a    hiredis的静态库
    # -pthread                                    线程库

.PHONY:clean
clean:
    rm hello

编译运行:

六、redis命令演示

工具文件:

util.hpp 文件:

# pragma once

# include <iostream>
# include <vector>
#include <string>

// 打印容器内元素
template<typename T>
inline void printContainer(const T& container) {
    for(const auto& elem : container) {
        std::cout << elem << std::endl;
    }
}

// 当容器内元素是 pair 类型时,打印容器内元素
template<typename T>
inline void printContainerPair(const T& container) {
    for(const auto& elem : container) {
        std::cout << elem.first << " : " << elem.second << std::endl;
    }
}

// 当容器内元素是 optional 类型时,打印容器内元素
template<typename T>
inline void printContainerOptional(const T& container) {
    for(const auto& elem : container) {
        if(elem) {
            std::cout << elem.value() << std::endl;
        } else {
            std::cout << "元素无效" << std::endl;
        }
    }
}

6.1 通用命令的使用

genetric.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <thread>
#include <sw/redis++/redis++.h>

#include "util.hpp"

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;
using sw::redis::Redis;

// get 和 set 的使用
void test1(Redis& redis) {
    cout << "get 和 set 的使用" << endl;

    // 清空数据库,避免之前残留的数据有干扰
    redis.flushall();

    // 使用 set 设置 key
    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");

    // 使用 get 获取到 key 对应的 value
    auto value1 = redis.get("key1");
    if(value1) {
        cout << "value1 = " << value1.value() << endl;
    } else {
        cout << "当前 key 不存在" << endl;
    }

    auto value2 = redis.get("key2");
    if(value2) {
        cout << "value2 = " << value2.value() << endl;
    } else {
        cout << "当前 key 不存在" << endl;
    }

    auto value3 = redis.get("key3");
    if(value3) {
        cout << "value3 = " << value3.value() << endl;
    } else {
        cout << "当前 key 不存在" << endl;
    }

    auto value4 = redis.get("key4");
    if(value4) {
        cout << "value4 = " << value4.value() << endl;
    } else {
        cout << "当前 key 不存在" << endl;
    }
}

// exists 的使用
void test2(Redis& redis) {
    cout << "exists" << endl;

    redis.flushall();

    redis.set("key", "111");
    redis.set("key3", "111");

    auto ret = redis.exists("key");
    cout << ret << endl;

    ret = redis.exists("key2");
    cout << ret << endl;

    ret = redis.exists({"key1", "key2", "key3"});
    cout << ret << endl;
}

// del 的使用
void test3(Redis& redis) {
    cout << "del" << endl;
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");

    vector<string> input{"key1", "key2", "key3"};
    auto ret = redis.del(input.begin(), input.end());
    cout << ret << endl;

    ret = redis.exists({"key1", "key2"});
    cout << ret << endl;
}

// keys 的使用
void test4(Redis& redis) {
    cout << "keys" << endl;
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");
    redis.set("key4", "444");
    redis.set("key5", "555");
    redis.set("key6", "666");

    // keys 的第二个参数是一个“插入迭代器”,咱们需要先准备好一个保存结果的容器
    // 接下来再创建一个插入迭代器指向容器的位置. 就可以把 keys 获取到的结果依次通过刚才的插入迭代器插入到容器的指定位置中了.
    vector<string> result;
    auto it = std::back_inserter(result);
    redis.keys("*", it);
    printContainer(result);
}

void test5(Redis& redis) {
    using namespace std::chrono_literals;

    std::cout << "expire and ttl" << std::endl;
    redis.flushall();

    redis.set("key", "111");
    // 10s => std::chrono::seconds(10)
    redis.expire("key", 10s);

    std::this_thread::sleep_for(3s);

    auto time = redis.ttl("key");
    std::cout << time << std::endl;
}

void test6(sw::redis::Redis& redis) {
    std::cout << "type" << std::endl;
    redis.flushall();

    redis.set("key", "111");
    string result = redis.type("key");
    std::cout << "key: " << result << std::endl;

    redis.lpush("key2", "111");
    result = redis.type("key2");
    std::cout << "key2: " << result << std::endl;

    redis.hset("key3", "aaa", "111");
    result = redis.type("key3");
    std::cout << "key3: " << result << std::endl;

    redis.sadd("key4", "aaa");
    result = redis.type("key4");
    std::cout << "key4: " << result << std::endl;

    redis.zadd("key5", "吕布", 99);
    result = redis.type("key5");
    std::cout << "key5: " << result << std::endl;
}

int main() {
    Redis redis("tcp://127.0.0.1:6379");
    
    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    // test5(redis);
    test6(redis);
}

get 和 set:test1()结果:

exists:test2()结果:

del:test3()结果:

keys:test4()结果:

expire and ttl:test5()结果:

type:test6()结果:

6.2 string的使用

string.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <thread>

#include <sw/redis++/redis++.h>
#include "util.hpp"

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;

using sw::redis::Redis;

using namespace std::chrono_literals;

void test1(Redis& redis) {
    std::cout << "get 和 set" << std::endl;
    redis.flushall();

    redis.set("key", "111");
    auto value = redis.get("key");
    if (value) {
        std::cout << "value: " << value.value() << std::endl;
    }

    redis.set("key", "222");
    value = redis.get("key");
    if (value) {
        std::cout << "value: " << value.value() << std::endl;
    }
}

void test2(Redis& redis) {
    std::cout << "set 带有超时时间" << std::endl;
    redis.flushall();

    redis.set("key", "111", 10s);

    std::this_thread::sleep_for(3s);

    long long time = redis.ttl("key");
    std::cout << "time: " << time << std::endl;
}

void test3(Redis& redis) {
    std::cout << "set NX 和 XX" << std::endl;
    redis.flushall();

    redis.set("key", "111");

    // set 的重载版本中, 没有单独提供 NX 和 XX 的版本, 必须搭配过期时间的版本来使用. 
    redis.set("key", "222", 0s, sw::redis::UpdateType::EXIST);

    auto value = redis.get("key");
    if (value) {
        std::cout << "value: " << value.value() << std::endl;
    } else {
        std::cout << "key 不存在!" << std::endl;
    }
}

void test4(Redis& redis) {
    std::cout << "mset" << std::endl;

    redis.flushall();

    // 第一种写法, 使用初始化列表描述多个键值对
    // redis.mset({ std::make_pair("key1", "111"), std::make_pair("key2", "222"), std::make_pair("key3", "333") });

    // 第二种写法, 可以把多个键值对提前组织到容器中. 以迭代器的形式告诉 mset
    vector<std::pair<string, string>> keys = {
        {"key1", "111"},
        {"key2", "222"},
        {"key3", "333"}
    };
    redis.mset(keys.begin(), keys.end());

    auto value = redis.get("key1");
    if (value) {
        std::cout << "value: " << value.value() << std::endl;
    }

    value = redis.get("key2");
    if (value) {
        std::cout << "value: " << value.value() << std::endl;
    }

    value = redis.get("key3");
    if (value) {
        std::cout << "value: " << value.value() << std::endl;
    }
}

void test5(Redis& redis) {
    std::cout << "mget" << std::endl;
    redis.flushall();

    vector<std::pair<string, string>> keys = {
        {"key1", "111"},
        {"key2", "222"},
        {"key3", "333"}
    };
    redis.mset(keys.begin(), keys.end());

    vector<sw::redis::OptionalString> result;
    auto it = std::back_inserter(result);
    redis.mget({"key1", "key2", "key3", "key4"}, it);

    printContainerOptional(result);
}

void test6(Redis& redis) {
    std::cout << "getrange 和 setrange" << std::endl;
    redis.flushall();

    redis.set("key", "abcdefghijk");

    string result = redis.getrange("key", 2, 5);
    std::cout << "result: " << result << std::endl;

    redis.setrange("key", 2, "xyz");

    auto value = redis.get("key");
    std::cout << "value: " << value.value() << std::endl;
}

void test7(Redis& redis) {
    std::cout << "incr 和 decr" << std::endl;
    redis.flushall();

    redis.set("key", "100");

    long long result = redis.incr("key");
    std::cout << "result: " << result << std::endl;

    auto value = redis.get("key");
    std::cout << "value: " << value.value() << std::endl;

    result = redis.decr("key");
    std::cout << "result: " << result << std::endl;

    value = redis.get("key");
    std::cout << "value: " << value.value() << std::endl;
}

int main() {
    Redis redis("tcp://127.0.0.1:6379");

    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    // test5(redis);
    // test6(redis);
    test7(redis);
    
    return 0;
}

get 和 set:test1()结果:

set 带有超时时间:test2()结果:

set NX 和 XX:test3()结果:

mset 带有超时时间:test4()结果:

mget 带有超时时间:test5()结果:

getrange 和 setrange 带有超时时间:test6()结果:

incr 和 dec 带有超时时间:test7()结果:

6.3 list的使用

list.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <thread>
#include <chrono>
#include <sw/redis++/redis++.h>
#include "util.hpp"

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;
using sw::redis::Redis;

using namespace std::chrono_literals;

void test1(Redis& redis) {
    std::cout << "lpush 和 lrange" << std::endl;
    redis.flushall();

    // 插入单个元素
    redis.lpush("key", "111");

    // 插入一组元素, 基于初始化列表
    redis.lpush("key", {"222", "333", "444"});

    // 插入一组元素, 基于迭代器
    vector<string> values = {"555", "666", "777"};
    redis.lpush("key", values.begin(), values.end());

    // lrange 获取到列表中的元素
    vector<string> results;
    auto it = std::back_inserter(results);
    redis.lrange("key", 0, -1, it);

    printContainer(results);
}

void test2(Redis& redis) {
    std::cout << "rpush" << std::endl;
    redis.flushall();

    // 插入单个元素
    redis.rpush("key", "111");

    // 插入多个元素, 基于初始化列表
    redis.rpush("key", {"222", "333", "444"});

    // 插入多个元素, 基于容器
    vector<string> values = {"555", "666", "777"};
    redis.rpush("key", values.begin(), values.end());

    // 使用 lrange 获取元素
    vector<string> results;
    auto it = std::back_inserter(results);
    redis.lrange("key", 0, -1, it);

    printContainer(results);
}

void test3(Redis& redis) {
    std::cout << "lpop 和 rpop" << std::endl;
    redis.flushall();

    // 构造一个 list
    redis.rpush("key", {"1", "2", "3", "4"});

    auto result = redis.lpop("key");
    if (result) {
        std::cout << "lpop: " << result.value() << std::endl;
    }

    result = redis.rpop("key");
    if (result) {
        std::cout << "rpop: " << result.value() << std::endl;
    }
}

void test4(Redis& redis) {
    using namespace std::chrono_literals;
    std::cout << "blpop" << std::endl;
    redis.flushall();

    auto result = redis.blpop({"key", "key2", "key3"}, 10s);
    if (result) {
        std::cout << "key:" << result->first << std::endl;
        std::cout << "elem:" << result->second << std::endl;
    } else {
        std::cout << "result 无效!" << std::endl;
    }
}

void test5(Redis& redis) {
    std::cout << "llen" << std::endl;
    redis.flushall();

    redis.lpush("key", {"111", "222", "333", "444"});
    long long len = redis.llen("key");
    std::cout << "len: " << len << std::endl;
}

int main() {
    Redis redis("tcp://127.0.0.1:6379");
    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    test5(redis);
    return 0;
}

lpush 和 lrange:test1()结果:

rpush:test2()结果:

lpop 和 rpo:test3()结果:

blpop:test4()结果:

llen:test5()结果:

6.4 set的使用

set.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <unordered_map>
#include <sw/redis++/redis++.h>

#include "util.hpp"

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;
using std::set;

using sw::redis::Redis;

void test1(Redis& redis) {
    std::cout << "sadd 和 smembers" << std::endl;
    redis.flushall();

    // 一次添加一个元素
    redis.sadd("key", "111");

    // 一次添加多个元素(使用初始化列表)
    redis.sadd("key", {"222", "333", "444"});

    // 一次添加多个元素(使用迭代器)
    set<string> elems = {"555", "666", "777"};
    redis.sadd("key", elems.begin(), elems.end());

    // 获取到上述元素
    // 此处用来保存 smembers 的结果, 使用 set 可能更合适. 
    vector<string> result;
    // auto it = std::back_inserter(result);
    // 由于此处 set 里的元素顺序是固定的. 指定一个 result.end() 或者 result.begin() 或者其他位置的迭代器, 都无所谓~~
    auto it = std::inserter(result, result.end());
    redis.smembers("key", it);

    printContainer(result);
}

void test2(Redis& redis) {
    std::cout << "sismember" << std::endl;
    redis.flushall();

    redis.sadd("key", {"111", "222", "333", "444"});

    bool result = redis.sismember("key", "555");
    std::cout << "result: " << result << std::endl;
}

void test3(Redis& redis) {
    std::cout << "scard" << std::endl;
    redis.flushall();

    redis.sadd("key", {"111", "222", "333"});
    long long result = redis.scard("key");
    std::cout << "result: " << result << std::endl;
}

void test4(Redis& redis) {
    std::cout << "spop" << std::endl;
    redis.flushall();

    redis.sadd("key", {"111", "222", "333", "444"});
    auto result = redis.spop("key");
    if (result) {
        std::cout << "result: " << result.value() << std::endl;
    } else {
        std::cout << "result 无效!" << std::endl;
    }
}

void test5(Redis& redis) {
    std::cout << "sinter" << std::endl;
    redis.flushall();

    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"111", "222", "444"});

    set<string> result;
    auto it = std::inserter(result, result.end());
    redis.sinter({"key1", "key2"}, it);

    printContainer(result);
}

void test6(Redis& redis) {
    std::cout << "sinterstore" << std::endl;
    redis.flushall();

    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"111", "222", "444"});

    long long len = redis.sinterstore("key3", {"key1", "key2"});
    std::cout << "len: " << len << std::endl;

    set<string> result;
    auto it = std::inserter(result, result.end());
    redis.smembers("key3", it);

    printContainer(result);
}

int main() {
    Redis redis("tcp://127.0.0.1:6379");
    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    // test5(redis);
    test6(redis);
    return 0;
}

sadd 和 smembers:test1()结果:

sismember:test2()结果:

scard:test3()结果:

spop:test4()结果:

sinter:test5()结果:

sinterstore:test6()结果:

6.5 hash的使用

hash.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <sw/redis++/redis++.h>

#include "util.hpp"

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;

using sw::redis::Redis;

void test1(Redis& redis) {
    std::cout << "hset 和 hget" << std::endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", std::make_pair("f2", "222"));
    // hset 能够一次性插入多个 field-value 对!!
    redis.hset("key", {
        std::make_pair("f3", "333"),
        std::make_pair("f4", "444")
    });
    vector<std::pair<string, string>> fields = {
        std::make_pair("f5", "555"),
        std::make_pair("f6", "666")
    };
    redis.hset("key", fields.begin(), fields.end());

    auto result = redis.hget("key", "f3");
    if (result) {
        std::cout << "result: " << result.value() << std::endl;
    } else {
        std::cout << "result 无效!" << std::endl;
    }
}

void test2(Redis& redis) {
    std::cout << "hexits" << std::endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", "f2", "222");
    redis.hset("key", "f3", "333");

    bool result = redis.hexists("key", "f4");
    std::cout << "result: " << result << std::endl;
}

void test3(Redis& redis) {
    std::cout << "hdel" << std::endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", "f2", "222");
    redis.hset("key", "f3", "333");

    long long result = redis.hdel("key", "f1");
    std::cout << "result: " << result << std::endl;

    result = redis.hdel("key", {"f2", "f3"});
    std::cout << "result: " << result << std::endl;

    long long len = redis.hlen("key");
    std::cout << "len: " << len << std::endl;
}

void test4(Redis& redis) {
    std::cout << "hkeys 和 hvals" << std::endl;
    redis.flushall();

    redis.hset("key", "f1", "111");
    redis.hset("key", "f2", "222");
    redis.hset("key", "f3", "333");

    vector<string> fields;
    auto itFields = std::back_inserter(fields);
    redis.hkeys("key", itFields);
    printContainer(fields);

    vector<string> values;
    auto itValues = std::back_inserter(values);
    redis.hvals("key", itValues);
    printContainer(values);
}

void test5(Redis& redis) {
    std::cout << "hmget 和 hmset" << std::endl;
    redis.flushall();

    redis.hmset("key", {
        std::make_pair("f1", "111"),
        std::make_pair("f2", "222"),
        std::make_pair("f3", "333")
    });

    vector<std::pair<string, string>> pairs = {
        std::make_pair("f4", "444"),
        std::make_pair("f5", "555"),
        std::make_pair("f6", "666")
    };
    redis.hmset("key", pairs.begin(), pairs.end());

    vector<string> values;
    auto it = std::back_inserter(values);
    redis.hmget("key", {"f1", "f2", "f3"}, it);
    printContainer(values);
}

int main() {
    Redis redis("tcp://127.0.0.1:6379");
    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    test5(redis);
    return 0;
}

hset 和 hget:test1()结果:

hexits:test2()结果:

hdel:test3()结果:

hkeys 和 hvals:test4()结果:

hmget 和 hmset:test5()结果:

6.6 zset的使用

zset.cpp 文件:

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <sw/redis++/redis++.h>

#include "util.hpp"

using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::unordered_map;

using sw::redis::Redis;

void test1(Redis& redis) {
    std::cout << "zadd 和 zrange" << std::endl;
    redis.flushall();

    redis.zadd("key", "吕布", 99);
    redis.zadd("key", {
        std::make_pair("赵云", 98),
        std::make_pair("典韦", 97)
    });
    vector<std::pair<string, double>> members = {
        std::make_pair("关羽", 95),
        std::make_pair("张飞", 93)
    };
    redis.zadd("key", members.begin(), members.end());

    // zrange 支持两种主要的风格:
    // 1. 只查询 member, 不带 score
    // 2. 查询 member 同时带 score
    // 关键就是看插入迭代器指向的容器的类型. 
    // 指向的容器只是包含一个 string, 就是只查询 member
    // 指向的容器包含的是一个 pair, 里面有 string 和 double, 就是查询 member 同时带有 score
    vector<string> memberResults;
    auto it = std::back_inserter(memberResults);
    redis.zrange("key", 0, -1, it);
    printContainer(memberResults);

    vector<std::pair<string, double>> membersWithScore;
    auto it2 = std::back_inserter(membersWithScore);
    redis.zrange("key", 0, -1, it2);
    printContainerPair(membersWithScore);
}

void test2(Redis& redis) {
    std::cout << "zcard" << std::endl;
    redis.flushall();

    redis.zadd("key", "zhangsan", 90);
    redis.zadd("key", "lisi", 91);
    redis.zadd("key", "wangwu", 92);
    redis.zadd("key", "zhaoliu", 93);

    long long result = redis.zcard("key");
    std::cout << "result: " << result << std::endl;
}

void test3(Redis& redis) {
    std::cout << "zrem" << std::endl;
    redis.flushall();

    redis.zadd("key", "zhangsan", 90);
    redis.zadd("key", "lisi", 91);
    redis.zadd("key", "wangwu", 92);
    redis.zadd("key", "zhaoliu", 93);

    redis.zrem("key", "zhangsan");

    long long result = redis.zcard("key");
    std::cout << "result: " << result << std::endl;
}

void test4(Redis& redis) {
    std::cout << "zscore" << std::endl;
    redis.flushall();

    redis.zadd("key", "zhangsan", 90);
    redis.zadd("key", "lisi", 91);
    redis.zadd("key", "wangwu", 92);
    redis.zadd("key", "zhaoliu", 93);

    auto score = redis.zscore("key", "zhangsan");
    if (score) {
        std::cout << "score: " << score.value() << std::endl;
    } else {
        std::cout << "score 无效" << std::endl;
    }
}

void test5(Redis& redis) {
    std::cout << "zrank" << std::endl;
    redis.flushall();

    redis.zadd("key", "zhangsan", 90);
    redis.zadd("key", "lisi", 91);
    redis.zadd("key", "wangwu", 92);
    redis.zadd("key", "zhaoliu", 93);

    auto rank = redis.zrank("key", "zhaoliu");
    if (rank) {
        std::cout << "rank: " << rank.value() << std::endl;
    } else {
        std::cout << "rank 无效" << std::endl;
    }
}

int main() {
    Redis redis("tcp://127.0.0.1:6379");
    // test1(redis);
    // test2(redis);
    // test3(redis);
    // test4(redis);
    test5(redis);
    return 0;
}

zadd 和 zrange:test1()结果:

zcard:test2()结果:

zrem:test3()结果:

zscore:test4()结果:

zrank:test5()结果:

redis学习打卡🥳

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/959424.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯3518 三国游戏 | 排序

题目传送门 这题的思路很巧妙&#xff0c;需要算出每个事件给三国带来的净贡献&#xff08;即本国士兵量减其他两国士兵量&#xff09;并对其排序&#xff0c;根据贪心的原理累加贡献量直到累加结果不大于0。最后对三国的胜利的最大事件数排序取最值即可。 n int(input()) a …

基于vue框架的的信用社业务管理系统设计与实现4gnx5(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,用户销户,用户存款,用户取款,用户转账,理财类型,投资理财,理财订单,金属类别,贵金属,金属订单,产品分类,保险产品,保险订单 开题报告内容 基于Vue框架的信用社业务管理系统设计与实现开题报告 一、研究背景与意义 随着金融科技的…

自然语言处理——从原理、经典模型到应用

1. 概述 自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是一门借助计算机技术研究人类语言的科学&#xff0c;是人工智能领域的一个分支&#xff0c;旨在让计算机理解、生成和处理人类语言。其核心任务是将非结构化的自然语言转换为机器可以…

微信小程序1.1 微信小程序介绍

1.1 微信小程序介绍 内容提要 1.1 什么是微信小程序 1.2 微信小程序的功能 1.3 微信小程序使用场景 1.4 微信小程序能取代App吗 1.5 微信小程序的发展历程 1.6微信小程序带来的机会

【已解决】OSS配置问题

OSS SDK快速入门_对象存储(OSS)-阿里云帮助中心 阿里官方的SDK使用方法还得配置环境变量access Key、access Secret &#xff0c;我没有配置&#xff0c;仅把access Key和access Secret写到了yml文件读取&#xff0c;结果上传图片时还是出现下面的问题。 [ ERROR ] [ com.s…

SVN客户端使用手册

目录 一、简介 二、SVN的安装与卸载 1. 安装&#xff08;公司内部一般会提供安装包和汉化包&#xff0c;直接到公司内部网盘下载即可&#xff0c;如果找不到可以看下面的教程&#xff09; 2. 查看SVN版本 ​编辑 3. SVN卸载 三、SVN的基本操作 1. 检出 2. 清除认证数据 3. 提交…

Oracle迁移DM数据库

Oracle迁移DM数据库 1 数据准备 2 DTS工具操作步骤 2.1 创建工程 打开DTS迁移工具&#xff0c;点击新建工程&#xff0c;填写好工程信息&#xff0c;如图&#xff1a; 2.2 新建迁移任务 右击迁移>选择新建迁移>填写迁移名称>勾选启用&#xff0c;然后确认下一步…

正则表达式以及Qt中的使用

目录 一、正则表达式 1、基本匹配&#xff1a; 2、元字符&#xff1a; 2.1 .运算符&#xff1a; 2.2 字符集&#xff1a; 2.3 重复次数&#xff1a; 2.4 量词{} 2.5 特征标群() 2.6 或运算符 2.7 \反斜线转码特殊字符 2.8 锚点 3、简写字符 4、零宽度断言 4.1 正…

PyQt6医疗多模态大语言模型(MLLM)实用系统框架构建初探(上.文章部分)

一、引言 1.1 研究背景与意义 在数字化时代,医疗行业正经历着深刻的变革,智能化技术的应用为其带来了前所未有的发展机遇。随着医疗数据的指数级增长,传统的医疗诊断和治疗方式逐渐难以满足现代医疗的需求。据统计,全球医疗数据量预计每年以 48% 的速度增长,到 2025 年将…

Java进阶(一)

目录 一.Java注解 什么是注解&#xff1f; 内置注解 元注解 二.对象克隆 什么是对象克隆? 为什么用到对象克隆 三.浅克隆深克隆 一.Java注解 什么是注解&#xff1f; java中注解(Annotation)又称java标注&#xff0c;是一种特殊的注释。 可以添加在包&#xff0c;类&…

Pyecharts之特殊图表的独特展示

在数据可视化的世界里&#xff0c;除了常见的柱状图、折线图、饼图等&#xff0c;还有一些特殊的图表可以为我们带来独特的展示效果&#xff0c;帮助我们以更有趣、更直观的方式呈现数据。Pyecharts 为我们提供了多种特殊图表的绘制功能&#xff0c;本文将介绍象形图、水球图和…

VSCode下EIDE插件开发STM32

VSCode下STM32开发环境搭建 本STM32教程使用vscode的EIDE插件的开发环境&#xff0c;完全免费&#xff0c;有管理代码文件的界面&#xff0c;不需要其它IDE。 视频教程见本人的 VSCodeEIDE开发STM32 安装EIDE插件 Embedded IDE 嵌入式IDE 这个插件可以帮我们管理代码文件&am…

TLF35584 基本介绍

1 概述 1&#xff09;多电压电源芯片&#xff0c;包含6路输出电压。 LDO_Com&#xff1a;低降后调节器 5V/200mA 通信电源。LDO_C &#xff1a;低降后调节器 5V/600mA (TLF35584xxVS1)/3.3 V/600mA (TLF35584xxVS2) uC电源。Volt_Ref &#xff1a;参考电压5.0 V /- 1%/150mA …

操作无法完成,因为文件已经在Electronic Team Virtual Serial Port Driver Service中打开

报错 操作无法完成,因为文件已经在Electronic Team Virtual Serial Port Driver Service中打开 现象 这个exe文件无法删除 解决办法 按下WinR, 找到Electronic Team Virtual Serial Port Driver Service,右击停止. 再次尝试删除,发现这个exe文件成功删除!

24_游戏启动逻辑梳理总结

首先这个项目从游戏根入口GameRoot.cs的初始化开始 分为 服务层初始化Svc.cs 与 业务系统层初始化Sys.cs 而服务层 分为 资源加载服务层ResSvc.cs 与 音乐播放服务层AudioSvc.cs 而在 资源加载服务层ResSvc.cs中 初始化了 名字的 配置文件 而音乐播放服务层AudioSvc.cs 暂时没…

125周六复盘 (167)帧数优化

1、关键词&#xff1a;帧数优化 2、上午收到一个平台的邮件&#xff0c;说欧盟DSA法案的事&#xff0c;然后联系客服解决问题。 3、近期测试中发现某些关卡帧数奇低&#xff0c;很是异常。 然后今天用了一天时间来排查、解决问题。 通过测试工具发现游戏逻辑部分耗时太多&…

使用 OpenCV 和 Python 轻松实现人脸检测

目录 一、准备工作 二、加载人脸检测模型 三、读取图像并进行人脸检测 四、处理视频中的人脸检测 五、优化人脸检测效果 六、总结 在人工智能和计算机视觉领域,人脸检测是一项非常基础且重要的技术。通过人脸检测,我们可以在图像或视频中识别并定位人脸,进而进行后续的…

Windows电脑安装USB Redirector并实现内外网跨网USB共享通信访问

文章目录 前言1. 安装下载软件1.1 内网安装使用USB Redirector1.2 下载安装cpolar内网穿透 2. 完成USB Redirector服务端和客户端映射连接3. 设置固定的公网地址 前言 我们每天都在与各种智能设备打交道&#xff0c;从手机到电脑&#xff0c;再到各种外设&#xff0c;它们已经…

20250122-正则表达式

1. 正则标记 表示一位字符&#xff1a;\\ 表示指定的一位字符&#xff1a;x 表示任意的一位字符&#xff1a;. 表示任意一位数字&#xff1a;\d 表示任意一位非数字&#xff1a;\D 表示任意一个字母&#xff1a;[a-zA-Z]&#xff08;大写或小写&#xff09; 表示任意一个…

RDMA 工作原理 | 支持 RDMA 的网络协议

注&#xff1a;本文为 “RDMA” 相关文章合辑。 英文引文机翻未校。 图片清晰度受引文所限。 Introduction to Remote Direct Memory Access (RDMA) Written by: Dotan Barak on March 31, 2014.on February 13, 2015. What is RDMA? 什么是 RDMA&#xff1f; Direct me…