Linux 下 Redis的使用笔记(1),hiredis的使用

Redis

什么是Redis?

Redis 是完全开源的,遵守BSD协议,高性能的key-value数据库。

BSD开源协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。当你发布使用了BSD协议的代码,或者以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:

  • 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。
  • 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。
  • 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

BSD代码鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销 售,因此是对商业集成很友好的协议。
很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者 二次开发。

内容截取自:菜鸟教程

Redis的特点

  • Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis 不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis 支持数据的备份,即master-slave模式的数据备份(主从复制)
  • Redis 性能极高,读速度为110000次/s,写速度为81000次/s。(一个字,快)
  • Redis 的所有操作都是原子性的。单个操作是原子性的,多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • Redis 还支持 publish/subscribe,通知,key过期等待特性。

Redis 的使用

hiredis 相关

安装与编译

https://github.com/redis/hiredis
git clone https://github.com/redis/hiredis.git
tar -xzvf hiredis.tar.gz //解压
cd hiredis //进入目录
make
sudo make install //将可执行程序赋值到/usr/local/bin目录中,当执行程序中就不要输入完整的路径
sudo ldconfig (更新动态库配置文件) /usr/local/lib
make test //测试redis是否编译正确
//编译时需要加上的后缀
g++ xxx.c -o xxx -I /usr/local/include/hiredis -lhiredis
或者直接g++ xxx.cc -lhiredis

安装完成后在需要使用的文件中加入

#include <hiredis/hiredis.h>

Redis 的重要API

连接redis数据库

redisContext* redisConnect(const char *ip, int port)
redisContext* redisConnectWithTimeout(const char *ip, int port, timeval tv)

//redisContext不是线程安全的
typedef struct redisContext
{
	int err; /*错误标志,正确连接标志为0,出错时设置为非零常量*/
	char errstr[128]; /*存放错误信息的字符串*/
	int fd;
	int flags;
	char *obuf; /* Write buffer */
	redisReader *reader; /* Protocol reader */
} redisContext;

示例程序:

redisContext *c = redisConnect("127.0.0.1", 6379);
if (c == NULL || c->err) {
	if (c) {
		printf("Error: %s\n", c->errstr);
		// handle error
	} else {
		printf("Can't allocate redis context\n");
	}
}

发送请求命令

第一个参数为连接数据库返回的值,剩余的是可变参数,类似printf。
此函数的返回值是void *,但是一般会强制转换为redisReply类型,便于做进一步处理。

void *redisCommand(redisContext *c, const char *format...)
  • 如果命令执行错误,返回值为NULL, redisContext 的err字段被设置为非零常量。
  • 如果,错误发生,原先的redisContext就不能重复使用,需要重新建立一个新的连接。
  • 如果成功执行命令,则标准返回一个 redisReply 类型,该类型结构如下:
typedef struct redisReply
{
	int type; /* 测试收到什么样的返回 REDIS_REPLY_* */
	long long integer; /* type 是 REDIS_REPLY_INTEGER 类型, integer保存返回的值*/
	int len; /* 保存str类型的长度 */
	char *str; /* type 是 REDIS_REPLY_ERROR 和 REDIS_REPLY_STRING,str保存返回的值 */
	size_t elements; /* type 是 REDIS_REPLY_ARRAY,保存返回多个元素的数量 */
	struct redisReply **element; /* 返回多个元素以redisReply对象的形式存放 */
} redisReply;

//type还可以是REDIS_REPLY_NIL,表示返回了一个零对象,没有数据可以访问。
  • 通过redisReply 结构体中的type变量可以确定命令执行的情况。
#define REDIS_REPLY_STRING 1 //字符串
#define REDIS_REPLY_ARRAY 2 //数组,例如mget返回值
#define REDIS_REPLY_INTEGER 3 //数字类型
#define REDIS_REPLY_NIL 4 //空
#define REDIS_REPLY_STATUS 5 //状态,例如set成功返回的‘OK’
#define REDIS_REPLY_ERROR 6 //执行失败
  • REDIS_REPLY_STATUS

    返回执行结果为状态的命令。比如set命令的返回值的类型是REDIS_REPLY_STATUS,然后只有当返回信息是“OK”时,才表示该命令执行成功。可以通过 reply->str 得到文字信息,通过 reply->len 得到信息长度。

  • REDIS_REPLY_ERROR
    返回错误。错误信息可以通过reply->str得到文字信息,通过 reply->len 得到信息长度。

  • REDIS_REPLY_INTEGER
    返回整型标识。可以通过 reply->integer 变量得到类型为 long long 的值。

  • REDIS_REPLY_NIL
    返回nil对象,说明不存在要访问的数据。

  • REDIS_REPLY_STRING
    返回字符串标识。可以通过 reply->str 得到具体值,通过 reply->len 得到信息长度。

  • REDIS_REPLY_ARRAY
    返回数据集标识。数据集中元素的数目可以通过 reply->elements 获得,每个元素是个 redisReply 对象,元素值可以通过 reply->element[…index…].* 形式获得,用在获得多个数据结果的操作。

