为什么单线程的Redis能支持高并发?

亚瑟 等级 676 0 0

一、Redis为什么是单线程

注意:redis 单线程指的是网络请求模块使用了一个线程,即一个线程处理所有网络请求,其他模块仍用了多个线程。

因为CPU不是Redis的瓶颈。Redis的瓶颈最有可能是机器内存或者网络带宽,既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。关于redis的性能,官方网站也有,普通笔记本轻松处理每秒几十万的请求

二、Redis为什么这么快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

三、常用的I/O模型

先来看一下传统的阻塞 I/O 模型到底是如何工作的:当使用 read 或者 write 对某一个文件描述符(File Descriptor 以下简称 FD)进行读写时,如果当前 FD 不可读或不可写,整个 Redis 服务就不会对其它的操作作出响应,导致整个服务不可用。

这也就是传统意义上的,也就是我们在编程中使用最多的阻塞模型:

阻塞式的 I/O 模型并不能满足这里的需求,我们需要一种效率更高的 I/O 模型来支撑 Redis 的多个客户(redis-cli),这里涉及的就是 I/O 多路复用模型了:

在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况,当其中的某些文件描述符可读或者可写时,select 方法就会返回可读以及可写的文件描述符个数。

四、多路I/O复用模型,非阻塞IO

下面举一个例子,模拟一个tcp服务器处理30个客户socket。

假设你是一个监考老师,让30个学生解答一道竞赛考题,然后负责验收学生答卷,你有下面几个选择:

1. 第一种选择:按顺序逐个验收,先验收A,然后是B,之后是C、D。。。这中间如果有一个学生卡住,全班都会被耽误。

这种模式就好比,你用循环挨个处理socket,根本不具有并发能力。

2. 第二种选择:你创建30个分身,每个分身检查一个学生的答案是否正确。 这种类似于为每一个用户创建一个进程或者线程处理连接。

3. 第三种选择,你站在讲台上等,谁解答完谁举手。这时C、D举手,表示他们解答问题完毕,你下去依次检查C、D的答案,然后继续回到讲台上等。此时E、A又举手,然后去处理E和A。

这种就是IO复用模型,Linux下的select、poll和epoll就是干这个的。将用户socket对应的fd注册进epoll,然后epoll帮你监听哪些socket上有消息到达,这样就避免了大量的无用操作。此时的socket应该采用非阻塞模式。

这样,整个过程只在调用select、poll、epoll这些调用的时候才会阻塞,收发客户消息是不会阻塞的,整个进程或者线程就被充分利用起来,这就是事件驱动,所谓的reactor模式。Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一个网络连接其实都对应一个文件描述符)

针对上面的举例在Redis中表现为

有30个redis客户端(考生)与redis服务器的网络连接模块(监考老师)保持TCP连接,客户端会不定时的发送请求给服务器,当有一个redis客户端发起请求,会触发unix系统像epoll这样的系统调用,Redis的I/O 多路复用模块封装了底层的epoll这样的 I/O 多路复用函数,然后转发到相应的事件处理器。

最后多路I/O复用模型图

文件事件处理器使用 I/O 多路复用模块同时监听多个 FD(文件描述符),当 accept、read、write 和 close 文件事件产生时,文件事件处理器就会回调 FD 绑定的事件处理器。

虽然整个文件事件处理器是在单线程上运行的,但是通过 I/O 多路复用模块的引入,实现了同时对多个 FD 读写的监控,提高了网络通信模型的性能,同时也可以保证整个 Redis 服务实现的简单。

本文转自 https://www.100txy.com/article/254,如有侵权,请联系删除。

收藏
评论区

相关推荐

