Redis为什么快

2023-11-18

Redis有多快?

Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 Memcached 差!

为什么这么快?

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中;

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

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

4、使用多路I/O复用模型,非阻塞IO;这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

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

以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:

由于Redis是单线程的,如果是传统的阻塞式IO,那么各个IO操作都将是顺序执行,如果当前的IO不可读或者不可写,整个Redis都将变成阻塞状态,而不会去询问是否其它IO流可读可写。

Redis是I/O多路复用的,采用了select,poll,epoll方法。前两个都是线程不安全的。select的官方文档说:

一个Sock(I/O Stream)插入到select中,如果另一个线程发现当前这个Sock不可用,要收回这个sock,Select是不支持的。你硬关掉了这个sock,最终对于这个流的操作结果可能会有多种。“If a file descriptor being monitored by select() is closed in another thread, the result is unspecified”

epoll是:

(1)线程安全的,

(2)不仅会通知sock有数据,还会具体告知那个sock里有数据。在select中只会告诉你sock里有数据,而不会返回具体的sock,需要你自己去一个一个的找,如果有上万个sock,找起来那是相当的费劲。

(3)只支持Linux平台

 

=================================IO多路复用的实现================================

IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。
 

                                                              多路分离函数select

如上图所示,用户首先将需要进行IO操作的socket添加到select中,然后阻塞等待select系统调用返回。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续进行。

从流程上看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后的最大优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断的调用select读取被激活的socket,即可以达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。

 

然而,使用select函数的优点并不仅限于此。虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只注册自己感兴趣的socket或者IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率。

IO多路复用模型使用了Reactor设计模式实现了这一机制。

 如上图所示,EventHandler抽象类表示IO事件处理器,它拥有IO文件句柄Handle(通过get_handle获取),以及对Handle的操作handle_event(读/写等)。继承于EventHandler的子类可以对事件处理器的行为进行定制。Reactor类用于管理EventHandler(注册、删除等),并使用handle_events实现事件循环,不断调用同步事件多路分离器(一般是内核)的多路分离函数select,只要某个文件句柄被激活(可读/写等),select就返回(阻塞),handle_events就会调用与文件句柄关联的事件处理器的handle_event进行相关操作。

 

 如图5所示,通过Reactor的方式,可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。用户线程注册事件处理器之后可以继续执行做其他的工作(异步),而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时,则通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。由于select函数是阻塞的,因此多路IO复用模型也被称为异步阻塞IO模型。注意,这里的所说的阻塞是指select函数执行时线程被阻塞,而不是指socket。一般在使用IO多路复用模型时,socket都是设置为NONBLOCK的,不过这并不会产生影响,因为用户发起IO请求时,数据已经到达了,用户线程一定不会被阻塞。

IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因为它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO,而非真正的异步IO。

===================异步IO=====================================

“真正”的异步IO需要操作系统更强的支持。在IO多路复用模型中,事件循环将文件句柄的状态事件通知给用户线程,由用户线程自行读取数据、处理数据。而在异步IO模型中,当用户线程收到通知时,数据已经被内核读取完毕,并放在了用户线程指定的缓冲区内,内核在IO完成后通知用户线程直接使用即可。

异步IO模型使用了Proactor设计模式实现了这一机制

相比于IO多路复用模型,异步IO并不十分常用,不少高性能并发服务程序使用IO多路复用模型+多线程任务处理的架构基本可以满足需求。况且目前操作系统对异步IO的支持并非特别完善,更多的是采用IO多路复用模型模拟异步IO的方式(IO事件触发时不直接通知用户线程,而是将数据读写完毕后放到用户指定的缓冲区中)。Java7之后已经支持了异步IO,感兴趣的读者可以尝试使用。

参考:https://blog.csdn.net/chenyao1994/article/details/79491337

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis为什么快 的相关文章

