redis7源码分析:redis 单线程模型解析,一条get命令执行流程
有了下文的梳理后
redis 启动流程
再来解析redis 在单线程模式下解析并处理客户端发来的命令
1. 当 client fd 可读时,会回调readQueryFromClient函数
void readQueryFromClient(connection *conn) {
client *c = connGetPrivateData(conn);
int nread, big_arg = 0;
size_t qblen, readlen;
/* Check if we want to read from the client later when exiting from
* the event loop. This is the case if threaded I/O is enabled. */
// 这里是多线程模型走的地方,被文分析单线程模式,不走这里
if (postponeClientRead(c)) return;
......
/* There is more data in the client input buffer, continue parsing it
* and check if there is a full command to execute. */
// 走到这里,开始处理客户端发来的命令
if (processInputBuffer(c) == C_ERR)
c = NULL;
}
2. 分析processInputBuffer
int processInputBuffer(client *c) {
/* Keep processing while there is something in the input buffer */
while(c->qb_pos < sdslen(c->querybuf)) {
if (c->flags & CLIENT_BLOCKED) break;
if (c->flags & CLIENT_PENDING_COMMAND) break;
if (isInsideYieldingLongCommand() && c->flags & CLIENT_MASTER) break;
if (c->flags & (CLIENT_CLOSE_AFTER_REPLY|CLIENT_CLOSE_ASAP)) break;
......
/* Multibulk processing could see a <= 0 length. */
if (c->argc == 0) {
resetClient(c);
} else {
if (io_threads_op != IO_THREADS_OP_IDLE) {
serverAssert(io_threads_op == IO_THREADS_OP_READ);
c->flags |= CLIENT_PENDING_COMMAND;
break;
}
/* We are finally ready to execute the command. */
// 最终在这里执行命令
if (processCommandAndResetClient(c) == C_ERR) {
return C_ERR;
}
}
}
......
return C_OK;
}
2.1 分析 processCommandAndResetClient
int processCommandAndResetClient(client *c) {
int deadclient = 0;
client *old_client = server.current_client;
server.current_client = c;
// 这里处理命令
if (processCommand(c) == C_OK) {
commandProcessed(c);
/* Update the client's memory to include output buffer growth following the
* processed command. */
updateClientMemUsageAndBucket(c);
}
if (server.current_client == NULL) deadclient = 1;
/*
* Restore the old client, this is needed because when a script
* times out, we will get into this code from processEventsWhileBlocked.
* Which will cause to set the server.current_client. If not restored
* we will return 1 to our caller which will falsely indicate the client
* is dead and will stop reading from its buffer.
*/
server.current_client = old_client;
/* performEvictions may flush slave output buffers. This may
* result in a slave, that may be the active client, to be
* freed. */
return deadclient ? C_ERR : C_OK;
}
2.2 分析 processCommand
int processCommand(client *c) {
......
/* Now lookup the command and check ASAP about trivial error conditions
* such as wrong arity, bad command name and so forth. */
// 这里搜索命令,sentinel的命令也是在这里处理
// 不像老版本,6.0以前,使用的是命令覆盖的方式,改用搜索
c->cmd = c->lastcmd = c->realcmd = lookupCommand(c->argv,c->argc);
......
/* Exec the command */
if (c->flags & CLIENT_MULTI &&
c->cmd->proc != execCommand &&
c->cmd->proc != discardCommand &&
c->cmd->proc != multiCommand &&
c->cmd->proc != watchCommand &&
c->cmd->proc != quitCommand &&
c->cmd->proc != resetCommand)
{
queueMultiCommand(c, cmd_flags);
addReply(c,shared.queued);
} else {
//最终普通命令调用 call函数执行
call(c,CMD_CALL_FULL);
c->woff = server.master_repl_offset;
if (listLength(server.ready_keys) && !isInsideYieldingLongCommand())
handleClientsBlockedOnKeys();
}
}
2.3 call函数在server.c中
void call(client *c, int flags) {
......
server.in_nested_call++;
c->cmd->proc(c);
server.in_nested_call--;
......
}
最终调用cmd 对应的proc
假设是get 请求,那么在lookupCommand时就会找到对应的command 对象,由redisCommandTable可知,对应方法为getCommand
t_string.c
void getCommand(client *c) {
getGenericCommand(c);
}
int getGenericCommand(client *c) {
robj *o;
// 搜索db中数据
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL)
return C_OK;
if (checkType(c,o,OBJ_STRING)) {
return C_ERR;
}
// 将数据写入到输出缓存中,待eventloop 发现可写后发送
addReplyBulk(c,o);
return C_OK;
}
redis7源码分析:redis 单线程模型解析,一条get命令执行流程的更多相关文章
- [源码分析] 带你梳理 Flink SQL / Table API内部执行流程
[源码分析] 带你梳理 Flink SQL / Table API内部执行流程 目录 [源码分析] 带你梳理 Flink SQL / Table API内部执行流程 0x00 摘要 0x01 Apac ...
- ThreadPoolExecutor源码分析-面试问烂了的Java线程池执行流程,如果要问你具体的执行细节,你还会吗?
Java版本:8u261. 对于Java中的线程池,面试问的最多的就是线程池中各个参数的含义,又或者是线程池执行的流程,彷佛这已成为了固定的模式与套路.但是假如我是面试官,现在我想问一些更细致的问题, ...
- Spring源码分析之AOP从解析到调用
正文: 在上一篇,我们对IOC核心部分流程已经分析完毕,相信小伙伴们有所收获,从这一篇开始,我们将会踏上新的旅程,即Spring的另一核心:AOP! 首先,为了让大家能更有效的理解AOP,先带大家过一 ...
- Memcached源码分析之线程模型
作者:Calix 一)模型分析 memcached到底是如何处理我们的网络连接的? memcached通过epoll(使用libevent,下面具体再讲)实现异步的服务器,但仍然使用多线程,主要有两种 ...
- springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)
在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...
- 源码分析——从AIDL的使用开始理解Binder进程间通信的流程
源码分析——从AIDL的使用开始理解Binder进程间通信的流程 Binder通信是Android系统架构的基础.本文尝试从AIDL的使用开始理解系统的Binder通信. 0x00 一个AIDL的例子 ...
- 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07
百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...
- 【Redis】事件驱动框架源码分析(单线程)
aeEventLoop初始化 在server.c文件的initServer函数中,对aeEventLoop进行了初始化: 调用aeCreateEventLoop函数创建aeEventLoop结构体,对 ...
- spring源码分析系列 (15) 设计模式解析
spring是目前使用最为广泛的Java框架之一.虽然spring最为核心是IOC和AOP,其中代码实现中很多设计模式得以应用,代码看起来简洁流畅,在日常的软件设计中很值得借鉴.以下是对一些设计模式的 ...
- jQuery 2.0.3 源码分析Sizzle引擎 - 词法解析
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 浏览器从下载文档到显示页面的过程是个复杂的过程,这里包含了重绘和重排.各家浏览器引擎的工作原理略有差别,但也有一定规则. 简 ...
随机推荐
- [转帖]tidb4.0.4使用tiup扩容TiKV 节点
https://blog.csdn.net/mchdba/article/details/108896766 环境:centos7.tidb4.0.4.tiup-v1.0.8 添加两个tikv节点 ...
- [转帖]解决jmeter请求响应结果乱码的问题
如下图所示,请求百度接口的时候,发现返回的信息里面中文是乱码 这个时候我们只需要改一下jmeter里的配置文件,设置响应结果的字符编码为UTF-8就行了. 进入jmeter安装目录/bin中,找到jm ...
- Python学习之四_部分battery的学习
Python学习之四_部分battery的学习 CentOS升级pip的方法 yum install python3 之后, 一般centos的版本都很低, 有时候很多module 是无法安装的. 一 ...
- [转载]Linux常用的可插拔认证模块(PAM)pam_limits.so、pam_rootok.so和pam_userdb.so的详解
Linux常用的可插拔认证模块(PAM)pam_limits.so.pam_rootok.so和pam_userdb.so的详解 https://blog.51cto.com/udb1680/1846 ...
- 根目录被赋予777 -R权限后的处理过程
解决某研发手残导致的系统宕机问题的处理过程 背景 2022.8.8 公司一台服务器出现了宕机的现象: 所有的人都无法远程, 都提示密码错误. 但是网络还是通的. 2022.8.12 出差前一天去了一趟 ...
- 从DevOps状态报告看技术团队的文化建设
本文源自一次内部分享,借由此机会又把历年的DevOps状态报告翻看了一遍,其实大多数时候我们对于DevOps的理解都在于流程,工具,实践这些看得见摸得着的东西,但就像文末的几点思考所说的那样,我们一直 ...
- vue 半场动画进入状态
<style> .box{ width: 30px; height: 30px; border-radius: 50%; background: red; } </style> ...
- golang实现的 https 协议的四层代理和七层代理
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 四层代理 在 tcp 这一层转发很简单. http 协议是 ...
- OpenIM集群(非k8s)部署文档
自行部署etcd/zookeeper/mysql/kafka/mongo/redis集群,可以根据此性能评估服务器需求. 以下是针对一台华为云主机s3的压测数据:8核16G内存,普通磁盘(非SSD)( ...
- openim支持十万超级大群
钉钉:根据相关监管要求,新建普通群人数上限调整为500人,不支持群人数扩容. 企业微信:内部群聊人数最多支持2000人,群个数无上限.全员群人数最多支持10000人.企业微信用户创建的外部群人数最多支 ...