Redis:cpp.redis++通用接口

news/2024/12/21 22:24:25/

Redis:cpp.redis++通用接口

    • redis对象
    • 通用接口
      • set & get
      • exists
      • del
      • flushall
      • keys
      • ttl
      • expire
      • type


本博客讲解redisC++客户端redis-plus-plus,这个版本的客户端,接口和redis原生命令几乎完全一致,博客内部不会详细讲解每个接口的具体功能,因为和redis命令是一样的,而是重点讲解器用法与参数。所有接口可以参考文档:[redis-plus-plus/redis.h]。

redis_6">redis对象

redis的所有操作都基于一个redis对象。

C++文件中写入以下代码:

#include <iostream>
#include <sw/redis++/redis++.h>int main()
{sw::redis::Redis redis("tcp://127.0.0.1:6379");std::string result = redis.ping();std::cout << result << std::endl;return 0;
}

在默认的路径下,redis++.h头文件放在了sw/redis++/目录下,其中sw是库作者的名称缩写。

main函数中,先创建一个Redis对象,其包含在命名空间sw::redis::内部。在创建对象时,要制定ip和端口号,格式如下:

tcp://IP地址:端口

其中redis的默认端口为6379

redis可以使用ping来检测连通性,通过redis.ping(),会返回一个字符串。

随后对代码进行编译:

g++ -o test_redis test.cpp -std=c++17 -l hiredis -l redis++ -l pthread

redis++需要依赖三个库:hiredisredis++pthread

如果运行程序,输出了PONG,那么说明redis是正常可用的。


通用接口

set & get

  • set函数声明如下:
bool set(const StringView &key,const StringView &val,const std::chrono::milliseconds &ttl = std::chrono::milliseconds(0),UpdateType type = UpdateType::ALWAYS);

此处有一个StringView类型,是一个只读的字符串,其效率比std::string更高,不过在C++17中也支持了std::string_view。只需要把它当作一般的std::string也没什么大问题。

函数中,前两位是keyvalue其余的都是缺省参数,所以可以只输入keyvalue

  • get函数声明如下:
OptionalString get(const StringView &key);

get的返回值也很特别,是一个OptionalString类型,这是因为redis中如果查询为空,会返回nil,对于std::string不好表示这样的空,所以使用了OptionalString来处理,一般用auto接收即可。

要注意的是OptionalString不支持operator<<,要通过.value()函数,获取其内部包含的std::string即可。

示例:

#include <iostream>
#include <sw/redis++/redis++.h>int main()
{sw::redis::Redis redis("tcp://127.0.0.1:6379");redis.set("key1", "111");redis.set("key2", "222");auto ret1 = redis.get("key1");std::cout << ret1.value() << std::endl;auto ret2 = redis.get("key2");std::cout << ret2.value() << std::endl;auto ret3 = redis.get("key3");std::cout << ret3.value() << std::endl;return 0;
}

输出结果:

111
222
terminate called after throwing an instance of 'std::bad_optional_access'what():  bad optional access
Aborted (core dumped)

此处由于没有插入key3,所以get时得到的值为nil,最后输出时抛出了异常。

如果要处理这个情况,那要用到OptionalString的另一个特性。OptionalString可以隐式转化为bool类型,如果元素有效则为true,元素无效则为false

输出之前,只需要判断一下返回值是否为true即可:

int main()
{sw::redis::Redis redis("tcp://127.0.0.1:6379");redis.set("key1", "111");redis.set("key2", "222");auto ret1 = redis.get("key1");if (ret1)std::cout << ret1.value() << std::endl;auto ret2 = redis.get("key2");if (ret2)std::cout << ret2.value() << std::endl;auto ret3 = redis.get("key3");if (ret3)std::cout << ret3.value() << std::endl;return 0;
}

exists

  • exists用于检测key是否存在,函数声明如下:
long long exists(const StringView &key);