随机推荐

  • 怎么删除win10系统的AdobeFlash

    随着移动端的趋势大流 HTML5应用场景更加的广泛 Flash逐渐走向没落 Flash短期时间并不会彻底消失掉 Adobe Flash FLASH不只是可以制作网页 还可以制作软件AIR 制作动画 制作游戏等等 现在最新版的软件改名为Ani
  • Linux writeback机制

    Linux 采用内存页来缓存磁盘文件内容 从而提高系统整体IO访问性能 这就是我们熟知的pagecache机制 对于进程的一次写文件操作 内核只是简单的把修改写到内存 并把页面标记为脏页 然后直接返回 具体的回写操作 由内核周期性的启动线程
  • springboot 快速集成Redis,非常简单

    gt gt 快速开始 创建springboot项目 引入redis pom依赖 如下
  • vue 软键盘弹起底部按钮顶起来的问题

    vue 软键盘弹起 底部按钮fixed固定定位的button按钮顶起来的问题 底部的button按钮被手机弹起的软键盘顶起来 影响页面美观 html的内容 div class hold div 现在data中定义一个记录高度的属性以及判断b
  • Qt导出数据到EXCEL的两种方式 (*****)

    目录 Qt如何将数据保存成CSV文件 Qt Tablewidget表格数据的导出和导入 Qt导出数据到EXCEL的两种方式 QT将QTableWidget数据保存至Excel Qt Tablewidget表格数据导出到 csv文件 测试 O
  • 网络安全-MS17-010漏洞-永恒之蓝

    网络安全 MS17 010漏洞 永恒之蓝 这个东西怎么说呢 无论是干网络的没干网络的 估计每个人都听说过这个叫做永恒之蓝的东西 这个东东当时可谓是红极一时 现在也有点热度 这个漏洞呢 在win10是不可以的 win8也是不行滴 只有win7
  • Chatgpt与网络安全

    Chatgpt与网络安全 一 简介 2022年11月30日发布的ChatGPT以其丰富的知识与出色的自然语言交互能力引起了现象级的关注 在股市上甚至出现了 ChatGPT概念股 的当下 ChatGPT究竟对于网络安全行业会产生怎样的影响 是
  • Can't connect to local MySQL server through socket '/tmp/mysql.sock'

    出现如题错误时 采取以下解决办法 ps ef grep mysql 找到运行的mysql进程 kill掉 service mysqld restart 重启mysql进程
  • uniapp之uni.navigateBack返回携带参数

    代码 let pages getCurrentPages 获取所有页面栈实例列表 let nowPage pages pages length 1 当前页页面实例 let prevPage pages pages length 2 上一页页
  • k8s挂载目录_k8s学习之存储卷volume详解

    1 案例准备 存储卷以MariaDb来演示 其中每个节点需要准备如下镜像 docker pull mariadb 10 5 2 编写部署mariadb的资源文件 apiVersion apps v1kind Deploymentmetada
  • 【C++】运算符重载实现分数类的四则运算

    题目 定义一个分数类 Fraction 该类具有分子 分母两个成员属性 编写程序完成以下功能 定义合适的构造函数 定义前自增 后自增运算符重载 完成分子 1操作 定义分数加减乘除四则运算的运算符重载函数 Fraction h头文件代码 pr
  • SpringSecurity进阶:OAuth2.0详解

    OAuth2是什么 OAuth是一个为了方便用户登入而使用的授权流程 他的优点是不需要向第三方平台暴露我们的用户名和密码 而是使用授权服务器颁发短期的token和效验token的方式开放部分资源给第三方平台 OAuth是一个授权协议不是认证
  • css解决浏览器记住密码后input框的背景色为淡黄色的代码

    input webkit autofill textarea webkit autofill select webkit autofill webkit text fill color ededed important webkit box
  • 100-The 3n+1 problem

    100 The 3n 1 problem Time limit 3 000 seconds Problems in Computer Science are often classified as belonging to a certai
  • SpringBoot引入本地jar包,引用sdk

    1 引入本地jar包并通过maven打包成jar包 第一步 创建lib包 将所需的本地jar包导入 第二步 在pom文件中引导路径
  • 【开发工具】Python解释器的下载和安装(windows系统)

    Python解释器的下载和安装目录 一 Python解释器种类 二 CPython解释器的下载 三 CPython解释器的安装 四 验证解释器是否安装成功 一 Python解释器种类 CPython C语 开发的解释器 官 应 泛的解释器
  • HTML常用标签--整理篇

    HTML常用标签 文章目录 HTML常用标签 文本标签 HTML格式化标签 HTML图像标签 HTML表格标签 HTML表单标签 文本标签 常 文本标签如下
  • JaveWeb-12JDBC

    目录 一 JDBC 1 什么是JDBC 2 JDBC编程步骤 1 装载相应数据库的JDBC驱动并进行初始化 2 建立JDBC和数据库之间的Connection连接 3 创建Statement或者PreparedStatement接口 执行S
  • 二叉排序树(二叉搜索树)的时间复杂度&空间复杂度

    二叉排序树又称二叉查找树 二叉搜索树 它或是一棵空的二叉树 或是具有下列性质的二叉树 若它的左子树不空 则左子树上所有节点的值均小于根节点的值 若它的右子树不空 则右子树上所有节点的值均大于根节点的值 它的左右子树也都是二叉排序树 如果二叉
  • Redis为什么快

    Redis有多快 Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库 由C语言编写 官方提供的数据是可以达到100000 的QPS 每秒内查询次数 这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 Memcach