一、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
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