当前位置: 首页 > 编程日记 > 正文

【redis】c/c++操作redis(对于hiredis的封装)

前言

最近一直在学习redis,通过c/cpp来执行redis命令,使用的是hiredis客户端来实现的。
先简单贴一下代码

头文件

#include <vector>
#include <string>
#include <hiredis/hiredis.h>
typedef enum en_redisResultType
{redis_reply_invalid = -1,redis_reply_string,redis_reply_integer,redis_reply_array,redis_reply_null
}redisResultType;
typedef struct st_redisResult
{int type;int inter;std::string strdata;std::vector<std::string> vecdata;
}redisResult;
class CRedisBase
{
public:CRedisBase(const char *szip, int port, const char *szpwd, int dbname);CRedisBase(void);~CRedisBase(void);int open_redis();int close_redis();int set_redis(const char *szcmd);int set_redis_datas(std::vector<std::string> vcmd);int get_redis(const char *szcmd, redisResult &result);int get_redis_datas(std::vector<std::string> vcmd, std::vector<redisResult> &vresult);int setConfig(const char *szip, int port, const char *szpwd, int dbname);
private:redisContext *m_redis;std::string m_strip;std::string m_strpasswd;int m_port;int m_db;int free_redis_reply(redisReply *reply);int auth_redis(const char *szpwd);int set_redis_pipeline(std::vector<std::string> vcmd, std::vector<int> &vstatus);int get_redis_pipeline(std::vector<std::string> vcmd, std::vector<redisResult> &vresult);
};

代码

#include "redisbase.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

初始化操作

CRedisBase::CRedisBase(const char *szip, int port, const char *szpwd, int dbname)
{m_redis = NULL;setConfig(szip, port, szpwd, dbname);
}CRedisBase::CRedisBase()
{m_redis = NULL;
}CRedisBase::~CRedisBase(void)
{close_redis();
}int CRedisBase::setConfig(const char *szip, int port, const char *szpwd, int dbname)
{m_strip = szip;m_strpasswd = szpwd;m_port = port;m_db = dbname;return 0;
}

建立redis连接

int CRedisBase::open_redis()
{close_redis();int ret = -1;struct timeval timeout = {1, 500000};// 1.5 secondsfor (int i = 0; i < 10; i ++){m_redis = redisConnectWithTimeout(m_strip.c_str(), m_port, timeout);if (m_redis == NULL || m_redis->err){if (m_redis){printf("connection redis %s:%d error:%s\n", m_strip.c_str(), m_port, m_redis->errstr);close_redis();}else{printf("connection redis %s:%d error:can't allocate redis context\n",m_strip.c_str(), m_port);}sleep(3);}else{if(auth_redis(m_strpasswd.c_str())){close_redis();printf("connection redis %s:%d error: auth error\n", m_strip.c_str(), m_port);}else{printf("connection redis %s:%d success\n", m_strip.c_str(), m_port);char szcmd[64]= {0};snprintf(szcmd,sizeof(szcmd),"select %d", m_db);printf("select db:%d\n", m_db);set_redis(szcmd);ret = 0;break;}}}return ret;
}

认证

int CRedisBase::auth_redis(const char *szpwd)
{int ret = 0;redisReply *reply = (redisReply *)redisCommand(m_redis, "AUTH %s", szpwd);if (reply == NULL){printf("AUTH error\n");return -1;}if (reply->type != REDIS_REPLY_STATUS){printf("AUTH error: type [%d]\n", reply->type);ret = -1;}else{if (strcmp(reply->str, "OK") == 0){printf("AUTH success [%s]\n", reply->str);}else{printf("AUTH error: [%s]\n", reply->str);ret = -1;}}return ret;
}

关闭操作

关闭redis连接

int CRedisBase::close_redis()
{if (m_redis){redisFree(m_redis);m_redis = NULL;}return 0;
}

释放reply

