侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

你知道Redis为什么这么快,了解I/O多路复用、了解跳表

技术  /  管理员 发布于 3个月前   81

今天我们讨论一下 redis 面试高频题,为什么 Redis 那么快?

首先,你可以先想一下答案,我先说下大家普遍的答案:

单线程
基于内存操作,速度快
I/O 多路复用

相信很多人第一时间回答出来上面这些,那么面试官一般会接着问,所有的操作都是单线程吗?单线程为什么快呢,什么是 I/O 多路复用?很多人这个时候就会 G 了。


今天我们好好聊聊,首先我们要知道,我们常说的 Redis 是单线程,主要是指 Redis 在网络 I/O 和 键值的读写操作是有一个线程来完成的,但是其他的一些功能是由其他的线程来执行的,如:

持久化数据落盘
集群主从同步
异步数据删除

所以严格来说,Redis 并不是单线程的。但是在面试中,我们可以先铺垫一下,如果面试官刨根问底,显然是不够的。


1. Redis 为什么用单线程

日常开发中,我们接触都更多是多线程,为了能够提升系统的请求数或者是吞吐率,我们会采用多线程来实现。

但是多线程模式在面临高并发场景下共享资源访问的时候会出现预期和实际结果不一样的情况:

当出现多线程同时在操作一个共享的资源时,我们为了保证结果的正确性,
我们需要有额外的开销来保证,如锁。
当有锁出现了,我们就需要在考虑在什么时候需要获取锁,释放锁,
其中就需要记录锁的状态,可想而知,性能就会下降。


2. 单线程 Redis 为什么那么快

我们正常理解下,多线程在处理能力上是要高于单线程的,但是为啥 Redis 的单线程模型却能达到惊人的每秒 10 万级别的处理能力呢?(采用百度百科)


这就是 Redis 在设计上的优秀之处。

实现高性能的一个方面是 Redis 是基于内存操作,它内部高效的数据结构,如跳表、哈希表等,

比如跳表:

单链表是一种各性能比较优秀的动态数据结构,可以支持快速的插入、删除、查找操作;

通俗来讲就是原始链表建立起来的多级索引的数据结构就称为跳表;

Redis中的有序集合(Sorted Set)就是用跳表(Skip list)来实现的。

还有就是 Redis 采用了 I/O 多路复用机制,从而保障在网络 I/O 中能够高效的处理并发请求,实现高吞吐率。这二者是实现高性能的重要原因。接下来就说说本文最重要的一个 I/O 多路复用机制。


3. I/O 多路复用模型

在 Linux 中,我们都知道 Linux 对文件的操作实际上就是通过文件描述符(fd),通过一个进程监听多个文件描述符,一旦某个文件描述符准备就绪,就会通知对应的程序响应并处理,这种通知的方式优势在于在单个时间内能够处理更多的链接。


Linux 中的 I/O 多路复用机制是指一个线程处理多个 IO 流,也就是我们通常说的 select/epoll。

在 Redis 单线中,允许在内核中同时存在多个监听文件描述符,内核会去监听在这上面的链接请求,一但有请求就会交给 Redis 线程处理,从而实现一个 Redis 线程可以处理多个 IO 流。那么什么是 select、epoll?


3.1 select

select 是一个函数,它支持最大的连接数是 1024 或者 2048,因为在 select 函数需要传入 fd_set 参数,这个 fd_set 的长度取决于操作系统的位数 1024 或者 2048。


其中 fd_set 是一个 bitmap,当数据没有到缓冲区那么就是 0, 反之到了缓冲区就是 1。select 函数的功能是将 fd_set 遍历,判断标识位是否存在变化,若发生变化就发起中断处理。


3.2 epoll

epoll 的首次提出是在 Linux 2.6 内核中,他是为了解决 select 的缺点。


它定义了 epoll_event 结构体来处理,解决 select 存在最大链接数的限制。epoll 不会遍历所有的文件描述符(fd),epoll 会将准备就绪的文件描述符维护在一块指定的空间内,每次从其中取出已经准备就绪的文件描述符进行处理,大大提高了性能。