示例

SET\GET\DEL

  • 图片中的 SET 命令换成 hiredis 的C代码形式如下:
#include <hiredis/hiredis.h>

redisContext * _connect = redisConnect("127.0.0.1",6379);
if(_connect == NULL || _connect -> err )
{
	if(_connect)
	{
		printf("Error: %s \n",_connect -> errstr);
	}else{
		printf("Can't allocate redis context\n");
	}
}
char key[1024]="key-1";
char val[1024]="hello";
printf("SET %s %s\n",key,val);
redisReply* _reply=(redisReply*)redisCommand(_connect,"SET %s %s",key,val);
//set 命令总是返回 ok ,所以此时 type 始终为 REDIS_REPLY_STATUS (5)
//且信息保存在 str 中
if(_reply -> type == REDIS_REPLY_STATUS )
{
  printf("%s\n",_reply -> str);
}
freeReplyObject(_reply);
  • 图片中的 GET 命令换成 hiredis 的C代码形式如下:
#include <hiredis/hiredis.h>

redisContext * _connect = redisConnect("127.0.0.1",6379);
if(_connect == NULL || _connect -> err )
{
	if(_connect)
	{
		printf("Error: %s \n",_connect -> errstr);
	}else{
		printf("Can't allocate redis context\n");
	}
}
char key[1024]="key-1";
printf("GET %s\n",key);
redisReply* _reply=(redisReply*)redisCommand(_connect,"GET %s",key);
//GET的返回值有三种:
//key 存在时,返回 key 的值
//key 不存在时,返回 nil 
//key 不是字符串类型,返回一个错误
if(_reply -> type == REDIS_REPLY_STRING )//存在,有值
{
  printf("%s\n",_reply -> str);
}else if(_reply -> type == REDIS_REPLY_NIL)//不存在
{
	printf("nil\n");
}else if(_reply -> type == REDIS_REPLY_ERROR)//错误
{
	printf("(error) %s\n",_reply -> str);
}
freeReplyObject(_reply);
  • 图片中的 DEL 命令换成 hiredis 的C代码形式如下:
#include <hiredis/hiredis.h>

redisContext * _connect = redisConnect("127.0.0.1",6379);
if(_connect == NULL || _connect -> err )
{
	if(_connect)
	{
		printf("Error: %s \n",_connect -> errstr);
	}else{
		printf("Can't allocate redis context\n");
	}
}
char key[1024]="key-1";
printf("DEL %s\n",key);
redisReply* _reply=(redisReply*)redisCommand(_connect,"DEL %s",key);
//DEL的返回值为删除的键的数目
if(_reply -> type == REDIS_REPLY_INTEGER )//数目
{
  printf("(integer) %lld\n",_reply -> integer);
}
freeReplyObject(_reply);
  • 其余命令的返回情况,类似处理
  • 对于 elementelements
    • 针对多个结果集,对应到 redis-cli 里面的每一行数据
    • 注意 element 相当于是保存结果的数组,先判断 type 是不是 REDIS_REPLY_ARRAY
    • elements 里保存是的结果数组的长度。
    • 调用完要记得调用 freeReplyObject() 把最开始的 结果 释放掉。(redis 自动递归释放)

Redis 的知识点

  • Redis 数据库里面的每一个键值对 (key-value pair) 都是由对象 (object) 组成的。
    1. 数据库键 总是一个字符串对象 (string object)
    2. 数据库键的值则可以是:
      • 字符串对象
      • 列表对象 (list object)
      • 哈希对象 (hash object)
      • 集合对象 (set object)
      • 有序集合对象 (sorted set object)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人生苦难处

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值