int CRedisBase::free_redis_reply(redisReply *reply)
{if (reply){freeReplyObject(reply);reply = NULL;}return 0;
}

数据操作

hiredis通过redisCommand接口获取数据后,数据保存在redisReply 结构体指针中,通过判断结构体的type成员类型,来获取相对应的数据。
为了防止断线,若redisReply 结构体指针为NULL时,重新连接redis

向redis设置数据

int CRedisBase::set_redis(const char *szcmd)
{if (szcmd == NULL)return -1;if (m_redis == NULL){if (open_redis())return -1;}redisReply *reply = (redisReply *)redisCommand(m_redis, szcmd);if (reply == NULL){close_redis();open_redis();reply = (redisReply *)redisCommand(m_redis, szcmd);if (reply == NULL){printf("exec [%s] error\n", szcmd);return -1;}}//printf("##########################exec [%s]\n", szcmd);int ret = 0;switch(reply->type){case REDIS_REPLY_STATUS:if (strcmp(reply->str, "OK") == 0)ret = 0;elseret = -1;printf("[%s] status [%s]\n", szcmd, reply->str);break;case REDIS_REPLY_ERROR:ret = -1;printf("[%s] error [%s]\n", szcmd, reply->str);break;case REDIS_REPLY_STRING:ret = 0;printf("[%s] set result type:string\n", szcmd);break;case REDIS_REPLY_INTEGER:ret = 0;printf("[%s] set result type:integer:%d\n", szcmd, reply->integer);break;case REDIS_REPLY_ARRAY:ret = 0;printf("[%s] set result type:array\n", szcmd);break;case REDIS_REPLY_NIL:ret = 0;printf("[%s] set result type:null\n", szcmd);break;default:ret = -1;printf("[%s] set error\n", szcmd);break;}free_redis_reply(reply);return ret;
}

向redis获取数据

int CRedisBase::get_redis(const char *szcmd, redisResult &result)
{if (szcmd == NULL)return NULL;if (m_redis == NULL){if (open_redis())return -1;}result.type =  redis_reply_invalid;result.inter = 0;redisReply *reply = (redisReply *)redisCommand(m_redis, szcmd);if (reply == NULL){close_redis();open_redis();reply = (redisReply *)redisCommand(m_redis, szcmd);if (reply == NULL){printf("exec [%s] error\n", szcmd);return -1;}}//printf("##########################exec [%s]\n", szcmd);int ret = 0;switch(reply->type){case REDIS_REPLY_STATUS:ret = -1;printf("[%s] status [%s]\n", szcmd, reply->str);break;case REDIS_REPLY_ERROR:ret = -1;printf("[%s] error [%s]\n", szcmd, reply->str);break;case REDIS_REPLY_STRING:ret = 0;result.type = redis_reply_string;result.strdata = reply->str;printf("[%s] get string\n", szcmd);break;case REDIS_REPLY_INTEGER:ret = 0;result.type = redis_reply_integer;result.inter = reply->integer;printf("[%s] get integer\n", szcmd);break;case REDIS_REPLY_ARRAY:ret = 0;result.type = redis_reply_array;for (int i = 0; i < reply->elements; i ++){result.vecdata.push_back(reply->element[i]->str);}printf("[%s] get array\n", szcmd);break;case REDIS_REPLY_NIL:ret = 0;result.type = redis_reply_null;printf("[%s] get null\n", szcmd);break;default:ret = -1;result.type = redis_reply_invalid;printf("[%s] get error\n", szcmd);break;}free_redis_reply(reply);return ret;
}

通过pipeline批量向redis设置数据

