首页 > 数据库 >Redis线程模型

Redis线程模型

时间:2023-04-12 20:32:45浏览次数:28  
标签:epoll redis 模型 Redis 线程 黄牛 IO 老王

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

单线程

redis的单线程是指redis的网络IO和KV读写是由单个线程来完成的,这是redis对外提供键值存储服务的主要流程。redis的其他功能比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的,并不是指整个redis服务只是一个线程。

为什么是单线程?

1、redis的普通KV存储瓶颈不在CPU,而往往可能受到内存和网络IO的制约。

2、redis中有多种类型的数据操作,甚至包括一些事务处理,如果采用多线程,则会被多线程产生的切换问题而困扰,也可能因为加锁导致系统架构变的异常复杂,更有可能会因为加锁解锁甚至死锁造成的性能损耗。

redis的作者这样说:

Redis线程模型_redis线程模型

总结来说就是对于redis来说单线程的设计能够保证性能,多线程在设计和实现上会带来更多的复杂度。

有多线程的考量吗?

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

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

但是redis的多线程只是在网络数据的读写这类耗时操作上使用了,执行命令仍然是单线程顺序执行。

高性能

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

IO多路复用:

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

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

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

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

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

阻塞IO模型,第三种方式就是IO复用模型了。老王老张老李都找了黄牛买票,这样大家都可以不用跑火车站了,都等黄牛消息,黄牛帮一个人买是买,帮多个人买也是买,反正都要在这里排队,还能多挣几份钱。老王老张老李的请求,都复用这个黄牛搞定了,老王他们节省了时间和精力干了其他事,黄牛一个人花费了差不多一样的时间和业务赚了多份钱。

大概理解了IO多路复用的概念,接下来就看看在redis中是如何实现的。针对IO复用思想前后主要有select|poll|epoll三种技术实现。

1、select

是IO多路复用的第一个实现(1983年),有IO事件发生了,却并不知道是哪几个流,只能无差别轮询所有流,找出后读出数据,或者写入数据的流,同时处理的流越多,轮询时间就越长。就好比黄牛并不会通知老王他们有没有买到票,而是老王自己不停地去问,这样买的人越多,不停给黄牛打骚扰电话的就越多。

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

1)单个进程可监视的fd数量被限制,即能监听端口的大小有限。一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max查看。32bit默认1024个,64bit默认是2048。

2)对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。

3)需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。

2、poll

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

3、epoll

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

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

Redis线程模型_redis_02

执行逻辑是:

Redis线程模型_redis线程模型_03

可以看到redis针对不同的操作系统会选用不同的实现,主流操作系统都有类似epoll的实现作为选择,同时也提供了select方式作为备选。

reactor反应堆模式

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

Redis线程模型_redis_04

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

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

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

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

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

到这里我们从redis的线程模型分析了redis为什么使用单线程,以及从单线程性能依旧很出色分析了基于IO多路复用的反应堆模式请求处理流程。

标签:epoll,redis,模型,Redis,线程,黄牛,IO,老王
From: https://blog.51cto.com/jowin/6186208

相关文章

  • springboot整合阿里云OSS实现多线程下文件上传(aop限制文件大小和类型)
    内容涉及:springboot整合阿里云oss自定义注解及aop的使用:对上传文件格式(视频格式、图片格式)、不同类型文件进行大小限制(视频和图片各自自定义大小)线程池使用:阿里云OSS多线程上传文件阿里云OSS分片上传大文件 业务需求需求一:前端传递单个或多个小文件(这里......
  • 模型+数据=新模型
    链家BELLEhttps://mp.weixin.qq.com/s/73EI7cY10ERQ075v2Uvyqg,中文对话大模型BELLE全面开源!https://github.com/LianjiaTech/BELLE该项目目前已经开源了如下内容,并且在持续更新中:150万中文指令微调数据集以Bloomz-7b1-mt(70亿参数)为基础,分别在20万,60万,100万,200万数据上进行......
  • 多线程篇
    1.Java中实现多线程的几种方法继承Thread类实现Runnable接口实现Callable接口线程池方式创建2.使用Thread、Runnable和Callable创建线程的优缺点采用继承Thread类的方式创建线程的优缺点优点:直接使用this即可获取当前线程,编程简单缺点:已经继承了Thread类......
  • Redis源码之ZipList压缩列表
    List(版本3.2之前)、Hash和SortedSet这三种数据类型,都可以使用压缩列表(ziplist)来保存数据。新版本Redis的quickList底层也是采用zipList支持,Redis版本更新频繁,本文不保证时效性。 一、ziplist结构ziplist是一个特殊双向链表,不像普通的链表使用前后指针关联在一起,它是存储......
  • Redis缓冲区溢出及解决方案
    缓冲区(buffer),是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。一、Redis缓冲区溢出影响在Redis中,主要有三个场景用到了缓冲区的概念。在客户端和服务器端之间进行通信时,用来暂存客户端发......
  • 大模型入门(一)—— LLaMa/Alpaca/Vicuna
    LLaMa模型是Meta开源的大模型,模型参数从7B到65B不等,LLaMa-7B在大多数基准测试上超过了GPT3-173B,而LLaMa-65B和Chinchilla-70B、PaLM-540B相比也极具竞争力。相比于ChatGPT或者GPT4来说,LLaMa可能效果上还有差距,但相比ClosedAI,至少LLaMa论文和模型都开源出来了,目前huggingface......
  • 善借ChatGPT提效,Cursor四问答设计业务简一概念模型示例
    作为一个程序员,对新事物不好奇,没有学习新技术的自觉意识,不知道如何更好地运用工具来提升自己的效率,又如何保持自己的竞争力呢上一次文字创作:梦,仰望星空;路,脚踏实地今天看看辅助编程~上一篇工具Cursor介绍:人人都是程序员,AI神器Cursor辅助,体验自然语言编程第一问:请使用java帮我......
  • BFT最前线|商汤科技发布大模型—商量;昆仑万维将推出大模型天工;王小川大模型产品命名为
    原创|文BFT机器人01商汤科技发布大模型商量4月10日,商汤科技发布大语言模型——商量(SenseChat),其背后的AI大模型「日日新SenseNova」,寓意为“苟日新、日日新、又日新“。和ChatGPT有些类似,商量作为一款聊天助手,具有语言理解、支持问答、解决复杂问题、提供定制化建议、创......
  • CodeGeeX论文发表:揭秘AI辅助编程工具背后的大模型
    近日,CodeGeeX模型迭代v1.5版本上线,用户反馈模型效果和使用效率较之前有大幅提升。恰逢CodeGeeX团队在arxiv上发布了论文,详细介绍了CodeGeeXAI编程辅助工具背后的代码生成大模型的架构、训练过程及推理加速等工作。今天我们对这篇论文的核心信息进行解读,让更多的开发者了解Cod......
  • Redis scan等命令的学习与研究
    Redisscan等命令的学习与研究摘要背景跟前几天说的一个问题类似.为了验证自己的设想,所以晚上继续写脚本进行了一轮次的验证.不过上次讨论时,打击好像都没听懂我说的所以这次准备从基础开始讲起.很多好东西在上来量之后可能会变成坏东西scan命令Redis在2.8之后......