百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Redis(一):单线程为何还能这么快?

mhr18 2024-11-17 13:31 24 浏览 0 评论

提到redis马上在我们脑海中会浮现出这样一些关键字:单线程、高性能、内存数据库、kv存储......这些关键字都从不同层面描述了redis的一些相关特性和技术实现。那么为什么redis具备这些特性以及是如何实现的,本文将进行一一分析。

一、单线程

1.1 为什么是单线程

  1. 总结Redis的普通KV存储瓶颈不在 CPU,而往往可能受到内存和网络I/O 的制约。
  2. Redis 中有多种类型的数据操作,甚至包括一些事务处理,如果采用多线程,则会被多线程产生的切换问题而困扰,也可能因为加锁导致系统架构变的异常复杂造成性能损耗。

Redis作者咋说的:

总结来说就是对于redis来说单线程的设计能够保证性能,多线程在设计和实现上会带来更多的复杂度。但是使用单线程的方式确实无法很好发挥多核CPU 的性能,可以通过在单机开多个Redis 实例来完善!

1.2 有多线程的考量吗

Redis4.0版本对于一些大键值对的删除操作,引入多线程来非阻塞地释放内存空间,能减少对 Redis 主线程阻塞的时间,提高执行的效率。

Redis6.0 引入多线程来提高网络 IO 读写性能。

这里要注意的是Redis 的多线程只是在网络数据的读写这类耗时操作上使用了, 执行命令仍然是单线程顺序执行。Redis6中默认是禁用多线程的,可以通过修改redis的配置文件中io-threads-do-reads=true来开启。除此之外还需要设置现场的数量才能正真开启多线程,配置参数为io-threads 3表示开启三个线程。

线程设置建议:关于线程数的设置,官方的建议是如果为 4 核的 CPU,建议线程数设置为 2 或 3,如果为 8 核 CPU 建议线程数设置为 6,线程数一定要小于机器核数,线程数并不是越大越好。

二、高性能

通常我们的理解是单线程性能没有多线程好,那redis又是如何做到高性能的了?

2.1 I/O多路复用

这是我们最多看到的一句解释,redis使用了I/O多路复用的模式,所以性能高,那么到底什么是I/O多路复用模型,以及在redis中怎么实现的。我这里先打几个比方来方便大家理解。

要过年了,老王去火车站买票回家过年,春运期间票不好买,老王买了三天买到了一张退票。这样一个场景老王有三种方式来完成这次买票:

方式一:老王去到火车站售票大厅,在长椅上躺了两夜,终于在第三天等到了一张票,兴高采烈的回家了。(老王在火车站待了三天,其他啥事没干,还耗费了6桶泡面一床棉被)

方式二:老王去到火车站售票大厅买票,没买到,之后每天中午再去一次,终于在第三天买到了票。(老王往返车站6次,路上耗费了3小时,不过这几天其他时间送了三天外卖,又给家里的老婆挣了不少钱)

方式三:老王去到火车站售票大厅买票,没买到,这时候看到一个黄牛在帮别人买票,老王想着还有外卖要送,就让黄牛帮他买,三天后黄牛买到了票通知他下班后来取。(老王往返车站两次,路上耗费1小时,给了黄牛50块手续费,其他时间送了三天外卖,由于老王临近过年每天都没耽搁的加班送外卖,平台奖励了老王500块)

第一种方式就是阻塞IO模型,第二种方式就是非阻塞IO模型,第三种方式就是IO复用模型了。除了老王,老张老李......都找了黄牛买票,这样大家都可以不用跑火车站了,等黄牛消息就行。黄牛帮一个人买是买,帮多个人买也是买,反正都要在这里排队,还能多挣几份钱。老王老张老李的请求,都复用这个黄牛搞定了,老王他们节省了时间和精力干了其他事,黄牛一个人花费了近乎一样的时间和精力赚了多份钱。 大概理解了I/O多路复用的概念接下来就看看在redis中是如何实现的。针对IO复用思想前后主要有select, poll, epoll 三种技术实现。

Select:select是I/O多路复用的第一个实现(1983年),有I/O事件发生了,却并不知道是哪几个流,只能无差别轮询所有流,找出能读出数据,或者写入数据的流,同时处理的流越多,轮询时间就越长。就好比黄牛给多个人买票,但是并不知道买到票是谁的,只能不停的去问所有买票的人是不是你的。这样买票的人越多,黄牛要问的人就越多。

select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:

  1. 单个进程可监视的fd数量被限制,即能监听端口的大小有限。一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048.
  2. 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。
  3. 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。

Poll:poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了多次无谓的遍历。它没有最大连接数的限制,原因是它是基于链表来存储的。

Epoll:epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。epoll实际上是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。

