redis客户端安装与实现C++版本

resp

redis客户端使用一个叫做RESP的协议,这里是redis关于此协议的官方界面链接:官网

  • 优点:简单好实现,快速进行解析,肉眼可读。
  • 传输层这里基于TCP,但和TCP又没有强耦合。
  • 请求和响应的模型是一问一答的形式。
  • 客户端给服务器发送的是bulk string形式的redis命令,服务器的返回值取决于command的形式,不同的command,返回值不一样。

redis-plus-plus

编写redis客户端服务器,主要使用的是redis-plus-plus库,如果打不开,可以使用watti:redis-plus-plus

  • 如果想要安装redis-plus-plus的话,需要先安装hiredis,因为redis-plus-plus是依赖hiredis的
    hiredis可以通过源码安装:
  • 也可以通过包管理器安装:
bash 复制代码
apt install libhiredis-dev #Ubuntu下的安装方式
  • 接下来安装redis-plus-plus本体:
bash 复制代码
git clone https://github.com/sewenew/redis-plus-plus.git

cd redis-plus-plus

mkdir build

cd build

cmake ..

make

sudo make install #把库拷贝到系统中

cd ..
  • tip:如果没有办法clone,提示GnuTLS recv error (-110): The TLS connection was non-properly terminated,可以使用以下命令。
bash 复制代码
apt-get install gnutls-bin
git config --global http.sslVerify false
git config --global http.postBuffer 1048576000
  • 使用redis-plus-plus链接到redis服务器。
    首先需要找到redis++的头文件和静态库文件的位置。

    使用ping命令测试一下连通性。
cpp 复制代码
#include<sw/redis++/redis++.h>
#include<string>
#include<iostream>

using std::cout;
using std::endl;
using std::string;

int main()
{
    //创建一个redis对象
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    //通过ping让客户端给服务器发一个ping,然后服务器返回一个pong
    string result=redis.ping();
    cout<<result<<endl;
    return 0;
}
  • 使用makefile编译文件
cpp 复制代码
helloworld:helloworld.cc
	g++ -o $@ $^ -std=c++17 /usr/local/lib/libredis++.a /usr/lib/x86_64-linux-gnu/libhiredis.a -pthread
.PHONY:clean
clean:
	rm -f helloworld
#请根据自己的情况选择库路径

这样就跑通了

通用命令

get和set

set

StringView和c++里的string很像,但不可写,所以效率比string高。

OptionalString可以表示非法值/无效值,如果直接使用string来表示,是不太方便表示nil这个值的,如果使用string*来表示,可以通过返回nullptr表示nil,但又涉及到内存归谁管的问题。

cpp 复制代码
#include<sw/redis++/redis++.h>
#include<string>
#include<iostream>

using std::cout;
using std::endl;
using std::string;

void test(sw::redis::Redis& redis)
{
    //清空数据库
    redis.flushall();
    //使用set指令
    redis.set("key1","value1");
    redis.set("key2","value2");
    redis.set("key3","value3");
}

int main()
{
    //创建一个redis对象
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    test(redis);
    return 0;
}

get

cpp 复制代码
#include<sw/redis++/redis++.h>
#include<string>
#include<iostream>

using std::cout;
using std::endl;
using std::string;

void test(sw::redis::Redis& redis)
{
    //清空数据库
    redis.flushall();
    //使用set指令
    redis.set("key1","value1");
    redis.set("key2","value2");
    redis.set("key3","value3");

    //使用get指令,找存在的key
    auto value1=redis.get("key1");
    cout<<"value1="<<value1.value()<<endl;
    auto value2=redis.get("key2");
    cout<<"value2="<<value2.value()<<endl;
    auto value3=redis.get("key3");
    cout<<"value3="<<value3.value()<<endl;
    //找不存在的key
    auto value4=redis.get("key4");
    cout<<"value4="<<value4.value()<<endl;
}

int main()
{
    //创建一个redis对象
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    test(redis);
    return 0;
}

运行后:key1到key3都是正常的,但key4抛出异常状态,因为key4不存在,value4其实是optional的非法状态,对于非法状态的optional进行取值,就会抛出异常,如果我们想处理这种情况,可以使用try-catch,或者访问value之前判定一下。

exists和del

exists :判断一个元素在不在数据库里面,返回值是long long类型,表示存在的参数类型。

cpp 复制代码
void test1(sw::redis::Redis& redis)
{
    //清空数据库
    redis.flushall();
    //使用exists
    redis.set("key","value");
    //如果元素存在
    auto ret=redis.exists("key");
    cout<<ret<<endl;
    //如果元素不存在
    ret=redis.exists("key1");
    cout<<ret<<endl;
}

int main()
{
    //创建一个redis对象
    sw::redis::Redis redis("tcp://127.0.0.1:6379");
    test1(redis);
    return 0;
}

如果我们想判定多个key,可以使用列表。