这就是 select 和 epoll 的区别,想看具体的源码可以自行了解,这里只是简单的描述一下。


3.3 Redis I/O 多路复用模型

在 Redis 中,其网络框架调用采用的是复用机制中的 epoll 机制,让内核监听文件描述符,此时 Redis 线程不会阻塞在某一个特定的监听或已连接的文件描述符,从而可以达到同时处理多个链接请求,提高并发性能。


为了当请求到达时会通知 Redis 线程, select/epoll 提供了基于事件的回调机制,即针对不同事件的发生,调用相应的处理函数。


说说回调机制时如何高效的工作的。当 select/epoll 监测到有文件描述符请求到达时,会发出对应的事件处理,这些事件会被放到一个事件处理队列中,然后 Redis 会对事件进行处理。通过对队列进行轮询,可以提高 CPU 利用率。同时,Redis 在处理事件时,会调用其相应的事件处理函数,实现基于事件的回调。最终使得请求能够第一时间及时响应,再一步提升 Redis 的相应性能。


举个发起读数据的例子,更好的理解上面 Redis I/O 多路复用模型。


当程序发起 Accept 和 Read 事件时, Redis 线程会注册这 Accept 和 Get 事件 对应的回调函数。当 Linux 内核监听到有链接请求或者读数据的请求时,会触发 Accept 和 Read 事件,与此同时调用 Redis 的 Accept 和 Get 函数进行数据处理。


4. 总结

现在,我们知道啦,Redis 为什么快了吧。

Redis 单线程是指在网络 I/O 和 键值的读写操作是有一个线程来完成的,采用单线程的好处是避免了多线程并发需要竞争获取锁。

单线程之所以性能高效是因为其选择了 I/O 多路复用模型。


转:

https://learnku.com/articles/73927

  • 上一条:
    来自知乎的最污技术解读,只有程序员才会秒懂
    下一条:
    2022年12月14日我可能阳了,就是感染新冠病毒了
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 性能测试工具、HTTP基准测试工具:wrk(0个评论)
    • namesilo域名+香港服务器+acme.sh给网站生成免费ssl证书流程步骤(0个评论)
    • 控制反转IOC设计模式简单的示例代码(0个评论)
    • 来自京东开发者的接口优化的常见方案实战总结(0个评论)
    • 最新访问谷歌Google镜像/学术/搜索_GitHub镜像/下载加速链接2023/2/16持续更新(0个评论)
    • 近期文章
    • 在go语言中使用GoPDF包把html生成PDF文件示例(0个评论)
    • 在go语言中创建和解析(读取)符号链接示例(0个评论)
    • ubuntu 22.04系统中报错:Python 3.6 is no longer supported by the Python core team...解决方式(0个评论)
    • Laravel 10.4版本发布(0个评论)
    • mysql5.7中实现分区表及分区where in查询示例及分区分表对比浅析(0个评论)
    • nginx + vue配置实现同域名下不同路径访问不同项目(0个评论)
    • 在laravel框架中的5个HTTP客户端技巧分享(0个评论)
    • 在go语言中使用FFmpeg库实现PCM音频文件编码为mp3格式文件流程步骤(0个评论)
    • gopacket免安装Pcap实现驱动层流量抓包流程步骤(0个评论)
    • 在laravel项目中实现密码强度验证功能推荐扩展包:password-strength(0个评论)
    • 近期评论
    • 博主 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 @ xiaoB 你只管努力,剩下的叫给天意;天若有情天亦老,..
    • xiaoB 在

      2023年国务院办公厅春节放假通知:1月21日起休7天中评论 会不会春节放假后又阳一次?..
    • BUG4 在

      你翻墙过吗?国内使用vpn翻墙可能会被网警抓,你需了解的事中评论 不是吧?..
    • 博主 在

      go语言+beego框架中获取get,post请求的所有参数中评论 @ t1  直接在router.go文件中配就ok..
    • Jade 在

      如何在MySQL查询中获得当月记录中评论 Dear zongscan.com team, We can skyroc..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客