Redis基础架构设计及核心网络模型架构演进

嵌入式技术

1335人已加入

描述

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核心的网络模型也被改造成了多线程。

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

Redis的I/O多路复用模块提供的API:

//下面的方法不同版本的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多路复用函数作为子模块,提供给上层接口做封装。

/*下面代码在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 会优先选择时间复杂度为

编辑:黄飞

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分