cpp 复制代码
void test1(sw::redis::Redis& redis)
{
    //清空数据库
    redis.flushall();
    //使用exists
    redis.set("key","value");
    redis.set("key1","value1");
    redis.set("key2","value2");
    ret=redis.exists({"key1","key2","key3"});
    cout<<ret<<endl;
}


del :用于删除元素,这里也是可以使用列表同时删除多个key的,返回值表示删除的个数。

cpp 复制代码
void test1(sw::redis::Redis& redis)
{
    //清空数据库
    redis.flushall();
    //使用exists
    redis.set("key","value");
    redis.set("key1","value1");
    redis.set("key2","value2");
    auto ret=redis.exists({"key1","key2","key3"});
    cout<<"exists"<<ret<<endl;
    ret=redis.del("key");
    cout<<"del"<<ret<<endl;
    ret=redis.exists({"key1","key2","key"});
    cout<<"exists"<<ret<<endl;
    ret=redis.del({"key1","key2"});
    cout<<"del"<<ret<<endl;
    ret=redis.exists({"key1","key2","key"});
    cout<<"exists"<<ret<<endl;
}

keys

keys是用于查询库里的多个值。

keys的第一个参数是模式,第二个参数是一个插入迭代器,所以我们需要事先准备一个保存结果的容器,接下来再创建一个插入迭代器指向容器的位置。

cpp 复制代码
void test2(sw::redis::Redis& redis)
{
    redis.flushall();
    redis.set("key1","111");
    redis.set("key2","222");
    redis.set("key3","333");
    redis.set("key4","444");

    vector<string> result;
    auto it=std::back_inserter(result);
    redis.keys("*",it);
    for(auto x:result)
    {
        cout<<x<<" ";
    }
    cout<<endl;
}

我们知道迭代器一般有五种,输入迭代器,输出迭代器,单项迭代器,双向迭代器和随机访问迭代器,插入迭代器本质上就是一种输出迭代器,主要的功能就是把另外一个迭代器赋值给插入迭代器。

另外一个迭代器赋值给插入迭代器的作用是:比如说插入迭代器back_insert_iterator是it1,普通迭代器是it2,将it2赋值给it1后,相当于就是获取it2指向的元素,然后按照it当前的位置和动作将元素插入(比如说,插入迭代器是back_insert_iterator的话,那么就是执行将it2指向的元素插入it1指向的容器末尾,相当于调用一次pushback),这样可以实现解耦合的目标(keys和c++迭代器的解耦合)

ttl和expire

expire :给一个key设置过期时间,第二个参数chrono::seconds主要是为了让看代码的人更清楚单位。

cpp 复制代码
void test3(sw::redis::Redis& redis)
{
    redis.flushall();
    redis.set("key1","111");
    redis.expire("key1",std::chrono::seconds(3));
    auto ret=redis.exists("key1");
    cout<<"exists"<<ret<<endl;
    sleep(4);
    ret=redis.exists("key1");
    cout<<"exists"<<ret<<endl;
}

c++标准库里也提供了一个函数叫sleep_for,因为不同的操作系统里提供了不同的sleep函数,所以使用标准库的函数可以有更好的兼容性。
ttl :用来看过期时间。

cpp 复制代码
void test3(sw::redis::Redis& redis)
{
    redis.flushall();
    redis.set("key1","111");
    redis.expire("key1",std::chrono::seconds(3));
    auto ret=redis.ttl("key1");
    cout<<"ttl"<<ret<<endl;
    sleep(2);
    ret=redis.ttl("key1");
    cout<<"ttl"<<ret<<endl;
}

type

用于获取一个key对应的value的类型。

cpp 复制代码
void test4(sw::redis::Redis& redis)
{
    redis.flushall();
    redis.set("key1","111");
    auto ret=redis.type("key1");
    cout<<"type:"<<ret<<endl;
}
相关推荐
Yiyaoshujuku2 小时前
疾病的发病率、发病人数、患病率、患病人数、死亡率、死亡人数查询网站及数据库
数据库·人工智能·算法
不想写bug呀2 小时前
Redis总结
数据库·redis·缓存
Neolnfra2 小时前
数据库提权实战指南
数据库·数据库安全
DarkAthena2 小时前
【GaussDB】合入原生PG的PR来修复CVE-2025-1094漏洞后产生的严重隐患
数据库·漏洞·gaussdb
予枫的编程笔记2 小时前
【Redis核心原理篇3】Redis 主从复制:数据同步的底层逻辑与实践
数据库·redis·缓存
pp起床2 小时前
【苍穹外卖】Day03 菜品管理
java·数据库·mybatis
321.。2 小时前
深入理解 Linux 线程封装:从 pthread 到 C++ 面向对象实现
linux·开发语言·c++
EmbedLinX2 小时前
Linux内核之文件系统:从VFS到实际存储的运作机制
linux·服务器·c语言·c++
2301_803554523 小时前
Qt中connect()实现信号与槽连接这一核心机制
java·数据库·qt