这个很简单,就是判断一个key是否存在。

但是其为什么要以long long作为返回值?其实exists还有另一个函数重载:

template <typename T>
long long exists(std::initializer_list<T> il);

其接收一个初始化列表,也就是可以同时接收多个key,此时有多少个key存在,就返回多少。

示例:

#include <iostream>
#include <sw/redis++/redis++.h>int main()
{sw::redis::Redis redis("tcp://127.0.0.1:6379");redis.set("key1", "111");redis.set("key2", "222");std::cout << redis.exists("key1") << std::endl;std::cout << redis.exists({"key1", "key2", "key3"}) << std::endl;return 0;
}

输出结果:

1
2

此处要注意,输入的是一个初始化列表(C++11),需要用{}把所有参数先包起来,构成一个初始化列表。


del

  • del用于删除key,函数声明如下:
long long del(const StringView &key);template <typename T>
long long del(std::initializer_list<T> il);

exists一样,支持删除一个或多个key,删除多个时要通过初始化列表。


flushall

  • flushall用于清空整个redis,函数声明如下:
void flushall(bool async = false);

该接口会清空redis内的所有数据,开发环境慎用,一般而言参数直接用默认的false即可。


keys

  • keys用于搜索符合条件的keykeys函数声明如下:
template <typename Output>
void keys(const StringView &pattern, Output output);

keys用于搜索所有符合条件的key,此处第一个参数pattern是匹配模式,output是一个插入迭代器,用于获取符合条件的key,元素类型是字符串,std::string或者StringView

int main()
{sw::redis::Redis redis("tcp://127.0.0.1:6379");redis.flushall();redis.set("key1", "111");redis.set("key2", "222");redis.set("key3", "222");redis.set("key4", "222");std::vector<std::string> result;auto it = std::back_inserter(result);redis.keys("*", it);for (auto& ret : result)std::cout << ret << std::endl;return 0;
}

输出结果:

key3
key2
key1
key4

此处的插入迭代器,是一种专门用于将元素插入到容器中的迭代器,主要有以下三种:

  1. std::front_insert_iterator:在容器头部插入
  2. std::back_insert_iterator:在容器尾部插入
  3. std::insert_iteraotr:在容器任意位置插入

这种迭代器,++--都是无效的,核心是operator=

比如模拟实现一个vector的插入迭代器:

template <typename T>
class InsertIterator {
public:// 构造函数,保存容器的引用和插入位置的迭代器InsertIterator(std::vector<T>& vec, typename std::vector<T>::iterator pos): vec_(vec), pos_(pos) {}// 重载赋值操作符,实现插入逻辑InsertIterator& operator=(const T& value) {pos_ = vec_.insert(pos_, value);return *this;}// 重载前置和后置增加操作符,因为插入操作不改变迭代器位置InsertIterator& operator++() { return *this; }InsertIterator& operator++(int) { return *this; }// 重载解引用操作符,以便可以链式调用InsertIterator& operator*() { return *this; }private:std::vector<T>& vec_;typename std::vector<T>::iterator pos_;
};

operator=内部,调用vector.insert接口,完成元素插入容器的操作,此时pos也会自动指向新的位置。

如果想要获取到容器对应的插入迭代器,可以使用标准库的接口:

std::front_inserter(容器);
std::back_inserter(容器);
std::inserter(容器);

在使用时,如果类似于std::vector这样的容器,提供了头尾删除接口,那么就可以使用front_inserter或者back_inserter这样的插入迭代器,但是像set这种容器,就只能使用inserter了。

这种插入迭代器,可以完成插入与容器的解耦合,redis返回的结果集,可以不用重载各种setvector等容器,而是使用统一的插入迭代器完成。


ttl

  • ttl用于获取key的剩余超时时间,函数声明如下:
long long ttl(const StringView &key);

这个函数结合下一个接口一起展示。


expire

  • expire用于设置超时时间,函数声明如下:
