redis4.0的命令

简介

正文

redisCommand与redisCommandTable

所有的命令一开始都位于server.c文件起始位置的redisCommandTable中,在观察redisCommandTable表之前,我们先看一下redisCommand结构体。

typedef void redisCommandProc(struct client *c);
typedef int *redisGetKeysProc(struct redisCommand *cmd, robj **argv, int argc, int *numkeys);
struct redisCommand {
char *name;
redisCommandProc *proc;
int arity;
char *sflags; /* Flags as string representation, one char per flag. */
int flags; /* The actual flags, obtained from the 'sflags' field. */
/* Use a function to determine keys arguments in a command line.
* Used for Redis Cluster redirect. */
redisGetKeysProc *getkeys_proc;
/* What keys should be loaded in background when calling this command? */
int firstkey; /* The first argument that's a key (0 = no keys) */
int lastkey; /* The last argument that's a key */
int keystep; /* The step between first and last key */
long long microseconds; /* total execution time */
long long calls;/*total execution count */
};

接着我们回到redisCommandTable,此处仅展示其中的getset命令。

struct redisCommand redisCommandTable[] = {
{"get",getCommand,3,"rF",0,NULL,1,1,1,0,0},
{"set",setCommand,-3,"wm",0,NULL,1,1,1,0,0}
};

name字段为指令的名称,客户端发送请求第一个参数就是指令的名称,name在字典中也被用于key来找到对应的redisCommand

proc字段为对应的处理函数,在解析完querybuf里的参数后,redis会执行c->cmd->proc(c)调用对应的处理函数,以set指令为例,在这里执行的就是setCommand。下文会对getset指令做详细的解析。

arity字段遵循以下规则:1. 如果为正,那么指令拥有固定的参数个数。 2.如果为负,那么指令有着最小的参数个数,但参数个数可能会更多。 【参数个数包含指令名称自己】

比如 set指令的最小参数个数为3,set msg "hello" , 但指令参数可能会更多, SET anotherkey "will expire in a minute" EX 60

Command arity follows a simple pattern:

  • positive if command has fixed number of required arguments.
  • negative if command has minimum number of required arguments, but may have more.

Command arity includes counting the command name itself.

sflagsflags代表相同的标志,只是数据的表示形式不同,不同flag代表的意义如下:

  • write - command may result in modifications
  • readonly - command will never modify keys
  • denyoom - reject command if currently out of memory
  • admin - server admin command
  • pubsub - pubsub-related command
  • noscript - deny this command from scripts
  • random - command has random results, dangerous for scripts
  • sort_for_script - if called from script, sort output
  • loading - allow command while database is loading
  • stale - allow command while replica has stale data
  • skip_monitor - do not show this command in MONITOR
  • asking - cluster related - accept even if importing
  • fast - command operates in constant or log(N) time. Used for latency monitoring.
  • movablekeys - keys have no pre-determined position. You must discover keys yourself.

初始化命令

虽然初始化的工作大多数在redisCommandTable配置中已经完成,但还需要在initserverconfig函数中会调用populateCommandTablesflags中的字符值转化为flags中的枚举值,并将命令注册到server.commands字典中。

void populateCommandTable(void) {
int j;
int numcommands = sizeof(redisCommandTable)/sizeof(struct redisCommand); for (j = 0; j < numcommands; j++) {
struct redisCommand *c = redisCommandTable+j;
char *f = c->sflags;
int retval1; while(*f != '\0') {
switch(*f) {
case 'w': c->flags |= CMD_WRITE; break;
case 'r': c->flags |= CMD_READONLY; break;
case 'm': c->flags |= CMD_DENYOOM; break;
case 'a': c->flags |= CMD_ADMIN; break;
case 'p': c->flags |= CMD_PUBSUB; break;
case 's': c->flags |= CMD_NOSCRIPT; break;
case 'R': c->flags |= CMD_RANDOM; break;
case 'S': c->flags |= CMD_SORT_FOR_SCRIPT; break;
case 'l': c->flags |= CMD_LOADING; break;
case 't': c->flags |= CMD_STALE; break;
case 'M': c->flags |= CMD_SKIP_MONITOR; break;
case 'k': c->flags |= CMD_ASKING; break;
case 'F': c->flags |= CMD_FAST; break;
default: serverPanic("Unsupported command flag"); break;
}
f++;
} retval1 = dictAdd(server.commands, sdsnew(c->name), c); serverAssert(retval1 == DICT_OK );
}
}

执行命令

processCommand函数在上篇文章中已经提到过,在解析完querybuf中的字符串,将其转化为client->argcclient->argv中的值后会调用。

processCommand本身做的工作大多数是条件检测,指令是否存在,参数个数是否合法,是否需要验证密码等等。

条件检测通过后,会调用call函数真正调用对应的处理函数。

set指令与字典

如果客户端向服务端发送set msg "hello"请求,在进入到processCommand指令的时候client->argc会被设置为3,client->argv 数组会被填充对应的redisObject lookupCommand会使用client->argv[0]->ptr也就是setserver.commands表中查找对应的redisCommand

server.commands的类型是dict,在服务器启动时初始化。

typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
unsigned long iterators; /* number of iterators currently running */
} dict;

创建一个dict对象时会传入对应的dictType对象,dictType对象就是存储了几个函数指针的对象,redis通过它实现了多态的效果。

typedef struct dictType {
uint64_t (*hashFunction)(const void *key);
void *(*keyDup)(void *privdata, const void *key);
void *(*valDup)(void *privdata, const void *obj);
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
void (*keyDestructor)(void *privdata, void *key);
void (*valDestructor)(void *privdata, void *obj);
} dictType;

当创建command表时,使用的是commandTableDictType,这意味着当对一个key哈希的时候,使用的是dictSdsCaseHash将会无视大小写,比较key值使用的函数是dictSdsKeyCaseCompre

参考文献

redis文档 command

自顶向下redis4.0(3)命令与dict的更多相关文章

  1. 自顶向下redis4.0(4)时间事件与expire

    redis4.0的时间事件与expire 目录 redis4.0的时间事件与expire 简介 正文 时间事件注册 时间事件触发 expire命令 删除过期键值 被动删除 主动删除/定期删除 参考文献 ...

  2. 自顶向下redis4.0(2)文件事件与客户端

    redis4.0的文件事件与客户端 目录 redis4.0的文件事件与客户端 简介 正文 准备阶段 接受客户端连接 处理数据 返回数据结果 参考文献 简介 文件事件的流程大概如下: 在服务器初始化时生 ...

  3. 自顶向下redis4.0(1)启动

    redis4.0的启动流程 目录 redis4.0的启动流程 简介 正文 全局server对象 初始化配置 初始化服务器 事件主循环 参考文献 简介 redis 在接收客户端连接之前,大概做了以下几件 ...

  4. 自顶向下redis4.0(5)持久化

    redis4.0的持久化 目录 redis4.0的持久化 简介 正文 rdb持久化 save命令 bgsave命令 rdb定期保存数据 进程结束保存数据 aof持久化 数据缓冲区 刷新数据到磁盘 ap ...

  5. linux下redis4.0.2集群部署(利用Ruby脚本命令)

    一.原生命令方式和Ruby脚本方式区别 利用Ruby脚本部署和用原生命令部署,节点准备的步骤都是一样的,节点启动后的握手,以及主从.槽分配,利用Ruby脚本一步就能完成,利用原生命令需要一步一步地执行 ...

  6. redis4.0.10安装与常用命令

    ----------- redis安装 ------------------------------------------- 安装reids:https://redis.io/download (4 ...

  7. redis-4.0.8 配置文件解读

    # Redis configuration file example.## Note that in order to read the configuration file, Redis must ...

  8. Redis4.0新特性之-大KEY删除

    接上一篇,我们得知了redis中存在大KEY,那么这个大KEY如何删除呢?本文将从源码角度分析Redis4.0带来的新特性. 在Redis中,对于大KEY的删除一直是个比较头疼的问题,为了不影响服务, ...

  9. Redis4.0新特性 -Lazy Free

    Redis4.0新增了非常实用的lazy free特性,从根本上解决Big Key(主要指定元素较多集合类型Key)删除的风险.笔者在redis运维中也遇过几次Big Key删除带来可用性和性能故障. ...

随机推荐

  1. Vector和ArrayList的联系和区别

    Vector和ArrayList的联系和区别 1.联系: 实用原理相同 功能相同 都是长度可变的数组结构,很多情况下可以互用 2.两者的主要区别:

  2. C语言中的const用法

    Const是什么? const是一个C语言的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程 ...

  3. 来吧,展示!SpringBoot OSS 整合全过程,没见过比这更详细的了

    前言 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量.安全.低成本.高可靠的云存储服务.其数据设计持久性不低于 99.9999999999%(12 ...

  4. Camtasia中对录制视频进行编辑——行为

    小视频的逐渐兴起,让我们的生活变得多姿多彩,同时,也造就了一批新媒体的创业者还有越来越多的网红,这不禁使我们也想加入他们的行列.但是问题来了,拍摄视频后最重要的是对视频进行剪辑,没有一款经济适用的软件 ...

  5. Guitar Pro编辑歌词教程

    吉他是常见的乐器之一,弹唱亦是音乐爱好者们最常见的表演方式.Guitar Pro(win系统)是吉他爱好者最常用的吉他谱制作软件,大家可以在该软件上创作自己的吉他谱.既然有了谱子,那自然是少不了歌词了 ...

  6. 在FL Studio中如何更好地为人声加上混响(进阶教程)

    为人声加上混响是我们在处理人声过程中必不可少的一步.然而,除了直接在人声混音轨道加上混响插件进行调节以外,这里还有更为细节的做法可以达到更好的效果. 步骤一:使用均衡器 在为人声加上混响之前,我们应该 ...

  7. Jmeter如何监测被测服务器资源

    前言 Jmeter自身不支持对服务器的监控,需要安装第三方插件进行扩展. 下载插件 jmeter添加插件步骤,选项-PluginManager 勾选上PerfMon选项,点击右下角的Apply-按钮 ...

  8. C语言项目(一):学生信息管理系统

    实现方式:链表 结构定义 1 typedef struct MyStu MyStudent; 2 typedef struct node Node; 3 typedef Node *pNode; 4 ...

  9. Clickhouse 入门

    clickhouse 简介 ck是一个列式存储的数据库,其针对的场景是OLAP.OLAP的特点是: 数据不经常写,即便写也是批量写.不像OLTP是一条一条写 大多数是读请求 查询并发较少,不适合放置先 ...

  10. java47

    1. 1.List集合根据角标获取元素 import java.util.ArrayList; import java.util.List; public class List集合 { @Suppre ...