简言
1. c++下使用redis的话,hiredis是首选,封装得好,接口简单
2. redis的下载和编译请参考笔者的这篇博客,等待
3. hiredis的编译请参考笔者的这篇博客,等待
4. hiredis有个很大的优点就是可以直接保存,读取结构体,简直不要太爽,不像go语言那种渣渣,只能保存字符串,想保存一个结构体时要把结构体序列化成字符串,比如转成json字符串再保存,太麻烦
代码下载地址
linux版:https://download.csdn.net/download/yzf279533105/11979214
windows版:代码都一样,没时间写哈
接口和结构
我们这里先了解一下hiredis的基本接口,笔者都加了注释
// 连接数据库,只是连接,并未认证,认证可以通过redisCommand执行命令来实现
redisContext *redisConnect(const char *ip, int port);
// 执行命令,注意:redisCommand(),redisCommandArgv() 的返回值其实是 redisReply* 类型
void *redisCommand(redisContext *c, const char *format, ...);
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
//释放资源
void freeReplyObject(void *reply);
void redisFree(redisContext *c);
// 执行命令的结果,注意:只要返回值不为空,就一定要释放,不然会有内存泄漏
typedef struct redisReply
{
/*执行结果的类型*/
int type;
/*执行结果为整数时,存储返回值*/
long long integer;
/*执行结果为string或error时,存储字符串的长度*/
size_t len;
/*执行结果是string或error时,存储返回值*/
char *str;
/*执行结果是数组时,表数组中元素的个数*/
size_t elements;
/*执行结果是数组时,存储元素*/
struct redisReply **element;
} redisReply;
接口封装
注:笔者的感觉是只要支持了struct整体的保存和读取,也就支持了大部分的读写需求,比如string, hash对象,没必要了
对吧,有了保时捷,还要啥自行车,至于list set zset等结构体,等有需求的时候再封装,那时候会更新博客滴
1. 初始化,并连接及认证,成功返回true, 失败返回false
// 初始化
// IP : redisIP地址
// port : redis端口号
// password : redis的认证密码
// timeout : 超时时间
bool Init(string IP, int port, string password, int timeout=5000);
2. 执行命令的接口
// 判断指定key是否存在
bool Exist(string key);
// 设置指定key的值,过期时间单位:秒
int Set(string key, string val, uint32_t expire);
// 获取指定key的值,字符串类型
string Get(string key);
// 设置指定key的值,bin类型
// pVal : 内存地址
// len : 内存大小
// expire : 过期时间,单位:秒
int Set(string key, const char* pVal, int length, uint32_t expire);
// 获取指定key的值,bin类型
int Get(string key, CAutoRedisReply& reply);
实验结果如图(这里只实验了string和结构体的保存,读取)
测试代码如下
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "redis_client.h"
using namespace std;
// 测试结构体,里面有各种类型的字段,但是不能有string类型,必须要能整体拷贝
struct SStruct
{
SStruct()
{
memset(this,0,sizeof(*this));
}
int a;
float b;
char c[20];
char d;
};
int main()
{
// redis连接实例
CRedisClient m_redisClient;
// redis配置,应该写在配置文件中读取,这里只是简单演示
string IP = "192.168.11.177";
int port = 6379;
string password = "yzf279533105";
int timeout = 5000;
// 初始化,并建立连接
if(!m_redisClient.Init(IP,port,password,timeout))
{
printf("main(), Init() failed");
return -1;
}
/////////////////////////////// Set测试 string类型 /////////////////////////////////////
string key = "key_1";
string val = "value_1";
int result = m_redisClient.Set(key, val, 30);
if(result != REDIS_SUCCESS)
{
printf("main(), Set(string) failed");
return -1;
}
printf("main(), Set(string), success, key=%s, value=%s \n", key.c_str(), val.c_str());
////////////////////////////// Get测试 string类型 //////////////////////////////////////
string value = m_redisClient.Get(key);
printf("main(), Get(string), success, key=%s, value=%s \n", key.c_str(), value.c_str());
///////////////////////////// Set测试 结构体类型 //////////////////////////////////////
SStruct s1;
s1.a = 321;
s1.b = 3.14159;
strcpy(s1.c,"hello world!");
s1.d = 'a';
string key2 = "struct:1";
result = m_redisClient.Set(key2, (char*)&s1, sizeof(SStruct), 100);
if(result != REDIS_SUCCESS)
{
printf("main(), Set(struct) failed");
return -1;
}
printf("main(), Set(struct), success, key2=%s \n", key2.c_str());
////////////////////////////// Get测试 结构体类型 //////////////////////////////////////
CAutoRedisReply reply;
result = m_redisClient.Get(key2, reply);
if(result != REDIS_SUCCESS)
{
printf("main(), Get(struct), failed");
return -1;
}
redisReply* replyPtr = reply.get();
SStruct s2;
// 整体拷贝给s2结构体即可
memcpy(&s2, replyPtr->str,sizeof(SStruct));
printf("main(), Get(struct), success, s2.a=%d, s2.b=%f, s2.c=%s, s2.d=%c \n", s2.a, s2.b, s2.c, s2.d);
getchar();
return 0;
}