C++客户端对Redis的使用

📅 2026/7/21 10:38:00 👁️ 阅读次数 📝 编程学习
C++客户端对Redis的使用
Redis头文件存在的路径:
/usr/local/include/sw/redis++
Redis库存在的路径:

/usr/local/lib/libredis++.a

检验连接Redis服务是否正常:
#include<iostream> #include<vector> #include<string> #include<unordered_map> #include<sw/redis++.h> using std::cout; using std::endl; using std::vector; using std::string; using unordered_map; int main() { //创建redis对象,tcp://为固定格式,tcp可换成其它支持的连接层协议,IP:port sw::redis::Redis redis("tcp://127.0.0.1:6379"); //检测是否连接成功了 string result = redis.ping(); cout<<result<<endl; return 0; }

在编译含有redis对象的代码时,需要包含三种库文件

1)redis++自己的静态库文件

2)hiredis的静态库,因为redis++依赖了hiredis

3)线程库,因为redis++依赖了线程库get

Redis的通用命令的使用

1.get/set 2.exists 3.del 4.keys 5.expire/ttl 6.type

1.get/set
#include<string> #include<unordered_map> #include<sw/redis++/redis++.h> using std::cout; using std::endl; void test(sw::redis::Redis& redis) { //清空数据库,避免被之前的数据干扰 redis.flushall(); //设置key val redis.set("key1",111"); redis.set("key2",222"); redis.set("key3",333"); //获取val值 auto value1 = redis.get("key1"); cout<<value1.value()<<endl; auto value2 = redis.get("key2"); cout<<value2.value()<<endl; auto value3 = redis.get("key3"); cout<<value3.value()<<endl; auto value4 = redis.get("key4"); cout<<value4.value()<<endl; } int main() { sw::redis::Redis redis("tcp://127.0.0.1:6379"); test(redis); return 0; }

这里面运用了StringView这样的类型(是在sw::redis命名空间里面的)

std::string是可以修改的,StringView是只读的,因为是只读的所以可以做很多优化工作,效率比std::string更高

在C++17中也提供了std::string_view类型,但为了向前兼容,所以Redis选择自己实现了一份

get函数的返回值为Optional,此处的Optional表示非法值/无效值,该类的存在为了解决返回值为nil的情况,std::string表示空类型并不方便,std::string*可以表示,但是返回指针又涉及到,内存归谁管,可能会引入不必要的麻烦,所以Redis自己实现了Optional专门为了解决这种情况

C++14版本引入了Optional类型,但为了向前兼容,所以Redis自己实现了一个Optional

Optional可以当作元素的容器

对于key4没有设置,所以对于非法状态optional,进行取值操作,就会抛出异常,也就是触发了SIGABRT信号

处理方式:

1)要么try catch,不推荐,因为这样会出现执行流跳跃的问题

2)在使用之前进行提前判定,举个例子:

#include<string> #include<unordered_map> #include<sw/redis++/redis++.h> using std::cout; using std::endl; void test(sw::redis::Redis& redis) { //清空数据库,避免被之前的数据干扰 redis.flushall(); //设置key val redis.set("key1",111"); redis.set("key2",222"); redis.set("key3",333"); //获取val值 auto value1 = redis.get("key1"); if(value1) cout<<value1.value()<<endl; auto value2 = redis.get("key2"); if(value2) cout<<value2.value()<<endl; auto value3 = redis.get("key3"); if(value3 )cout<<value3.value()<<endl; auto value4 = redis.get("key4"); if(value4) cout<<value4.value()<<endl; } int main() { sw::redis::Redis redis("tcp://127.0.0.1:6379"); test(redis); return 0; }
EXISTS

举个例子:

#include<iostream> #include<sw/redis++/redis++.h> using std::cout; using std::endl; void test(sw::redis::Redis& redis) { redis.flushall(); redis.set("key1","111"); //判定key1是否存在 auto ret = redis.exists("key1"); cout<<ret<<endl; //使用初始化列表进行操作,返回值依然是long long类型,返回存在个数 auto retl = redis.exists({"key1","key2","key3"}); } int main() { sw::redis::Redis redis("tcp://127.0.0.1:6379"); test(redis); return 0; }
DEL

