C++学习记录:C++连接Redis数据库

  之前学习了Redis数据库相关的内容,但是并没有在编写C++代码中用到Redis相关内容。
  本篇笔记记录了个人在 Linux 环境下使用 C++ 连接 Redis 数据库的过程。实现了一个简单的排行榜功能。
  由于现在的主流是使用 java 连接 redis,所以在网上查询 C语言 的API消耗了一部分时间,在本篇笔记中,我将记录相关数据结构和API的使用方法。

一、基础准备

1. 找到hiredis.h

  一般来讲,这个文件在你的redis文件夹下deps/hiredis目录中。将其include到源码中即可使用redis的API。
在这里插入图片描述

2. 编译并且连接库

  此时可以尝试写一个基础代码,随后编译。例如:

1
2
3
4
5
6
7
8
/*此文件位于redis文件夹下 test.cpp*/
#include"deps/hiredis/hiredis.h"

int main()
{

return 0;
}

  随后编译:

1
g++ test.cpp -o test -l hiredis

  若可以正常编译,则说明没问题。若是提示找不到hiredis库文件,则按下面进行操作:

1
2
3
4
5
6
7
8
//首先进入redis文件夹中,安装
# cd redis-x.x.xx
# make
# make install
//随后进入 redis/deps/hiredis 文件夹中,安装
# cd deps/hiredis/
# make
# make install

  随后即可正常编译。

3. 运行

  找到上面编译生成的文件,运行,若成功执行即可跳过本节内容。
  若提示找不到链接文件,则说明动态库无法被正确连接。则按下面步骤操作:

1
2
3
4
5
6
//进入动态库链接文件
# vim /etc/ld.so.conf
//在新的一行中加入库文件所在目录
添加: .../redis-x.x.x/deps/hiredis
//更新/etc/ld.so.cache文件
# ldconfig

  随后即可正常运行编译生成的文件。

二、代码相关

1. 常用

  • 建立redis连接
    1
    2
    3
    4
    5
    redisContext* myredis = redisConnect("127.0.0.1",6379);
    /*
    如果 myredis->err = true,则说明连接失败
    字符串 myredis->errstr 即为失败原因
    */
  • 执行redis语句并接收结果
    1
    2
    3
    4
    redisReply* reply = (redisReply*)redisCommand(myredis, "set zzz 1");
    /*
    语句执行的结果,储存在 redisReply结构体类型 的 reply 中
    */
  • 释放reply结构体
    1
    freeReplyObject(reply);
  • 断开redis连接
    1
    redisFree(myredis);

2. redisReply结构体

  我感觉这算是redis相关内容中比较重要的内容了,语句执行的结果全在这个结构体中。

  • 下面是这个结构体的定义:
1
2
3
4
5
6
7
8
typedef struct redisReply {
int type; /* 返回值类型 */
long long integer; /* 当返回类型为 REDIS_REPLY_INTEGER 时 */
size_t len; /* 返回的字符串长度 */
char *str; /* 当返回值类型为 REDIS_REPLY_ERROR 和 REDIS_REPLY_STRING */
size_t elements; /* 返回的数组长度 */
struct redisReply **element; /* 当返回值类型为 REDIS_REPLY_ARRAY */
} redisReply;
  • type的类型
1
2
3
4
5
6
REDIS_REPLY_STRING: 1 
REDIS_REPLY_ARRAY: 2
REDIS_REPLY_INTEGER:3
REDIS_REPLY_NIL: 4
REDIS_REPLY_STATUS: 5
REDIS_REPLY_ERROR: 6

我们首先通过type来确认返回值的类型:

  1. 返回值为1即为字符串,通过reply->str获取。
  2. 返回值为2即为数组,通过reply->element获取到redisReply数组,再遍历该数组,通过type正确获取其中信息。
  3. 返回值为3即为数字,通过reply->integer获取。
  4. 返回值为4即为空。
  5. 返回值为5即为执行语句的状态,通过reply->str获取,若结果为”OK”即为成功执行。
  6. 返回值为6即为执行错误。

  返回值的类型和执行语句的类型是相关的,例如我执行get命令,则type应该为1;若我执行zrevrange命令,则type应该为2。在下文中,我简单实现了一个排行榜功能,其中使用的结构为sorted_set,则其返回的排行榜结果type应为2,通过遍历其element数组,即可获取排行榜信息。

三、一个简单的排行榜demo

1. 思路

  简单来说就是获取key和范围,使用sprintf拼接redis查询语句,通过返回的redisReply结构体输出结果。

2. 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include<iostream>
#include<stdio.h>
#include"deps/hiredis/hiredis.h"
using namespace std;

redisContext* myredis = new redisContext;
redisReply* reply = new redisReply;
char query[150];//查询语句

void get_rank(const char* key_name, int start, int stop)
{
sprintf(query, "zrevrange %s %d %d", key_name, start, stop);
reply = (redisReply *)redisCommand(myredis, query);
//printf("命令执行结果 reply type: %d\n", reply->type);
if (reply->type == 2)
{
for(int i=0;i<reply->elements;i++)
{
if(reply->element[i]->type != 1)
{
printf("Error-Please check that the input is correct\n");
freeReplyObject(reply);
return;
}
if(i == 0)
{
printf("\nRANK:\n|----------|\n");
}
printf("| %2d -- %2s |\n", i+1, reply->element[i]->str);
}
printf("|----------|\n\n");
}
else
{
printf("Error-Please check that the input is correct\n");
}
freeReplyObject(reply);
}

void get_rank_withscores(const char* key_name, int start, int stop)
{
sprintf(query, "zrevrange %s %d %d withscores", key_name, start, stop);
reply = (redisReply *)redisCommand(myredis, query);
//printf("命令执行结果 reply type: %d\n", reply->type);
if (reply->type == 2)
{
for(int i=0;i<reply->elements;i+=2)
{
if(reply->element[i]->type != 1)
{
printf("Error-Please check that the input is correct\n",reply->element[i]->type);
freeReplyObject(reply);
return;
}
if(i == 0)
{
printf("\nRANK:\n|-----------------|\n");
}
printf("| %2d -- %2s -- %3s |\n", i/2+1, reply->element[i]->str, reply->element[i+1]->str);
}
printf("|-----------------|\n\n");
}
else
{
printf("Error-Please check that the input is correct\n");
}
freeReplyObject(reply);
}

int main()
{
myredis = redisConnect("127.0.0.1",6379);
if(myredis->err)//if error
{
cout << "Connection Error:" << myredis->errstr << endl;
}

//查询key:score的前十名
get_rank("score", 0, 9);

//查询key:score的前十名 并且带上分数
get_rank_withscores("score", 0 ,9);

redisFree(myredis);
return 0;
}

3. 执行结果

(上为不带分数 下为带分数)
在这里插入图片描述