Redis常用命令及C/C++调用Redis接口详解
文章目录
一、Redis常用命令
一般Redis都是安装在linux上,分为server和client。
启动Redis服务端
在终端输入以下命令启动 Redis 服务端:
$redis-server
启动Redis客户端
在终端输入以下命令启动 Redis 客户端:
#若设置了密码,使用如下格式启动
$redis-cli -h [ip] -p [port] -a [password]
#简单格式
$redis-cli
输入后,返回提示如下:
redis 127.0.0.1:6379>
注意:127.0.0.1 是本地计算机的 IP 地址,6379 是运行 Redis 服务器的默认端口号。
Redis常用命令详解
Redis 命令大致可分为以下几种:
- 服务端(server)命令
- 客户端(client)命令
- 键命令(key)
- 数据类型命令
- 功能应用命令
这本《Redis 常用命令手册》介绍了 Redis 中经常使用的命令,包括键命令和数据类型命令,其中数据类型命令包括 String、List、Hash、Set 以及 Sorted Set。
键(Key)命令
我们知道 Redis 是 key-value 型数据库,使用 key 对 value 进行存储,因此,键(Key)命令是 Redis 中经常使用的一类命令。常用的键命令如下所示:
命令 | 说明 |
---|---|
DEL | 若键存在的情况下,该命令用于删除键 |
DUMP | 用于序列化给定 key ,并返回被序列化的值 |
EXISTS | 用于检查键是否存在,若存在则返回 1,否则返回 0 |
EXPIRE | 设置 key 的过期时间,以秒为单位 |
EXPIREAT | 该命令与 EXPIRE 相似,用于为 key 设置过期时间,不同在于,它的时间参数值采用的是时间戳格式。 |
KEYS | 此命令用于查找与指定 pattern 匹配的 key |
MOVE | 将当前数据库中的 key 移动至指定的数据库中(默认存储为 0 库,可选 1-15中的任意库) |
PERSIST | 该命令用于删除 key 的过期时间,然后 key 将一直存在,不会过期 |
PEXPIRE | 设置 key 的过期,以毫秒为单位 |
RANDOMKEY | 从当前数据库中随机返回一个 key |
RENAME | 修改 key 的名称 |
SCAN | 基于游标的迭代器,用于迭代数据库中存在的所有键,cursor 指的是迭代游标 |
TTL | 用于检查 key 还剩多长时间过期,以秒为单位 |
TYPE | 该命令用于获取 value 的数据类型。 |
Hash 命令
Hash(哈希散列)是 Redis 基本数据类型之一,它以字符串映射表的形式来进行存储。Hash 特别适合用于存储对象。常用的命令如下所示:
命令 | 说明 |
---|---|
HDEL | 用于删除一个或多个哈希表字段 |
HEXISTS | 用于确定哈希字段是否存在 |
HGET | 获取存储在 key 中的哈希字段的值 |
HGETALL | 获取存储在 key 中的所有哈希字段值 |
HINCRBY | 为存储在 key 中的哈希表指定字段做整数增量运算 |
HKEYS | 获取存储在 key 中的哈希表的所有字段 |
HLEN | 获取存储在 key 中的哈希表的字段数量 |
HSET | 用于设置存储在 key 中的哈希表字段的值 |
HVALS | 用于获取哈希表中的所有值 |
String 命令
Strings(字符串)结构是 Redis 的基本数据类型之一,我们可以通过相关字符串命令对其进行操作,比如设置、检索、删除等等。字符串类型有诸多的应用场景,比如微博粉丝的关注与取消等。
下面介绍了 Redis 中常营的字符串命令:
命令 | 说明 |
---|---|
APPEND | 该命令将 value 追加到 key 所存储值的末尾 |
BITCOUNT | 该命令用于计算字符串中,被设置为 1 的比特位的数量。 |
DECR | 将 key 所存储的整数值减 1 |
DECRBY | 将 key 所储存的值减去给定的递减值(decrement) |
GET | 用于检索指定键的值 |
GETBIT | 对 key 所存储的字符串值,获取其指定偏移量上的位(bit) |
GETRANGE | 返回 key 中字符串值的子字符 |
GETSET | 将给定 key 的值设置为 value,并返回 key 的旧值 |
INCR | 将 key 所存储的整数值加 1 |
INCRBY | 将 key 所储存的值加上给定的递增值(increment) |
INCRBYFLOAT | 将 key 所储存的值加上指定的浮点递增值(increment) |
MGET | 一次性获取一个或多个 key 所存储的值 |
MSET | 该命令允许同时设置多个键值对 |
MSETNX | 当指定的 key 都不存在时,用于设置多个键值对 |
SET | 用于设定指定键的值 |
SETBIT | 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit) |
SETEX | 将值 value 存储到 key中 ,并将 key 的过期时间设为 seconds (以秒为单位) |
STRLEN | 返回 key 所储存的字符串值的长度 |
SETNX | 当 key 不存在时设置 key 的值 |
SETRANGE | 从偏移量 offset 开始,使用指定的 value 覆盖的 key 所存储的部分字符串值 |
List 命令
List 是 Redis 中最常用数据类型之一。Redis 提供了诸多用于操作列表类型的命令,通过这些命令你可以实现将一个元素添加到列表的头部,或者尾部等诸多操作。
List 常用的命令如下所示:
命令 | 说明 |
---|---|
BLPOP | 用于删除并返回列表中的第一个元素(头部操作),如果列表中没有元素,就会发生阻塞,直到列表等待超时或发现可弹出元素为止 |
BRPOP | 用于删除并返回列表中的最后一个元素(尾部操作),如果列表中没有元素,就会发生阻塞,直到列表等待超时或发现可弹出元素为止 |
BRPOPLPUSH | 从列表中取出最后一个元素,并插入到另一个列表的头部。如果列表中没有元素,就会发生阻塞,直到等待超时或发现可弹出元素时为止 |
LINDEX | 通过索引获取列表中的元素 |
LINSERT | 指定列表中一个元素在它之前或之后插入另外一个元素 |
LLEN | 用于获取列表的长度 |
LPOP | 从列表的头部弹出元素,默认为第一个元素 |
LPUSH | 在列表头部插入一个或者多个值 |
LPUSHX | 当储存列表的 key 存在时,用于将值插入到列表头部 |
LRANGE | 获取列表指定范围内的元素 |
LREM | 表示从列表中删除元素与 value 相等的元素。count 表示删除的数量,为 0 表示全部移除 |
LSET | 表示通过其索引设置列表中元素的值 |
LTRIM | 保留列表中指定范围内的元素值 |
Set 命令
Redis set 数据类型由键值对组成,这些键值对具有无序、唯一的性质,这与 Python 的 set 相似。当集合中最后一个元素被移除之后,该数据结构也会被自动删除,内存也同样会被收回。
由于 set 集合可以实现去重,因此它有很多适用场景,比如用户抽奖活动,使用 set 集合可以保证同一用户不被第二次选中。
Redis set 常用的命令如下所示:
命令 | 说明 |
---|---|
SADD | 向集合中添加一个或者多个元素,并且自动去重 |
SCARD | 返回集合中元素的个数 |
SDIFF | 求两个或对多个集合的差集 |
SDIFFSTORE | 求两个集合或多个集合的差集,并将结果保存到指定的集合(key)中 |
SINTER | 求两个或多个集合的交集 |
SINTERSTORE | 求两个或多个集合的交集,并将结果保存到指定的集合(key)中 |
SMEMBERS | 查看集合中所有元素 |
SMOVE | 将集合中的元素移动到指定的集合中 |
SPOP | 弹出指定数量的元素 |
SRANDMEMBER | 随机从集合中返回指定数量的元素,默认返回 1个 |
SREM | 删除一个或者多个元素,若元素不存在则自动忽略 |
SUNION | 求两个或者多个集合的并集 |
SUNIONSTORE | 求两个或者多个集合的并集,并将结果保存到指定的集合(key)中 |
Zset 命令
zset 是 Redis 提供的最具特色的数据类型之一,首先它是一个 set,这保证了内部 value 值的唯一性,其次它给每个 value 添加了一个 score(分值)属性,通过对分值的排序实现了有序化。比如用 zset 结构来存储学生的成绩,value 值代表学生的 ID,score 则是的考试成绩。我们可以对成绩按分数进行排序从而得到学生的的名次。
下面列出了 zset 的常用命令,如下所示:
命令 | 说明 |
---|---|
ZADD | 用于将一个或多个成员添加到有序集合中,或者更新已存在成员的 score 值 |
ZCARD | 获取有序集合中成员的数量 |
ZCOUNT | 用于统计有序集合中指定 score 值范围内的元素个数 |
ZINCRBY | 用于增加有序集合中成员的分值 |
ZINTERSTORE | 求两个或者多个有序集合的交集,并将所得结果存储在新的 key 中 |
ZRANGE | 返回有序集合中指定索引区间内的成员数量 |
ZRANGEBYLEX | 返回有序集中指定字典区间内的成员数量 |
ZRANGEBYSCORE | 返回有序集合中指定分数区间内的成员 |
ZRANK | 返回有序集合中指定成员的排名 |
ZREM | 移除有序集合中的一个或多个成员 |
ZREMRANGEBYRANK | 移除有序集合中指定排名区间内的所有成员 |
ZREMRANGEBYSCORE | 移除有序集合中指定分数区间内的所有成员 |
ZREVRANGE | 返回有序集中指定区间内的成员,通过索引,分数从高到低 |
ZREVRANK | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
ZSCORE | 返回有序集中,指定成员的分数值 |
ZUNIONSTORE | 求两个或多个有序集合的并集,并将返回结果存储在新的 key 中 |
二、C/C++调用接口连接和操作Redis数据库
上面的这些命令在是Redis自身的命令,但是在我们的C/C++代码,我们不能直接执行这些命令,我们需要通过Redis提供的API来访问Redis。
redis支持不同的编程语言,但是调用了不同的redis包,例如:java对应jedis;php对应phpredis;C++对应的则是hredis。
因此我们需要安转hredis。安装完hredis之后,我们就可以通过hredis提供的API来连接、操作Redis。
redis提供的api在头文件<hiredis.h>中提供,我们直接把文件内容拿过来了解一些,再一次讲解每个函数的使用方法。
hiredis.h
#ifndef __HIREDIS_H
#define __HIREDIS_H
#include "read.h"
#include <stdarg.h> /* for va_list */
#include <sys/time.h> /* for struct timeval */
#include <stdint.h> /* uintXX_t, etc */
#include "sds.h" /* for sds */
#include "alloc.h" /* for allocation wrappers */
#define HIREDIS_MAJOR 0
#define HIREDIS_MINOR 14
#define HIREDIS_PATCH 0
#define HIREDIS_SONAME 0.14
/* Connection type can be blocking or non-blocking and is set in the
* least significant bit of the flags field in redisContext. */
#define REDIS_BLOCK 0x1
/* Connection may be disconnected before being free'd. The second bit
* in the flags field is set when the context is connected. */
#define REDIS_CONNECTED 0x2
/* The async API might try to disconnect cleanly and flush the output
* buffer and read all subsequent replies before disconnecting.
* This flag means no new commands can come in and the connection
* should be terminated once all replies have been read. */
#define REDIS_DISCONNECTING 0x4
/* Flag specific to the async API which means that the context should be clean
* up as soon as possible. */
#define REDIS_FREEING 0x8
/* Flag that is set when an async callback is executed. */
#define REDIS_IN_CALLBACK 0x10
/* Flag that is set when the async context has one or more subscriptions. */
#define REDIS_SUBSCRIBED 0x20
/* Flag that is set when monitor mode is active */
#define REDIS_MONITORING 0x40
/* Flag that is set when we should set SO_REUSEADDR before calling bind() */
#define REDIS_REUSEADDR 0x80
#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */
/* number of times we retry to connect in the case of EADDRNOTAVAIL and
* SO_REUSEADDR is being used. */
#define REDIS_CONNECT_RETRIES 10
#ifdef __cplusplus
extern "C" {
#endif
/* This is the reply object returned by redisCommand() */
typedef struct redisReply {
int type; /* REDIS_REPLY_* */
long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
size_t len; /* Length of string */
char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
} redisReply;
redisReader *redisReaderCreate(void);
/* Function to free the reply objects hiredis returns by default. */
void freeReplyObject(void *reply);
/* Functions to format a command according to the protocol. */
int redisvFormatCommand(char **target, const char *format, va_list ap);
int redisFormatCommand(char **target, const char *format, ...);
int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen);
void redisFreeCommand(char *cmd);
void redisFreeSdsCommand(sds cmd);
enum redisConnectionType {
REDIS_CONN_TCP,
REDIS_CONN_UNIX
};
/* Context for a connection to Redis */
typedef struct redisContext {
int err; /* Error flags, 0 when there is no error */
char errstr[128]; /* String representation of error when applicable */
int fd;
int flags;
char *obuf; /* Write buffer */
redisReader *reader; /* Protocol reader */
enum redisConnectionType connection_type;
struct timeval *timeout;
struct {
char *host;
char *source_addr;
int port;
} tcp;
struct {
char *path;
} unix_sock;
} redisContext;
redisContext *redisConnect(const char *ip, int port);
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
redisContext *redisConnectNonBlock(const char *ip, int port);
redisContext *redisConnectBindNonBlock(const char *ip, int port,
const char *source_addr);
redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
const char *source_addr);
redisContext *redisConnectUnix(const char *path);
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
redisContext *redisConnectUnixNonBlock(const char *path);
redisContext *redisConnectFd(int fd);
/**
* Reconnect the given context using the saved information.
*
* This re-uses the exact same connect options as in the initial connection.
* host, ip (or path), timeout and bind address are reused,
* flags are used unmodified from the existing context.
*
* Returns REDIS_OK on successful connect or REDIS_ERR otherwise.
*/
int redisReconnect(redisContext *c);
int redisSetTimeout(redisContext *c, const struct timeval tv);
int redisEnableKeepAlive(redisContext *c);
void redisFree(redisContext *c);
int redisFreeKeepFd(redisContext *c);
int redisBufferRead(redisContext *c);
int redisBufferWrite(redisContext *c, int *done);
/* In a blocking context, this function first checks if there are unconsumed
* replies to return and returns one if so. Otherwise, it flushes the output
* buffer to the socket and reads until it has a reply. In a non-blocking
* context, it will return unconsumed replies until there are no more. */
int redisGetReply(redisContext *c, void **reply);
int redisGetReplyFromReader(redisContext *c, void **reply);
/* Write a formatted command to the output buffer. Use these functions in blocking mode
* to get a pipeline of commands. */
int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);
/* Write a command to the output buffer. Use these functions in blocking mode
* to get a pipeline of commands. */
int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
int redisAppendCommand(redisContext *c, const char *format, ...);
int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
/* Issue a command to Redis. In a blocking context, it is identical to calling
* redisAppendCommand, followed by redisGetReply. The function will return
* NULL if there was an error in performing the request, otherwise it will
* return the reply. In a non-blocking context, it is identical to calling
* only redisAppendCommand and will always return NULL. */
void *redisvCommand(redisContext *c, const char *format, va_list ap);
void *redisCommand(redisContext *c, const char *format, ...);
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
#ifdef __cplusplus
}
#endif
#endif
从文件代码可以看到,对于我们使用C/C++来连接操作Redis数据库,我们最少需要了解:
- 一个结构体:redisContext,这个结构体中,包含着我们连接Redis的信息。
- 几个函数:
- redisContext *redisConnect(const char *ip, int port);连接Redis函数
- void *redisCommand(redisContext *c, const char *format, …);给Redis传递命令
- void redisFree(redisContext *c);
- void freeReplyObject(void *reply);
函数详解
函数原型:redisContext *redisConnect(const char *ip, int port)
说明:该函数用来连接redis数据库,参数为数据库的ip地址和端口,一般redis数据库的端口为6379
该函数返回一个结构体redisContext。
函数原型:void *redisCommand(redisContext *c, const char *format, …);
说明:该函数执行命令,就如sql数据库中的SQL语句一样,只是执行的是redis数据库中的操作命令,第一个参数为连接数据库时返回的redisContext,剩下的参数为变参,就如C标准函数printf函数一样的变参。返回值为void*,一般强制转换成为redisReply类型的进行进一步的处理。
函数原型void freeReplyObject(void *reply);
说明:释放redisCommand执行后返回的redisReply所占用的内存
函数原型:void redisFree(redisContext *c);
说明:释放redisConnect()所产生的连接。
同步API
连接redis数据库
函数 redisConnect 被用来创建一个 redisContext。这个 context 是hiredis持有的连接状态。redisConnect 结构体有一个整型的 err 变量来标识连接错误码,如果连接错误则为非零值。变量 errstr 标识连接结果的文字描述。更多这方面的信息会在以下Errors章节说明。当你使用 redisConnect 来创建连接时应该检查err变量来判断是否连接正常建立。
redisContext *c = redisConnect("127.0.0.1", 6379);
if (c != NULL && c->err) {undefined
printf("Error: %s\n", c->errstr); // handle error }
发送命令到redis
有多种方法可以发送命令到redis。
首先介绍的是redisCommand。此函数类似于printf的使用方式,如
reply = redisCommand(context, “SET foo bar”);
类似于printf的s%格式化方式,如
reply = redisCommand(context, “SET foo %s”, value);
当你需要发送二进制安全的命令可以采用%b的格式化方式,同时需要一个字符串指针和size_t类型的字符串长度参数,如下
reply = redisCommand(context, “SET foo %b”, value, (size_t) valuelen);
在API内部,Hiredis根据不同的参数分割命令转化为操作redis数据库的标准命令,你可以格式化多个参数来构造redis的命令,如下
reply = redisCommand(context, "SET key:%s %s", myid, value);
处理redis应答
当命令被成功执行后redisCommand会有相应的返回值。如果有错误发生,返回值为NULL并且redisReply结构体中的err变量将会被设置成相应的值(请参照Errors章节)。一旦有错误发生context不能被重用并且你需要建立一个新的连接。
redisCommand执行后返回值类型为redisReply。通过redisReply结构体中的type变量可以确定命令执行的情况。
- 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…].*形式获得,用在获取多个数据结果的操作。
执行完命令调用后应该通过freeReplyObject()释放redisReply,对于嵌套对象(比如数组)要注意,并不需要嵌套进行释放,这样是有害的会造成内存破坏。
Important:hiredis当前版本 (0.10.0)当使用异步API时会自己释放replies对象。这意味着你使用异步API时并不需要主动调用freeReplyObject 。relpy对象当回调返回时将会被自动释放。但是这种行为也许会在将来的版本中改变,所以升级时请密切关注升级日志。
清理连接资源
断开连接并且释放context使用以下函数
void redisFree(redisContext *c);
此函数立马关闭socket并且释放创建context时分配的资源。
发送多个命令参数
和redisCommand函数相似,redisCommandArgv函数可以用于传输多个命令参数。函数原型为
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
类似于 lpush, del key1 key2…, zadd key score1 member1 score2 member2…这类命令, 其中 argc是传递参数的个数, argv主要用于传递的string的value, 而argvlen 是每个string的size。
访问Redis代码实例
#ifdef _cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <hiredis/hiredis.h>
void main()
{
redisContext * conn = redisConnect("127.0.0.1", 6379);
if (conn->err)
{
printf("connection error\n");
redisFree(conn);
return;
}
redisReply * reply = redisCommand(conn, "set foo 1234");
freeReplyObject(reply);
reply = redisCommand(conn, "get foo");
printf("%s\n", reply->str);
freeReplyObject(reply);
redisFree(conn);
}
#ifdef _cplusplus
}
#endif
更多推荐



所有评论(0)