返回值:

表示当前删除成功的个数

#include<iostream> #include<sw/redis++/redis++.h> using std::cout; using std::endl; void test(sw::redis::Redis& redis) { redis.flushall(); redis.set("key1","111"); //判定key1是否存在 auto ret1 = redis.del("key1"); cout<<ret<<endl; auto ret2 = redis.del({"key1","key2","key3"}); cout<<ret2<<endl; } int main() { sw::redis::Redis redis("tcp://127.0.0.1:6379"); test(redis); return 0; }
KEYS

第一个参数为:遍历规则,*,?等

第二个参数:插入迭代器,指向保存结果的容器

#include<iostream> #include<sw/redis++/redis++.h> #include<string> #include<vector> using std::cout; using std::endl; using std::vector; using std::string; void test(sw::redis::Redis& redis) { 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"); vector<string> result; //构造擦插入迭代器 auto it = std::back_inserter(result); redis.keys("*",it); } int main() { sw::redis::Redis redis("tcp://127.0.0.1:6379"); test(redis); return 0; }
STL五种迭代器类型

1.输入迭代器

2.输出迭代器

3.前向迭代器

4.双向迭代器

5.随机迭代器

随机访问迭代器最大的优势,就在于以O(1)的复杂度快速定位到指定位置,主要依靠内存的随机访问

上述五种迭代器,为什么没有插入迭代器?

插入迭代器,本质上也是属于输出迭代器

1)front_insert_iterator,可以绑定区间的开头,向该位置之前插入

2)back_insert_iterator,可以绑定区间的结尾,向该位置之后插入

3)insert_iterator,可以绑定区间的任意位置,向该位置之前插入

一般不会直接构造出这几个对象,因为比较麻烦,一般会使用一些辅助函数来进行构造,如back_insert_iterator的构造函数std::back_inserter(某容器对象)

实现插入迭代器本质的操作就是赋值,把其它迭代器,赋值给这个插入迭代器,举个例子:
it为插入迭代器,it2为普通迭代器,it = it2,相当于是获取到it2指向的元素,然后把元素按照it当前插入迭代器的位置和动作来进行插入操作,比如it是一个back_insert_iterator,那么就是在赋完值后,调用push_back()函数,来实现尾插。

redis.keys("*",it);这里为什么选择传递迭代器,而不是直接传递容器?

因为这样可以解耦合,可以向任何容器中插入

EXPIRE,TTL

第二个参数还可以传递long long类型,但是不推荐,因为可读性比较差,比如:直接写10,你不知道这个单位是10s还是10ms,默认是s

举个例子:

#include<iostream> #include<sw/redis++/redis++.h> #include<string> #include<vector> //使用系统库休眠函数需要引入的头文件 #include<chrono> #include<thread> using std::cout; using std::endl; using std::vector; using std::string; void test( sw::redis::Redis& redis) { redis.flushall(); //10s为字面值常量 10s == std::chrono::seconds(10); redis.expire("key1",10s); //想直接传递值需要打开命名空间 using namespace std::chrono_literals; //设置休眠时间 std::this_thread::sleep_for(3s) //返回值long long类型 auto time = redis.ttl("key"); cout<<time<<enld; } int main() { sw::redis::Redis redis("tcp:/127.0.0.1"6379"); test(redis); return 0; }
TYPE

#include<iostream> #include<sw/redis++/redis++.h> #include<string> #include<vector> //使用系统库休眠函数需要引入的头文件 #include<chrono> #include<thread> using std::cout; using std::endl; using std::vector; using std::string; void test( sw::redis::Redis& redis) { redis.flushall(); redis.set("key1","111"); if(redis.exists("key1")) { std::string result = redis.type("key1"); cout<<result<<endl; } } int main() { sw::redis::Redis redis("tcp:/127.0.0.1"6379"); test(redis); return 0; }