Redis是著名的NoSQL键值数据库服务器,为了保证效率,其数据都缓存在内存中。与Memcached相比,Redis支持的数据类型更多,包括String,List,Set,Zset和Hash。下面简单介绍一下Redis内部运行流程。

Redis是单线程运行的。在这个主线程中,Redis通过循环不断接收处理外部事件,处理外部事件同时产生的网络操作,如回复客户端请求,也转化为事件进行处理。

Redis的主函数在redis.c文件中,主函数最终调用aeMain函数进入事件处理循环,aeMain即是Redis运行的核心部分。下面详细看一下aeMain函数:

void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop= 0;
while(!eventLoop->stop) {
if(eventLoop->beforesleep != NULL)
eventLoop->beforesleep(eventLoop);
aeProcessEvents(eventLoop,AE_ALL_EVENTS); }
}

可以看到,这个函数非常简单。每次循环中,Redis都依次调用beforeSleep函数和aeProcessEvents函数。

aeProcessEvents函数是具体处理外部事件的函数,它将会处理外部(也包括内部事件)事件。在调用aeProcessEvents之前,redis都会调用beforeSleep函数。

我们先看看aeProcessEvents函数,它会处理两类事件:定时器事件以及文件(包括网络)相关事件。对应的函数分别是processTimeEvents和readQueryFromClient(其对应接收客户端数据操作,而写操作对应的函数是sendReplyToClient,这两个网络事件相关的函数具体实现在networking.c中)。

具体来看readQueryFromClient,它在接收完客户端数据后,调用processInputBuffer.后续具体流程是:

processInputBuffer->processCommand->call。

其中processCommand会通过lookupCommand函数,查找Redis对应执行的命令,然后调用call函数。Redis支持的命令定义在redis.c的变量redisCommandTable中。

call函数是redid执行命令的核心函数。其中具体执行命令的语句是

c->cmd->proc();//lookupCommand函数查找到的命令处理函数

Redis在本地执行完命令后,如果需要将数据写入AOF文件,或者将数据发送给slave服务器,则调用propagate函数。propagate函数会调用feedAppendOnlyFile和replicationFeedSlaves,通过函数名即能确认两个函数具体功能。

feedAppendOnlyFile函数将命令存入缓存,在本次事件循环结束后,进入下次事件循环之前,redis调用beforeSleep函数时会将缓存写入本地磁盘,具体细节可参考Redis持久化相关介绍。replicationFeedSlaves调用addReply,最终调用aeCreateFileEvent创建一个Socket事件将命令同步到slave.这个事件将在下次事件循环时处理,具体执行的函数将是sendReplyToClient。

现在转回来看c->cmd->proc();以zadd命令为例:

zadd命令对应的函数是zaddCommand,具体实现函数是zaddGenericCommand,其在内存中修改完zset数据(请参考zset实现介绍)后,同样也调用addReply(通过addReplyLongLong)回复客户端,Redis在aeMain的下一次循环时处理对应产生的socket事件。

以上即Redis处理客户端命令的整个过程。需要说明的是,对于每个写操作命令来说,Redis回复客户端之前,将会在内存中更新命令结果,同时可以选择是否同步将命令写入磁盘(可以在beforeSleep函数中会将AOFbuffer写入磁盘,具体参考Redis持久化介绍),然后才会回复客户端,并将命令更新结果同步到slave。

深入理解Redis:命令处理流程的更多相关文章

  1. REdis命令处理流程处理分析

    分析版本:REdis-5.0.4. REdis命令处理流程可分解成三个独立的流程(不包括复制和持久化): 1) 接受连接请求流程: 2) 接收请求数据和处理请求流程,在这个过程并不会发送处理结果给Cl ...

  2. redis 命令的调用过程

    参考文献: Redis 是如何处理命令的(客户端) 我是如何通过添加一条命令学习redis源码的 从零开始写redis客户端(deerlet-redis-client)之路--第一个纠结很久的问题,r ...

  3. 深入理解Redis:底层数据结构

    简介 redis[1]是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...

  4. Netty开发redis客户端,Netty发送redis命令,netty解析redis消息

    关键字:Netty开发redis客户端,Netty发送redis命令,netty解析redis消息, netty redis ,redis RESP协议.redis客户端,netty redis协议 ...

  5. 深入理解redis复制原理

    原文:深入理解redis复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof ...

  6. Redis(二):redis命令构建及关键属性解析

    上一篇文章,我们从框架层面,主要介绍了redis的启动过程,以及主要的命令处理流程逻辑.这些更多的都是些差不多的道理,而要细了解redis,则需要更细节的东西. 今天我们稍微内围的角度,来看看几个命令 ...

  7. Redis命令拾遗二(散列类型)

    本文版权归博客园和作者吴双共同所有,欢迎转载,转载和爬虫请注明原文地址 :博客园蜗牛NoSql系列地址  http://www.cnblogs.com/tdws/tag/NoSql/ Redis命令拾 ...

  8. Shell命令和流程控制

    Shell命令和流程控制 在shell脚本中可以使用三类命令: 1)Unix 命令: 虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令.这些命令通常是用来进行文件和文字 ...

  9. Redis命令

    redis的常用命令主要分为两个方面.一个是键值相关命令.一个是服务器相关命令(redis-cli进入终端) 1.键值相关命令 keys * 取出当前所有的key exists name 查看n是否有 ...

随机推荐

  1. iOS - UIToolbar

    前言 NS_CLASS_AVAILABLE_IOS(2_0) __TVOS_PROHIBITED @interface UIToolbar : UIView <UIBarPositioning& ...

  2. [转]瓦的VPS后台kiwivm面板使用+安装AMH+装VPN

    参考网址:http://u-lis.com/archives/4159 ZC:网页图片保存于“百度云 OsSkill --> 全部文件 > 知识__来自网页 > 瓦 > 瓦_面 ...

  3. caffe中的Blob块

    首先说明:Blob定义了一个类模板. 让我们看一下Blob的头文件里有什么哈: 定义了一个全局变量: const ; 看看它的构造函数: Blob() : data_(), diff_(), coun ...

  4. 什么是Plist文件

    直接将数据直接写在代码里面,不是一种合理的做法.如果数据经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低 因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据.如果 ...

  5. spring中的Log4jConfigListener作用和webapp.root的设置

    转:http://blog.sina.com.cn/s/blog_7bbf356c01016wld.html 使用spring中的Log4jConfigListener有如如下好处:     1. 动 ...

  6. oracle中修改表名

    <<<备忘>>>   answer1: ALTER TABLE old_table_name RENAME TO new_table_name;(大写为系统命令) ...

  7. python字符串替换的2种有效方法

    python 字符串替换可以用2种方法实现:1是用字符串本身的方法.2用正则来替换字符串 下面用个例子来实验下:a = 'hello word'我把a字符串里的word替换为python1用字符串本身 ...

  8. java 生成随机数

    本段代码是生成的六位随机数.也可修改生成任意位随机数. int[] array = {0,1,2,3,4,5,6,7,8,9}; Random rand = new Random(); for (in ...

  9. html 实体 => htmlspecialchars

    因为没有办法判断用户输入的数据是否安全, 可能含有和sql语句相冲突的字符,比如 '  " < >,那就有一个办法, 把这些特殊字符处理一下,比如吧空格符号变成 ,这样sql语句 ...

  10. hook_schema 小总结

    1, primary key 可以带空格 做为下表 但field就不行 2, dev_node 仅为下标 'primary key' => array('nid'),    'foreign k ...