NoSQL从小白到码神 火推08
NoSQL从小白到码神 =========== 本课程适用于运维、开发相关人员。 ---------------- 课程目录: - NoSQL背景 - NoSQL简介 - NoSQL和关系型数据库对比 - Redis简介 - Redis下载安装配置(Linux环境) - Redis优点
qhfl
Redis -----   Redis是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。   Redis有以下特点:     -- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。     -- Redis支持五种数据类型。     -- Redis支持数据库备份。   Redi
redis 学习(常用命令及demo)
redis ===== NOSQL 介绍: 是一项全新的数据库革命性运动,是一个非关系型数据库,在超大规模和高并发的SNS类型网站中应用广泛。 NoSql是以key-value形式存储,特点是:非关系型、分布式、开源的水平可扩展。 特点优势: * 处理超大量数据 * 运行在便宜pc集群上 * 击碎了性能瓶颈 应用场景: 1\
Flink读取数据存入Redis中
1.环境准备:   1.搭建单机版的Redis   2.虚拟机上nc -l 9000方式产生数据 2.需求分析: 通过socket的nc -l 9000方式产生数据,然后将数据以list的形式存入到Redis中 3.flink依赖的redis的pom文件         [redis的依赖](https://www.oschina.net/ac
Redis 2.8.9源码
**本文为作者原创,转载请注明出处:**[http://my.oschina.net/fuckphp/blog/505956](http://my.oschina.net/fuckphp/blog/505956)             Redis 的 ae模块的代码主要分布在 ae.c ae.h 还有 ae\_\*.c 中,分别实现了epoll、evpo
Redis migrate 数据迁移工具
在工作中可能会遇到单点Redis向Redis集群迁移数据的问题,但又不能老麻烦运维来做。为了方便研发自己迁移数据,我这里写了一个简单的Redis迁移工具,希望对有需要的人有用。 #### 本工具支持: * 单点Redis到单点Redis迁移 * 单点Redis到Redis集群迁移 * Redis集群到Redis集群迁移 * Redis集群
Redis 单线程如何处理那么多的并发客户端连接?
为什么Redis是单线程的 ------------- 1.官方答案 因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。 IO多路复用技术 -------- redis 采用网络IO多路复用技术来保证在多连接的
Redis 基础
基本类型 String,hash,list,set,sorted set(zset) 安装 -- 按照README的安装步骤进行 架构原理 ---- ### redis单进程,单线程,并发很多的请求,如何变得很快的呢?? 当我们使用多个redis-cli进行连接的时候,我们首先对通过redis-cli连接到了linux kernel,li
Redis 基础、高级特性与性能调优
本文将从Redis的基本特性入手,通过讲述Redis的数据结构和主要命令对Redis的基本能力进行直观介绍。之后概览Redis提供的高级能力,并在部署、维护、性能调优等多个方面进行更深入的介绍和指导。 本文适合使用Redis的普通开发人员,以及对Redis进行选型、架构设计和性能调优的架构设计人员。 **目录** ------ * 概述
Redis 备份、容灾及高可用实战
郝朝阳,宜搜科技,运维工程师,负责前端运维工作。专注于运维自动化的实现。致力于DevOps思想的推广,帮助企业形成形成自有文化的运维体系建设。 ### 一,Redis简单介绍 Redis是一个高性能的key-value非关系型数据库,由于其具有高性能的特性,支持高可用、持久化、多种数据结构、集群等,使其脱颖而出,成为常用的非关系型数据库。 此
Redis 集群之 Redis
Redis集群官方推荐方案 Redis-Cluster 集群 redis cluster   通过分片实࣫容量扩展   通过主从复制实࣫节点的高可用   节点之间互相通信   每个节点都维护整个集群的节点信息   redis-cluster把所有的物理节点映射到\[0-16383\]slotЇ,cluster 负责维护node<->sl
Redis全面解析
1、什么是Redis? Redis是BSD协议,是一个高性能的key-value非关系型数据库。 2、redis单线程问题 所谓的单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。 redis采用多路复用机制:即多个网络socket复用一个io线程,实际是单个线程通过记录跟踪每一个S
Redis哨兵
Redis-Sentinel是redis官方推荐的高可用性解决方案, 当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。 而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群, 自动发现master
Redis线程模型理解
![](https://img2018.cnblogs.com/blog/1143025/201909/1143025-20190923233927145-1424046209.png) 过程解析: 在redis启动初始化时,redis会将连接应答处理器跟AE\_READABLE事件关联起来,接着如果一个客户端跟redis发起连接,此时会产生一个AE\_
Redis网络模型的源码分析
Redis的网络模型是基于I/O多路复用程序来实现的。源码中包含四种多路复用函数库epoll、select、evport、kqueue。在程序编译时会根据系统自动选择这四种库其中之一。下面以epoll为例,来分析Redis的I/O模块的源码。 epoll系统调用方法 ----------- Redis网络事件处理模块的代码都是围绕epoll那三个系统方法