int CRedisBase::set_redis_datas(std::vector<std::string> vcmd)
{std::vector<int> vstatus;if (set_redis_pipeline(vcmd, vstatus)){close_redis();open_redis();if (set_redis_pipeline(vcmd, vstatus)){printf("exec set redises error\n");return -1;}}return 0;
}int CRedisBase::set_redis_pipeline(std::vector<std::string> vcmd, std::vector<int> &vstatus)
{if (vcmd.empty())return 0;if (m_redis == NULL){if (open_redis())return -1;}for (int i = 0; i < vcmd.size(); i ++){redisAppendCommand(m_redis, vcmd[i].c_str());}for (int i = 0; i < vcmd.size(); i ++){int ret = -1;redisReply *reply = NULL;if (redisGetReply(m_redis, (void **)&reply) == REDIS_OK && reply != NULL)if (ret == REDIS_OK && reply != NULL){switch(reply->type){case REDIS_REPLY_STATUS:if (strcmp(reply->str, "OK") == 0)ret = 0;elseret = -1;printf("[%s] status [%s]\n", vcmd[i].c_str(), reply->str);break;case REDIS_REPLY_ERROR:ret = -1;printf("[%s] error [%s]\n", vcmd[i].c_str(), reply->str);break;case REDIS_REPLY_STRING:ret = 0;printf("[%s] set result type:string\n", vcmd[i].c_str());break;case REDIS_REPLY_INTEGER:ret = 0;printf("[%s] set result type:integer:%d\n", vcmd[i].c_str(), reply->integer);break;case REDIS_REPLY_ARRAY:ret = 0;printf("[%s] set result type:array\n", vcmd[i].c_str());break;case REDIS_REPLY_NIL:ret = 0;printf("[%s] set result type:null\n", vcmd[i].c_str());break;default:ret = -1;printf("[%s] set error\n", vcmd[i].c_str());break;}}else{freeReplyObject(reply);reply = NULL;return -1;}freeReplyObject(reply);reply = NULL;vstatus.push_back(ret);}return 0;
}

通过pipeline批量获取数据

int CRedisBase::get_redis_datas(std::vector<std::string> vcmd, std::vector<redisResult> &vresult)
{if (get_redis_pipeline(vcmd, vresult)){close_redis();open_redis();if (get_redis_pipeline(vcmd, vresult)){printf("exec get redises error\n");return -1;}}return 0;
}int CRedisBase::get_redis_pipeline(std::vector<std::string> vcmd, std::vector<redisResult> &vresult)
{if (vcmd.empty())return -1;if (m_redis == NULL){if (open_redis())return -1;}for (int i = 0; i < vcmd.size(); i ++){redisAppendCommand(m_redis, vcmd[i].c_str());}for (int i = 0; i < vcmd.size(); i ++){int ret = -1;redisResult result;result.type =  redis_reply_invalid;result.inter = 0;redisReply *reply = NULL;if (redisGetReply(m_redis, (void **)&reply) == REDIS_OK && reply != NULL){switch(reply->type){case REDIS_REPLY_STATUS:if (strcmp(reply->str, "OK") == 0)ret = 0;elseret = -1;printf("[%s] status [%s]\n", vcmd[i].c_str(), reply->str);break;case REDIS_REPLY_ERROR:ret = -1;printf("[%s] error [%s]\n", vcmd[i].c_str(), reply->str);break;case REDIS_REPLY_STRING:ret = 0;result.type = redis_reply_string;result.strdata = reply->str;printf("[%s] get string\n", vcmd[i].c_str());break;case REDIS_REPLY_INTEGER:ret = 0;result.type = redis_reply_integer;result.inter = reply->integer;printf("[%s] get integer\n", vcmd[i].c_str());break;case REDIS_REPLY_ARRAY:ret = 0;result.type = redis_reply_array;for (int i = 0; i < reply->elements; i ++){result.vecdata.push_back(reply->element[i]->str);}printf("[%s] get array\n", vcmd[i].c_str());break;case REDIS_REPLY_NIL:ret = 0;result.type = redis_reply_null;printf("[%s] get null\n", vcmd[i].c_str());break;default:ret = -1;result.type = redis_reply_invalid;printf("[%s] get error\n", vcmd[i].c_str());break;}}else{freeReplyObject(reply);reply = NULL;return -1;}freeReplyObject(reply);reply = NULL;vresult.push_back(result);}return 0;
}