通过以上三种技术实现的分析,epoll无疑是最好的选择,那么redis中是这样选择的吗?先来看下redis在做多路复用函数选择时的代码实现:

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针对不同的操作系统会选用不同的实现,主流操作系统都有类似epoll的实现作为选择,同时也提供了select方式作为备选。

2.2 Reactor(反应堆模式)

有了epoll等IO复用技术的支撑,接下来我们看看redis是如何利用IO复用来串连起socket连接请求和具体任务处理的。


由上图可以看出redis处理并发客户端连接的方式是利用epoll来实现IO多路复用,将连接信息和事件放到队列中,之后依次放到文件事件分派器,事件分派器将事件分发给事件处理器。这种处理方式叫做反应堆模式。Redis是基于Reactor模式(反应堆模式)开发了自己的网络模型,形成了一个完备的基于IO复用的事件驱动服务器。

上面我们了解到epoll方式的多路复用实现已经是很高性能的了,那么为什么redis在此基础上还要基于Reactor来实现自己的网络模型了?

epoll将收集到的可读写事件全部放入队列中等待业务线程的处理,此时线程池的工作线程拿到任务进行处理,实际场景中可能有很多种请求类型,工作线程每拿到一种任务就进行相应的处理,处理完成之后继续处理其他类型的任务,工作线程需要关注各种不同类型的请求,对于不同的请求选择不同的处理方法,因此请求类型的增加会让工作线程复杂度增加,维护起来也变得越来越困难。

如果我们在epoll的基础上进行业务区分,并且对每一种业务设置相应的处理函数,每次来任务之后对任务进行识别和分发,每种处理函数只处理一种业务,这种模型也就是Reactor反应堆模式的设计思路。

通俗点讲就是黄牛的业务做的很好,找黄牛除了买火车票还有买机票电影票的,那么黄牛每次处理不同的业务的时候就要不断跑来跑去切换业务场景,显然这样业务没法做大做强,黄牛就找了多个业务员,负责专门买火车票,飞机票,电影票,这样黄牛接到不同业务的时候就交给不同的业务员去做,接客能力一下就增强了。

三、告一段落

到这里我们从redis的线程模型分析了redis为什么使用单线程,以及从单线程性能依旧很出色分析了基于I/O多路复用的反应堆模式请求处理流程。下一篇将从redis的内存模型来解读redisdb的数据结构以及内存回收机制。

文章导航

类别

标题

发布

Redis

Redis(一):单线程为何还能这么快

本文章

Redis(二):内存模型及回收算法

2021.10.22

Redis(三):持久化

2021.10.27

Redis(四):主从同步

即将上线

Redis(五):集群搭建

即将上线

Redis(六):实战应用

即将上线



Elasticsearch

Elasticsearch:概述

2021.10.20

Elasticsearch:核心

2021.10.25

Elasticsearch:实战

2021.10.29

Elasticsearch写入流程详解

即将上线

Elasticsearch查询流程详解

即将上线

Elasticsearch集群一致性

即将上线

Lucene的基本概念

即将上线

Elasticsearch部署架构和容量规划

即将上线



RocketMQ

RocketMQ—NameServer总结及核心源码剖析

2021.11.01

RocketMQ—深入剖析Producer

即将上线

Broker—启动流程源码解密

即将上线

Broker—接受消息处理流程解密

即将上线



Tomcat源码分析

Tomcat(一):项目结构及架构分析

即将上线

Tomcat(二):启动关闭流程分析

即将上线

Tomcat(三):应用加载原理分析

即将上线

Tomcat(四):网络请求原理分析

即将上线

Tomcat(五):嵌入式及性能调优

即将上线



Nacos

Nacos项目结构及架构分析

即将上线

Nacos服务注册源码解析

即将上线

Nacos配置管理源码解析

即将上线

Nacos2.0版本优化功能解析

即将上线



Netty

计算机网络&nio核心原理

即将上线

详细解读kafka是如何基于原生nio封装网络通信组件的?

即将上线

netty初识之核心组件介绍

即将上线

源码解析netty服务端,端口是如何拉起来的?新连接接入又如何处理?

即将上线

深入netty中各种事件如何在pipeline中传播的?

即将上线

网络编程中拆包粘包是什么?kafka以及netty是如何解决的?

即将上线

深入解读netty中最为复杂的缓存分配是如何进行的?

即将上线

源码分析netty、kafka、sentinel中不同时间轮实现方式以及细节

即将上线

尝试从上帝角度对比kafka&netty中的性能优化,各种设计模式的丰富运用

即将上线

Netty在Rocketmq中的实践,RocketMq的消息协议解读

即将上线



关注IT巅峰技术,私信作者,获取以下2021全球架构师峰会PDF资料。



?

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: