Redis在C++中的对象封装

背景

在微服务的开发过程中,分布式缓存数据库redis几乎是必然要使用到的,然而redis的储存数据全是string类型的数据,在读取数据和保存数据时,c++没法直接将操作对象进行存储和保存,必须进行转换。我们希望提供一个公共load与save接口完成对象数据到redis数据之间的无缝转换。本文是作者在工程实践的一些经验总结,主要实现目标为提供对象到redis之间的操作接口,使上层应用的调用变得稍微简单一点,数据存储到redis时采用hash表进行存储。

需求梳理

假设我们的数据类为Data,定义如下:

class Data
{
   
public:
	Data(int inkey):key(inkey){
   }
public:
	void load();
	void save();
	
public:
	std::string key;
	int field1;
	int field2;
};

Data的对象通过load接口将对应的key从redis中读到我们的类成员中,通过save接口将自己的成员变量保存到redis中,有了目标之后我们接下来再进行分解,看一下load与save具体应该怎么实现。先看一下伪代码

Data::load()
{
   
	loadfromRedis(key, {
   "field1", "field2"}, field1, field2);
}
Data::save()
{
   
	savetoRedis(key, "field1", field1, "field2", field2);
}

我们希望load调用loadfromRedis函数来实现从redis到对象数据的加载工作,loadfromRedis函数的第一个参数为redis数据库中存储的key,中间大括号括起来的是字段名称,剩下的参数是对象的数据成员;Data的save函数调用savetoRedis函数完成保存动作,第一个参数为key,后面参数依次为字段名称、值。有了大致的方向之后,我们梳理一下需求

  • loadfromRedis(key, {“field1”, “field2”}, field1, field2):
    • 字段名称需要使用初始化列表
    • 字段值为多个成员变量,所以这里需要使用可变参模板,利用模板的类型自动推导将从redis读出来的字符串类型转换为对应的成员变量类型
  • savetoRedis(key, “field1”, field1, “field2”, field2):
    • 除第一个参数外,其他参数需使用可变参模块实现,利用模板的类型自动推导将所有成员变量自动转换为字符串形式进行存储

redis数据加载接口实现

有了上面的分析,我们可以开始编写模板的伪代码了

template<typename ... Args>
void loadfromRedis(const std::string &keys, std::initializer_list<std::string> fields, Args &&... args)
{
   
	std::vector<std::string> values;
	redis.hmget(keys, fields, values);
	toArgs(values.begin(), values.end(), std::forward<Args>(args)...)
}
  • step 1. 先定义一个vector类型的values类存储从redis读出来的value字符串
  • step 2. 使用redis客户端接口hmget从指定key中读取出指定fields的value值,存入values中
  • step 3. 将values的值依次转存到args中

这里需要注意的是可变参模板的参数类型,我这里使用的右值引用&&符作为参数的类型限定符,主要考虑到loadfromRedis这个函数本身并不直接对参数进行处理,而是将可变参数传递到toArgs函数里边进行处理,所以这里的可变参数仅仅只起到代理转发的作用,属于通用型的参数,即可以接受任意类型的参数。模板中的右值引用符&&与非模板函数的右值引用符&&用法有一点区别,模板中的右值引用符&&主要用于定义通用型的参数类型。另外虽然args即可为左值引用也可以为右值引用,但当args的值为右值引用时,args这个变量仍为左值,所以我们在使用args参数时,通过std::forward(args)将args的参数类型保持一致

另外还有一点需要注意,那就是省略参数符…的使用,可以这样使用

fun(args...)
</
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们开始使用 POCO C++ 库来封装 Redis。 首先,我们需要在 C++ 环境安装 Redis C++ 客户端。Redis C++ 客户端是一个 Redis 服务器的 C++ 接口,可以让我们在 C++ 程序使用 Redis 数据库。 安装 Redis C++ 客户端: ``` git clone https://github.com/sewenew/redis-plus-plus.git cd redis-plus-plus mkdir build cd build cmake .. make && make install ``` 接下来,我们可以开始使用 POCO C++ 库来封装 Redis。 我们可以编写一个 RedisClient 类来封装 Redis 客户端接口。下面是 RedisClient 类的头文件: ```c++ #include <string> #include <vector> #include <memory> #include <Poco/Net/StreamSocket.h> #include <redisclient/redisclient.h> class RedisClient { public: RedisClient(const std::string& host, int port, const std::string& password = ""); ~RedisClient(); bool ping(); bool set(const std::string& key, const std::string& value); std::string get(const std::string& key); bool del(const std::string& key); bool exists(const std::string& key); std::vector<std::string> keys(const std::string& pattern); private: std::unique_ptr<RedisClient::Connection> _connection; }; ``` 接下来,我们需要实现 RedisClient 类的每个函数。 首先是构造函数和析构函数: ```c++ RedisClient::RedisClient(const std::string& host, int port, const std::string& password) { _connection = RedisClient::Connection::connect(host, port); if (!password.empty()) { _connection->auth(password); } } RedisClient::~RedisClient() { _connection->disconnect(); } ``` 这个构造函数会建立一个 Redis 连接,并且如果有密码,就会进行身份验证。析构函数会关闭 Redis 连接。 接下来是 ping 函数: ```c++ bool RedisClient::ping() { auto reply = _connection->ping(); return reply->isStatus() && reply->str() == "PONG"; } ``` 这个函数会向 Redis 服务器发送 PING 命令,并检查服务器是否成功响应。 接下来是 set 和 get 函数: ```c++ bool RedisClient::set(const std::string& key, const std::string& value) { auto reply = _connection->set(key, value); return reply->isStatus() && reply->str() == "OK"; } std::string RedisClient::get(const std::string& key) { auto reply = _connection->get(key); return reply->str(); } ``` 这两个函数分别用于设置和获取 Redis 的键值对。 接下来是 del 和 exists 函数: ```c++ bool RedisClient::del(const std::string& key) { auto reply = _connection->del(key); return reply->isInteger() && reply->integer() == 1; } bool RedisClient::exists(const std::string& key) { auto reply = _connection->exists(key); return reply->isInteger() && reply->integer() == 1; } ``` 这两个函数分别用于删除和检查 Redis 的键是否存在。 最后是 keys 函数: ```c++ std::vector<std::string> RedisClient::keys(const std::string& pattern) { auto reply = _connection->keys(pattern); std::vector<std::string> keys; for (const auto& item : reply->toArray()) { keys.push_back(item->str()); } return keys; } ``` 这个函数用于获取与指定模式匹配的所有键。 现在我们已经完成了 RedisClient 类的封装,可以在应用程序使用它了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值