bool expire(const StringView &key, long long timeout);
bool expire(const StringView &key, const std::chrono::seconds &timeout);

expire设置超时时间时,有两种模式,第一个重载的timeoutlong long类型,以秒为单位,也可以使用std::chrono::seconds来控制。

返回值与redis原生的ttl完全一致,如果key不存在返回-2,如果key存在但是没有超时时间返回-1

示例:

#include <iostream>
#include <chrono>#include <sw/redis++/redis++.h>int main()
{sw::redis::Redis redis("tcp://127.0.0.1:6379");redis.flushall();redis.set("key1", "111");redis.set("key2", "222");redis.set("key3", "222");redis.expire("key1", 10);redis.expire("key2", std::chrono::seconds(1));std::cout << redis.ttl("key1") << std::endl;std::cout << redis.ttl("key2") << std::endl;std::cout << redis.ttl("key3") << std::endl;std::cout << redis.ttl("key4") << std::endl;return 0;
}

输出结果:

10
1
-1
-2

type

  • type用于获取key对于的value的类型,函数声明如下:
std::string type(const StringView &key);

其返回值是标准的std::string



http://www.ppmy.cn/news/1536971.html

相关文章

如何用深度神经网络预测潜在消费者

1. 模型架构 本项目采用的是DeepFM模型&#xff0c;其结构结合了FM&#xff08;因子分解机&#xff09;与深度神经网络&#xff08;DNN&#xff09;&#xff0c;实现了低阶与高阶特征交互的有效建模。模型分为以下几层&#xff1a; 1.1 FM部分&#xff08;因子分解机层&#…

C#系统学习路线

分享一个C#程序员的成长学习路线规划&#xff0c;希望能够帮助到想从事C#开发的你。 我一直在想&#xff0c;初学者刚开始学习编程时应该学些什么&#xff1f;学习到什么程度才能找到工作&#xff1f;才能在项目中发现和解决Bug&#xff1f; 我不知道每位初学者在学习编程时是…

SpringBoot 整合 阿里云 OSS图片上传

一、OOS 简介 ‌阿里云OSS&#xff08;Object Storage Service&#xff09;是一种基于云存储的产品&#xff0c;适用于存储和管理各种类型的文件&#xff0c;包括图片、视频、文档等。‌ 阿里云OSS具有高可靠性、高可用性和低成本等优点&#xff0c;因此被广泛应用于各种场景&…

快速区分 GPT-3.5 与 GPT-4

问&#xff1a;鲁迅为什么暴打周树人&#xff1f; GPT3.5回答 各种稀奇古怪的理由 GPT4回答 正确区分鲁迅和周树人是同一个人 国内GPT入口 https://ai-to.cn/url/?ulihaimao

vue3实现登录获取token并自动刷新token进行JWT认证

在《django应用JWT(JSON Web Token)实战》介绍了如何通过django实现JWT&#xff0c;并以一个具体API接口实例的调用来说明JWT如何使用。本文介绍如何通过vue3的前端应用来使用JWT认证调用后端的API接口&#xff0c;实现一下的登录认证获取JWT进行接口认证。 一、账号密码登录获…

【ROS】机器人系统仿真-URDF集成Rviz基本流程

机器人系统仿真&#xff1a;是通过计算机对实体机器人系统进行模拟的技术&#xff0c;在 ROS 中&#xff0c;仿真实现涉及的内容主要有三:对机器人建模(URDF)、创建仿真环境(Gazebo)以及感知环境(Rviz)等系统性实现。 1.URDF URDF可以以一种 XML 的方式描述机器人的部分结构&…

Vue.js 组件开发知识详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

RCE(remote command/code execute)远程命令注入

远程命令注入RCE RCE(remote command/code execute&#xff0c;远程命令执行)漏洞&#xff0c;一般出现这种漏洞&#xff0c;是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口&#xff0c;比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上。一般会给…