redis使用笔记
- 1、Redis简介
-
- [1.1 含义](#1.1 含义)
- [1.2 功能](#1.2 功能)
- [1.3 特点](#1.3 特点)
- [2. 常用的数据结构](#2. 常用的数据结构)
-
- [2.1 HASH](#2.1 HASH)
- [3 redis接口定义](#3 redis接口定义)
-
- [3.1 redisReply](#3.1 redisReply)
- [3.2 redisContext](#3.2 redisContext)
- [3.3 redisCommand](#3.3 redisCommand)
- [4 实践操作](#4 实践操作)
-
- [4.1 遇到问题](#4.1 遇到问题)
-
- [4.1.1 Get哈希的时候返回error](#4.1.1 Get哈希的时候返回error)
- [4.1.2 长度一直为0,str没法打印(未解决)](#4.1.2 长度一直为0,str没法打印(未解决))
1、Redis简介
最近项目需要使用redis,第一次操作做下工作笔记,以方便后续遇到问题时回头整理复盘,本篇我会持续补充持续更新~
1.1 含义
Redis(Remote Dictionary Server),是一种基于内存的数据结构存储服务。
1.2 功能
可以用作于数据库,缓存和消息队列,而且是开源的。
1.3 特点
- 基于内存的存储,操作速度非常快;
- 丰富的数据结构,包括字符串、列表、集合、有序集合等;
- 支持持久化存储;
- 集群支持;
- 灵活性;
- 易于使用;
2. 常用的数据结构
2.1 HASH
cpp
HMSET key field value [field value ...]
如果key存在,则更新value的值,如果key不存在,则更新key-value的键值对
cpp
HMSET usertable name "Alice" age 30 gender "female"
解释:将name Alice、age 30、gender female设置到usertable里面。同理,有set就必然会有get,含义就不再赘述,直接看代码:
cpp
HMGET key field [field ...]
HMGET usertable name age gender // 举例
即从usertable里面获取name age gender这三个哈希字段,这只是命令的源码,实际开发过程中还要配合hiredis的接口进行操作访问:
3 redis接口定义
3.1 redisReply
cpp
typedef struct redisReply {
int type;
long long integer;
double dval;
size_t len;
char *str;
char vtype[4];
size_t elements;
struct redisReply **element;
} redisReply;
type的枚举类型如下:
cpp
#define REDIS_REPLY_STRING 1 // 字符串
#define REDIS_REPLY_ARRAY 2 // 数组
#define REDIS_REPLY_INTEGER 3 // 整形
#define REDIS_REPLY_NIL 4 // 不存在的类型
#define REDIS_REPLY_STATUS 5 // 状态回复类型
#define REDIS_REPLY_ERROR 6 // 错误恢复类型
#define REDIS_REPLY_DOUBLE 7
#define REDIS_REPLY_BOOL 8
#define REDIS_REPLY_MAP 9
#define REDIS_REPLY_SET 10
#define REDIS_REPLY_ATTR 11
#define REDIS_REPLY_PUSH 12
#define REDIS_REPLY_BIGNUM 13
#define REDIS_REPLY_VERB 14
3.2 redisContext
一般是用来与redis服务器建连,常见用法如下:
cpp
redisContext *context = redisConnect("127.0.0.1", 6379);
if ((context == nullptr) || (context->err)) {
if (context) {
qDebug() << "Error: " << context->errstr;
redisFree(context);
} else {
qDebug() << "Error: Failed to allocate redis context";
}
return;
}
注意它是非线程安全的。
3.3 redisCommand
主要有两个入参,第一个是redisContext,另一个就是需要执行的命令,比如set、get这些。举个例子:
cpp
reply = redisCommand(context, "SET name xiaoyi"); // set
reply = redisCommand(context, "GET name"); // get
不仅如此,还可以通过插入变量来控制命令,如下:
cpp
reply = redisCommand(context, "SET name %s", value);
4 实践操作
cpp
void main()
{
const char* hostIP = "xxx.xxx.xxx.xxx";
qDebug() << "hostIP is: " << hostIP;
redisContext *context = redisConnect(hostIP, 6379);
qDebug() << "connect begin!";
if ((context == nullptr) || (context->err)) {
if (context) {
qDebug() << "Error: " << context->errstr;
redisFree(context);
} else {
qDebug() << "Error: Failed to allocate redis context";
}
return;
}
qDebug() << "connect success!";
redisReply *reply = (redisReply *)redisCommand(context, "HMGET xxxx k v ");
if (reply == nullptr) {
qDebug() << "reply is nullptr";
return;
}
qDebug() << "Get reply type" << reply->type;
qDebug() << "Get reply len" << reply->len;
qDebug() << "Get reply elements" << reply->elements;
qDebug() << "Get reply element 0 type:" << reply->element[0]->type;
qDebug() << "GET reply Error: " << reply->str;
freeReplyObject(reply);
// free redis connect
redisFree(context);
}
而实际情况未必就能如愿以偿,要明白编译、调试失败是常态,成功只是无数次实验中的少数。
4.1 遇到问题
4.1.1 Get哈希的时候返回error
源代码:
cpp
redisReply *reply = (redisReply *)redisCommand(context, "GET Bams_AC_alarm11");
打印窗口如下:
原因:通过上面错误的定义,得知6表示的是查询失败,查询相关资料得知redisCommand中的命令应该采用HMGET类型,修改如下:
cpp
redisReply *reply = (redisReply *)redisCommand(context, "HMGET Bams_AC_alarm11 v t ");
验证结果:
4.1.2 长度一直为0,str没法打印(未解决)
修改代码如下:
cpp
const char* command1 = "GET nameKey";
redisReply *reply = (redisReply *)redisCommand(context, command1);
if (reply == nullptr) {
qDebug() << "reply is nullptr";
return;
}
qDebug() << "Command:" << command1;
if (reply->type == REDIS_REPLY_STRING) {
printf("rely str is %s\n", reply->str);
printf("rely len is %s\n", reply->len);
}
无意中将len打印成string类型,但发现居然能把正确的值给打印出来:
偶然无意间用字符类型打印了len,结果就出现了自己预期中的值:
没想通这是为什么,然后通过redis desktop manager本地进行查询,确认确实也是设置进去且查询的数值一致:
迷,先记着吧,后面解决后再更新。