参考文章

封装hiredis
redis 使用-hiredis库使用

转载于:https://www.cnblogs.com/JesseTsou/p/10418439.html

相关文章:

OpenCV代码提取:transpose函数的实现

OpenCV中的transpose函数实现图像转置&#xff0c;公式为&#xff1a;目前fbc_cv库中也实现了transpose函数&#xff0c;支持多通道&#xff0c;uchar和float两种数据类型&#xff0c;经测试&#xff0c;与OpenCV3.1结果完全一致。实现代码transpose.hpp&#xff1a;// fbc_cv …

只给测试集不给训练集,要怎么做自己的物体检测器?

9 月5 日&#xff0c;下周四&#xff0c;大家期待已久的由《动手学深度学习》作者&#xff0c;亚马逊首席科学家亲自带领的「深度学习实训营」就要在北京开营了。今天&#xff0c;李沐已经把这次深度学习实训营白天的教学内容和代码上传到 Gituhub 和 D2L.ai 网站了&#xff0c…

MYSQL忘记登录密码

1、关闭Mysql&#xff1a; 如果 MySQL 正在运行&#xff0c;首先杀之 killall -TERM mysqld 2、另外的方法启动 MySQL &#xff1a;bin/safe_mysqld --skip-grant-tables 3、可以不需要密码就进入 MySQL 了。 然后就是 >use mysql>update user set passwordpassword(&qu…

OpenCV代码提取:flip函数的实现

OpenCV中实现图像翻转的函数flip&#xff0c;公式为&#xff1a;目前fbc_cv库中也实现了flip函数&#xff0c;支持多通道&#xff0c;uchar和float两种数据类型&#xff0c;经测试&#xff0c;与OpenCV3.1结果完全一致。实现代码flip.hpp&#xff1a;// fbc_cv is free softwar…

NLP这两年:15个预训练模型对比分析与剖析

作者 | JayLou来源 | 知乎前言在之前写过的《NLP的游戏规则从此改写&#xff1f;从word2vec, ELMo到BERT》一文中&#xff0c;介绍了从word2vec到ELMo再到BERT的发展路径。而在BERT出现之后的这大半年的时间里&#xff0c;模型预训练的方法又被Google、Facebook、微软、百度、O…

大三下学期第一周总结

本周以是开学第一周了&#xff0c;在生活方面&#xff0c;生活琐事确实变多了起来。每天上课&#xff0c;看着老师熟悉的面庞&#xff0c;如履春风。感觉学习没有那么多的陌生恐惧。学习是一方面&#xff0c;身体锻炼不能落下。一周至少保证三小时及其以上的运动。身体是革命的…

AD rodc扩展报错

AD rodc扩展报错AD RODC抢夺FSMO五大角色后&#xff0c;架构扩展报错&#xff0c;解决办法参考链接&#xff1a;http://support.microsoft.com/kb/949257/en-us

Dropout、梯度消失/爆炸、Adam优化算法,神经网络优化算法看这一篇就够了

作者 | mantch来源 | 知乎1. 训练误差和泛化误差对于机器学习模型在训练数据集和测试数据集上的表现。如果你改变过实验中的模型结构或者超参数&#xff0c;你也许发现了&#xff1a;当模型在训练数据集上更准确时&#xff0c;它在测试数据集上却不⼀定更准确。这是为什么呢&am…

入行AI,你需要一本Python机器学习入门

​目前机器学习红遍全球。男女老少都在学机器学习模型&#xff0c;分类器&#xff0c;神经网络和吴恩达。你也想成为一份子&#xff0c;但你该如何开始&#xff1f;今天小编推荐这本《Python机器学习》教你快速入门。​01什么是机器学习&#xff1f;从出生的那天起&#xff0c;…

通过transpose和flip实现图像旋转90/180/270度

在fbc_cv库中&#xff0c;提供了对图像进行任意角度旋转的函数rotate&#xff0c;其实内部也是调用了仿射变换函数warpAffine。如果图像仅是进行90度倍数的旋转&#xff0c;是没有必要用warpAffine函数的。这里通过transpose和flip函数实现对图像进行顺时针90度、180度、270度的…

DIY强大的虚拟化环境-技术可行性部分

【技术可行性部分】大体的cpu支不支持呀&#xff0c;实际效果使用呀&#xff0c;截图效果截图嵌套虚拟化[esxi&#xff0c;xenserver&#xff0c;Hyper-V]嵌套虚拟化&#xff1a;经过各种查资料&#xff0c;和测试验证[只测过intel的&#xff0c;amd的有类似的文章请去下面的资…

C++11中rvalue references的使用

Rvalue references are a feature of C that was added with the C11 standard. The syntax of an rvalue reference is to add && after a type.为了支持移动操作&#xff0c;C11引入了一种新的引用类型----右值引用(rvalue reference)。所谓右值引用就是必须绑定到右…

AIの幕后人:探秘“硬核英雄”的超级武器

作者 | 云计算的阿晶 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 掐指一算八年之前&#xff0c;那时正是国内互联网卯足劲头起飞的一年&#xff0c;各行各业表现都很突出&#xff0c;尤其是与人们生活密切相关的手机&#xff0c;正大踏步地从功能机向智能手机转…

PAT乙级1003

1003 我要通过&#xff01; &#xff08;20 point(s)&#xff09;“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件&#xff0c;系统就输出“答案正确”&#xff0c;否则输出“答案错误”。 得到“答案…

史上最简洁的UITableView Sections 展示包含NSDicionary 的NSArray

这个最典型的就是电话本&#xff0c;然后根据A&#xff0d;Z分组, 当然很多例子&#xff0c;不过现在发现一个很简洁易懂的&#xff1a; 1. 准备数据&#xff0c;定义一个dictionary来显示所有的内容&#xff0c;这个dictionary对应的value全是数组 也就是&#xff1a; A &…

微软麻将AI Suphx或引入“凤凰房”,与其他AI对打

作者 | 夕颜出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;【导读】在刚刚结束的上海2019世界人工智能大会上&#xff0c;微软宣布了其在人工智能领域的最新研究突破——由微软亚洲研究院研发的麻将 AI 系统 Suphx 在国际知名的专业麻将平台“天凤”上荣升十段&…

C++11中std::function的使用

类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作&#xff0c;这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等。 通过std::function对C中各种可调用实体(普通函数、Lambd…

django模板的导入

模板导入 前提:多个页面有一个相同的页面版块(多个有样式标签的集合体) 如何运用:可以将多个样式标签的集合进行封装对外提供版块的名字(接口),在有该版块的页面中直接导入即可 语法:{% include 版块页面的路径 %} 四inclusion_tag自定义标签 -- 模板导入 前提:多个页面有一个相…

[UML]UML系列——包图Package

系列文章 [UML]UML系列——用例图Use Case [UML]UML系列——用例图中的各种关系&#xff08;include、extend&#xff09; [UML]UML系列——类图Class [UML]UML系列——类图class的关联关系&#xff08;聚合、组合&#xff09; [UML]UML系列——类图class的依赖关系 [UML]UML系…

2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)

A Drawing Borders 很多构造方法&#xff0c;下图可能是最简单的了 代码&#xff1a; #include<bits/stdc.h> using namespace std; const int maxn1e610; struct Point{ int x,y; }; Point a[maxn]; int numa0; Point b[maxn]; int numb0; vector<pair<double,d…

C++11中std::bind的使用

