点击上方“芋道源码”,选择“设为星标”
管她前浪,还是后浪?
能浪的浪,才是好浪!
每天 10:33 更新文章,每天掉亿点点头发...
源码精品专栏
- 原创 | Java 2021 超神之路,很肝~
- 中文详细注释的开源项目
- RPC 框架 Dubbo 源码解析
- 网络应用框架 Netty 源码解析
- 消息中间件 RocketMQ 源码解析
- 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析
- 作业调度中间件 Elastic-Job 源码解析
- 分布式事务中间件 TCC-Transaction 源码解析
- Eureka 和 Hystrix 源码解析
- Java 并发源码
来源:juejin.cn/post/
6949929673615179789
- 1. Redis基础架构设计
- 2. Redis核心网络模型架构的演进
- 3. Redis BIO系统的演进
- 4. 小结
Redis真的是单线程吗?网上有很多关于这个问题的讨论,得出的结论也几乎是一致的。本文在讨论这个问题之前,先定义好问题中“单线程”的概念边界:
- 1.单线程指的是“核心网络模型”
- 2.单线程指的是Redis整个服务端架构的设计
对于边界1,那么答案是肯定的,在Redis v6.0 版本以前,Redis的网络模型一直都是单线程模式的,即使到了v6.0版本,所有客户端命令的执行依然是在主线程上完成的;对于边界2,答案是否定的,Redis从发布之出就有两个BIO(background I/O service)
线程来异步处理aof持久化、关闭文件的任务,在Redis v4.0版本中又添加了一个BIO线程,将比较耗时的命令异步化,到了Redis v6.0,Redis核心的网络模型也被改造成了多线程。
在概念边界2的限制下,我们可以得出结论:Redis从来都不是单线程工作的 !在Redis发布近十年来,在系统架构演进过程中都遇到了哪些问题?作者antirez对这些问题是怎样思考的?采取了什么样的方案来改进?探索这些问题对于开发者的成长很有价值,也是本文的写作目的,笔者会结合相关源码与读者共同解答这些问题。
1. Redis基础架构设计
性能优异的服务离不开好的架构设计,Redis使用 I/O multiplexing
实现了单线程接收海量客户端请求;通过单线程Reactor
模型实现了高性能的事件处理;基于条件变量实现的生产者消费者模型构建了自己的BIO系统
。本节先简单介绍一下这些从Redis诞生以来就一直使用的基础架构设计。
1.1 Redis对 I/O multiplexing 的封装
I/O multiplexing 指的是多个网络socket I/O 复用同一个线程,它解决了C10K的问题。Redis将不同的 I/O 多路复用函数封装成相同的 API 提供给上层使用,仅仅以单线程处理网络I/O,就可以为成千上万的客户端提供服务。
Redis的I/O多路复用模块提供的API:
代码语言:javascript复制//下面的方法不同版本的redis在src目录下的ae_epoll.c、ae_evport.c、ae_kqueue.c、ae_select.c代码文件中都有实现
static int aeApiCreate(aeEventLoop *eventLoop)
static int aeApiResize(aeEventLoop *eventLoop, int setsize)
static void aeApiFree(aeEventLoop *eventLoop)
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)
static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask)
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)
Redis可以在多个平台上运行,所以会通过宏定义,根据编译平台的不同,选择不同的I/O多路复用函数作为子模块,提供给上层接口做封装。
代码语言:javascript复制/*下面代码在Redis不同版本的ae.c源码文件中均包含
*Include the best multiplexing layer supported by this system.
* The following should be ordered by performances, descending. */
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
#ifdef HAVE_EPOLL
#include "ae_epoll.c"
#else
#ifdef HAVE_KQUEUE
#include "ae_kqueue.c"
#else
#include "ae_select.c"
#endif
#endif
#endif
Redis 会优先选择时间复杂度为