std::bind函数是用来绑定函数调用的某些参数的。std::bind它可以预先把指定可调用实体的某些参数绑定到已有的变量&#xff0c;产生一个新的可调用实体。它绑定的参数的个数不受限制&#xff0c;绑定的具体哪些参数也不受限制&#xff0c;由用户指定。 std::bind&#xff1a;(…

在图数据上做机器学习,应该从哪个点切入?

作者 | David Mack编译 | ronghuaiyang来源 | AI公园&#xff08;ID:AI_Paradise&#xff09;【导读】很多公司和机构都在使用图数据&#xff0c;想在图上做机器学习但不知从哪里开始做&#xff0c;希望这篇文章给大家一点启发。自从我们在伦敦互联数据中心(Connected Data Lon…

C++11中Lambda表达式的使用

Lambda表达式语法&#xff1a;[capture ] ( params ) mutable exception attribute -> return-type { body } 其中capture为定义外部变量是否可见(捕获)&#xff0c;若为空&#xff0c;则表示不捕获所有外部变量&#xff0c;即所有外部变量均不可访问&#xff0c; 表示所有…

倒计时2天 | 专属技术人的盛会,为你而来!

5G 元年&#xff0c;人工智能 60 年&#xff0c;全球AI市场正发生着巨大的变化&#xff0c;顶尖科技企业和创新力量不断地进行着技术的更迭和应用的推进&#xff0c;专属于 AI 开发者的技术盛宴——2019 AI开发者大会&#xff08;AI ProCon&#xff09;将于 2 天后&#xff08;…

了解大数据的特点、来源与数据呈现方式

作业来源&#xff1a;https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2639 浏览2019春节各种大数据分析报告&#xff0c;例如&#xff1a; 这世间&#xff0c;再无第二个国家有能力承载如此庞大的人流量。http://www.sohu.com/a/290025769_313993春节人口迁徙大数据…

Mysql使用大全 从基础到存储过程

平常习惯了phpmyadmin等其他工具的的朋友有的根本就不会命令&#xff0c;如果让你笔试去面试我看你怎么办&#xff0c;所以&#xff0c;学习一下还是非常有用的&#xff0c;也可以知道你通过GUI工具的时候工具到底做了什么。Mysql用处很广&#xff0c;是php最佳拍档&#xff0c…

GDAL库简介以及在Windows下编译过程

GDAL(Geospatial Data Abstraction Library&#xff0c;地理空间数据抽象库)是一个在X/MIT许可协议下的开源栅格空间数据转换库。官网http://www.gdal.org/index.html&#xff0c;也可参考GitHub https://github.com/OSGeo/gdal&#xff0c;最新release版本为2.1.1. GDAL是一个…

Hexo博客NexT主题美化之评论系统

前言 更多效果展示&#xff0c;请访问我的 个人博客。 效果图&#xff1a; Valine 诞生于2017年8月7日&#xff0c;是一款基于Leancloud的快速、简洁且高效的无后端评论系统。 教程&#xff1a; 登录 Leancloud 官网&#xff0c;注册之后创建一个应用&#xff0c;选择【设置】-…

倒计时1天 | 专属技术人的盛会,为你而来!

5G 元年&#xff0c;人工智能 60 年&#xff0c;全球AI市场正发生着巨大的变化&#xff0c;顶尖科技企业和创新力量不断地进行着技术的更迭和应用的推进&#xff0c;专属于 AI 开发者的技术盛宴——2019 AI开发者大会&#xff08;AI ProCon&#xff09;将于 明天&#xff08;9 …

Selenium 2 WebDriver 多线程 并发

我用的是Selenium2&#xff0c;至于它的背景和历史就不赘述了。Selenium2也叫WebDriver。下面讲个例子&#xff0c;用WebDriverjava来写个自动化测试的程序。&#xff08;如果能用firefox去测试的话&#xff0c;我就直接用Selenium IDE录脚本了。。。&#xff09;有个前提&…