范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

高性能IO模型为什么单线程Redis能那么快?

  你好,我是蒋德钧。
  今天,我们来探讨一个很多人都很关心的问题:"为什么单线程的Redis能那么快?"
  首先,我要和你厘清一个事实,我们通常说,Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的,这也是Redis对外提供键值存储服务的主要流程。但Redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
  所以,严格来说,Redis并不是单线程,但是我们一般把Redis称为单线程高性能,这样显得"酷"些。接下来,我也会把Redis称为单线程模式。而且,这也会促使你紧接着提问:"为什么用单线程?为什么单线程能这么快?"
  要弄明白这个问题,我们就要深入地学习下Redis的单线程设计机制以及多路复用机制。之后你在调优Redis性能时,也能更有针对性地避免会导致Redis单线程阻塞的操作,例如执行复杂度高的命令。
  好了,话不多说,接下来,我们就先来学习下Redis采用单线程的原因。
  Redis为什么用单线程?
  要更好地理解Redis为什么用单线程,我们就要先了解多线程的开销。
  多线程的开销
  日常写程序时,我们经常会听到一种说法:"使用多线程,可以增加系统吞吐率,或是可以增加系统扩展性。"的确,对于一个多线程的系统来说,在有合理的资源分配的情况下,可以增加系统中处理请求操作的资源实体,进而提升系统能够同时处理的请求数,即吞吐率。下面的左图是我们采用多线程时所期待的结果。
  但是,请你注意,通常情况下,在我们采用多线程后,如果没有良好的系统设计,实际得到的结果,其实是右图所展示的那样。我们刚开始增加线程数时,系统吞吐率会增加,但是,再进一步增加线程时,系统吞吐率就增长迟缓了,有时甚至还会出现下降的情况。
  为什么会出现这种情况呢?一个关键的瓶颈在于,系统中通常会存在被多线程同时访问的共享资源,比如一个共享的数据结构。当有多个线程要修改这个共享资源时,为了保证共享资源的正确性,就需要有额外的机制进行保证,而这个额外的机制,就会带来额外的开销。
  拿Redis来说,在上节课中,我提到过,Redis有List的数据类型,并提供出队(LPOP)和入队(LPUSH)操作。假设Redis采用多线程设计,如下图所示,现在有两个线程A和B,线程A对一个List做LPUSH操作,并对队列长度加1。同时,线程B对该List执行LPOP操作,并对队列长度减1。为了保证队列长度的正确性,Redis需要让线程A和B的LPUSH和LPOP串行执行,这样一来,Redis可以无误地记录它们对List长度的修改。否则,我们可能就会得到错误的长度结果。这就是多线程编程模式面临的共享资源的并发访问控制问题。
  并发访问控制一直是多线程开发中的一个难点问题,如果没有精细的设计,比如说,只是简单地采用一个粗粒度互斥锁,就会出现不理想的结果:即使增加了线程,大部分线程也在等待获取访问共享资源的互斥锁,并行变串行,系统吞吐率并没有随着线程的增加而增加。
  而且,采用多线程开发一般会引入同步原语来保护共享资源的并发访问,这也会降低系统代码的易调试性和可维护性。为了避免这些问题,Redis直接采用了单线程模式。
  讲到这里,你应该已经明白了"Redis为什么用单线程",那么,接下来,我们就来看看,为什么单线程Redis能获得高性能。
  单线程Redis为什么那么快?
  你好,我是蒋德钧。
  今天,我们来探讨一个很多人都很关心的问题:"为什么单线程的Redis能那么快?"
  首先,我要和你厘清一个事实,我们通常说,Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的,这也是Redis对外提供键值存储服务的主要流程。但Redis的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
  所以,严格来说,Redis并不是单线程,但是我们一般把Redis称为单线程高性能,这样显得"酷"些。接下来,我也会把Redis称为单线程模式。而且,这也会促使你紧接着提问:"为什么用单线程?为什么单线程能这么快?"
  要弄明白这个问题,我们就要深入地学习下Redis的单线程设计机制以及多路复用机制。之后你在调优Redis性能时,也能更有针对性地避免会导致Redis单线程阻塞的操作,例如执行复杂度高的命令。
  好了,话不多说,接下来,我们就先来学习下Redis采用单线程的原因。
  Redis为什么用单线程?
  要更好地理解Redis为什么用单线程,我们就要先了解多线程的开销。
  多线程的开销
  日常写程序时,我们经常会听到一种说法:"使用多线程,可以增加系统吞吐率,或是可以增加系统扩展性。"的确,对于一个多线程的系统来说,在有合理的资源分配的情况下,可以增加系统中处理请求操作的资源实体,进而提升系统能够同时处理的请求数,即吞吐率。下面的左图是我们采用多线程时所期待的结果。
  但是,请你注意,通常情况下,在我们采用多线程后,如果没有良好的系统设计,实际得到的结果,其实是右图所展示的那样。我们刚开始增加线程数时,系统吞吐率会增加,但是,再进一步增加线程时,系统吞吐率就增长迟缓了,有时甚至还会出现下降的情况。
  为什么会出现这种情况呢?一个关键的瓶颈在于,系统中通常会存在被多线程同时访问的共享资源,比如一个共享的数据结构。当有多个线程要修改这个共享资源时,为了保证共享资源的正确性,就需要有额外的机制进行保证,而这个额外的机制,就会带来额外的开销。
  拿Redis来说,在上节课中,我提到过,Redis有List的数据类型,并提供出队(LPOP)和入队(LPUSH)操作。假设Redis采用多线程设计,如下图所示,现在有两个线程A和B,线程A对一个List做LPUSH操作,并对队列长度加1。同时,线程B对该List执行LPOP操作,并对队列长度减1。为了保证队列长度的正确性,Redis需要让线程A和B的LPUSH和LPOP串行执行,这样一来,Redis可以无误地记录它们对List长度的修改。否则,我们可能就会得到错误的长度结果。
  这就是多线程编程模式面临的共享资源的并发访问控制问题。
  并发访问控制一直是多线程开发中的一个难点问题,如果没有精细的设计,比如说,只是简单地采用一个粗粒度互斥锁,就会出现不理想的结果:即使增加了线程,大部分线程也在等待获取访问共享资源的互斥锁,并行变串行,系统吞吐率并没有随着线程的增加而增加。
  而且,采用多线程开发一般会引入同步原语来保护共享资源的并发访问,这也会降低系统代码的易调试性和可维护性。为了避免这些问题,Redis直接采用了单线程模式。
  讲到这里,你应该已经明白了"Redis为什么用单线程",那么,接下来,我们就来看看,为什么单线程Redis能获得高性能。
  单线程Redis为什么那么快?
  通常来说,单线程的处理能力要比多线程差很多,但是Redis却能使用单线程模型达到每秒数十万级别的处理能力,这是为什么呢?其实,这是Redis多方面设计选择的一个综合结果。
  一方面,Redis的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因。另一方面,就是Redis采用了多路复用机制,使其在网络IO操作中能并发处理大量的客户端请求,实现高吞吐率。接下来,我们就重点学习下多路复用机制。
  首先,我们要弄明白网络操作的基本IO模型和潜在的阻塞点。毕竟,Redis采用单线程进行IO,如果线程被阻塞了,就无法进行多路复用了。
  基本IO模型与阻塞点
  你还记得我在第一节课介绍的具有网络框架的SimpleKV吗?
  以Get请求为例,SimpleKV为了处理一个Get请求,需要监听客户端请求(bind/listen),和客户端建立连接(accept),从socket中读取请求(recv),解析客户端发送请求(parse),根据请求类型读取键值数据(get),最后给客户端返回结果,即向socket中写回数据(send)。
  下图显示了这一过程,其中,bind/listen、accept、recv、parse和send属于网络IO处理,而get属于键值数据操作。既然Redis是单线程,那么,最基本的一种实现是在一个线程中依次执行上面说的这些操作。
  但是,在这里的网络IO操作中,有潜在的阻塞点,分别是accept()和recv()。当Redis监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞在accept()函数这里,导致其他客户端无法和Redis建立连接。类似的,当Redis通过recv()从一个客户端读取数据时,如果数据一直没有到达,Redis也会一直阻塞在recv()。
  这就导致Redis整个线程阻塞,无法处理其他客户端请求,效率很低。不过,幸运的是,socket网络模型本身支持非阻塞模式。
  非阻塞模式
  Socket网络模型的非阻塞模式设置,主要体现在三个关键的函数调用上,如果想要使用socket非阻塞模式,就必须要了解这三个函数的调用返回类型和设置模式。接下来,我们就重点学习下它们。
  在socket模型中,不同操作调用后会返回不同的套接字类型。socket()方法会返回主动套接字,然后调用listen()方法,将主动套接字转化为监听套接字,此时,可以监听来自客户端的连接请求。最后,调用accept()方法接收到达的客户端连接,并返回已连接套接字。
  针对监听套接字,我们可以设置非阻塞模式:当Redis调用accept()但一直未有连接请求到达时,Redis线程可以返回处理其他操作,而不用一直等待。但是,你要注意的是,调用accept()时,已经存在监听套接字了。
  虽然Redis线程可以不用继续等待,但是总得有机制继续在监听套接字上等待后续连接请求,并在有请求时通知Redis。
  类似的,我们也可以针对已连接套接字设置非阻塞模式:Redis调用recv()后,如果已连接套接字上一直没有数据到达,Redis线程同样可以返回处理其他操作。我们也需要有机制继续监听该已连接套接字,并在有数据达到时通知Redis。
  这样才能保证Redis线程,既不会像基本IO模型中一直在阻塞点等待,也不会导致Redis无法处理实际到达的连接请求或数据。
  到此,Linux中的IO多路复用机制就要登场了。
  基于多路复用的高性能I/O模型
  Linux中的IO多路复用机制是指一个线程处理多个IO流,就是我们经常听到的select/epoll机制。简单来说,在Redis只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给Redis线程处理,这就实现了一个Redis线程处理多个IO流的效果。
  下图就是基于多路复用的Redis IO模型。图中的多个FD就是刚才所说的多个套接字。Redis网络框架调用epoll机制,让内核监听这些套接字。此时,Redis线程不会阻塞在某一个特定的监听或已连接套接字上,也就是说,不会阻塞在某一个特定的客户端请求处理上。正因为此,Redis可以同时和多个客户端连接并处理请求,从而提升并发性。
  为了在请求到达时能通知到Redis线程,select/epoll提供了基于事件的回调机制,即针对不同事件的发生,调用相应的处理函数。
  那么,回调机制是怎么工作的呢?其实,select/epoll一旦监测到FD上有请求到达时,就会触发相应的事件。
  这些事件会被放进一个事件队列,Redis单线程对该事件队列不断进行处理。这样一来,Redis无需一直轮询是否有请求实际发生,这就可以避免造成CPU资源浪费。同时,Redis在对事件队列中的事件进行处理时,会调用相应的处理函数,这就实现了基于事件的回调。因为Redis一直在对事件队列进行处理,所以能及时响应客户端请求,提升Redis的响应性能。
  为了方便你理解,我再以连接请求和读数据请求为例,具体解释一下。
  这两个请求分别对应Accept事件和Read事件,Redis分别对这两个事件注册accept和get回调函数。当Linux内核监听到有连接请求或读数据请求时,就会触发Accept事件和Read事件,此时,内核就会回调Redis相应的accept和get函数进行处理。
  这就像病人去医院瞧病。在医生实际诊断前,每个病人(等同于请求)都需要先分诊、测体温、登记等。如果这些工作都由医生来完成,医生的工作效率就会很低。所以,医院都设置了分诊台,分诊台会一直处理这些诊断前的工作(类似于Linux内核监听请求),然后再转交给医生做实际诊断。这样即使一个医生(相当于Redis单线程),效率也能提升。
  不过,需要注意的是,即使你的应用场景中部署了不同的操作系统,多路复用机制也是适用的。因为这个机制的实现有很多种,既有基于Linux系统下的select和epoll实现,也有基于FreeBSD的kqueue实现,以及基于Solaris的evport实现,这样,你可以根据Redis实际运行的操作系统,选择相应的多路复用实现。
  小结
  今天,我们重点学习了Redis线程的三个问题:"Redis真的只有单线程吗?""为什么用单线程?""单线程为什么这么快?"
  现在,我们知道了,Redis单线程是指它对网络IO和数据读写的操作采用了一个线程,而采用单线程的一个核心原因是避免多线程开发的并发控制问题。单线程的Redis也能获得高性能,跟多路复用的IO模型密切相关,因为这避免了accept()和send()/recv()潜在的网络IO操作阻塞点。
  搞懂了这些,你就走在了很多人的前面。如果你身边还有不清楚这几个问题的朋友,欢迎你分享给他/她,解决他们的困惑。
  另外,我也剧透下,可能你也注意到了,2020年5月,Redis 6.0的稳定版发布了,Redis 6.0中提出了多线程模型。那么,这个多线程模型和这节课所说的IO模型有什么关联?会引入复杂的并发控制问题吗?会给Redis 6.0带来多大提升?关于这些问题,我会在后面的课程中和你具体介绍。
  每日一问
  我给你提个小问题,在"Redis基本IO模型"图中,你觉得还有哪些潜在的性能瓶颈吗?欢迎在留言区写下你的思考和答案,我们一起交流讨论。

iPhone销量依旧强劲!其他产品营收均下滑果粉之家,专业苹果手机技术研究十年!您身边的苹果专家上周苹果发布了2022财年第三财季的业绩报告,可以看出iPhone13的销量依旧表现强劲,即便是新款iPhone14系列即将发布粉丝贪便宜入手国行iPhone13ProMax准新机,有配置锁,极易被锁如果一台iPhone有配置锁,那就是监管机。监管机虽然便宜,但缺点很多,不仅无法还原和刷机,所属企业还可以隐藏限制iPhone功能抹除反锁iPhone。如果机器被锁,没有任何办法,预算1500元左右,这5款手机性价比超高,有1款还搭载鸿蒙系统您在阅读前请点击上面的关注二字,后续会第一时间为您提供更多有价值的相关内容,感谢您的支持。如果只有1500元左右的预算,想要购买手机的话,可以选择这5款超高性价比的机型,其中华为这红米K50Ultra即将上线,2亿主摄5000mAh120W,台积电骁龙芯坐镇就目前的形式来看,很多人还对Redmi抱有刻板印象,还把Redmi当作以前的红米,只注重核心参数配置的升级,不太注意品质工艺的提升,实际上同样在两千元以内,Redmi还提供了友商所买对不买贵,4款手机最值得买,性能强而且短期价格不会下跌您在阅读前请点击上面的关注二字,后续会第一时间为您提供更多有价值的相关内容,感谢您的支持。很多人在购买手机的时候都犹豫不决,如果购买刚发布的新款机型,可能会出现一两个月就会下调价格曾遭延期的按摩游戏按摩狂改名现已登陆Steam此前,美少女按摩游戏按摩狂NS版宣布延期发售,有消息称游戏制作团队成员是索尼旗下偶像团体日向坂46的粉丝,并用偶像的名字为游戏中角色命名,这种在尺度较大游戏中夹杂私货的行为引起了不8月你好的20句励志温柔文案及海报,值得收藏转眼间,七月已经悄然消逝,八月的脚步姗姗而来,愿你有一个温暖的地方,愿你所付出的汗水都有所收获。七月,再见,八月,你好!1七月的遗憾与小沮丧就不要提起了带着星星点点的光去开启八月的小米米家发布眼镜相机,头上带摄像头的人,谁会不爱呢?8月1日,米家眼镜相机正式发布。这是一款面向未来的智能眼镜形态相机,它首次将头戴形态与强大的潜望双摄系统相结合,辅以高性能AR光机系统,为用户提供可解放双手的第一视角实时拍摄全新体这款跑表为什么能成为性价比之王备受跑者推崇?关注慧跑,助您轻如羽跑无伤如今的跑者拥有跑表的比例越来越高,可穿戴设备厂家为了这个市场自然也是使出浑身解数,推出了琳琅满目的各式跑表。跑者购买适合自己的跑表无非从性能和价格两个维度8月新机大盘点!骁龙8成首选,2999元低价时代即将到来?今天是八月的第一天,这个月将会有多款骁龙8芯片手机和消费者见面作为高通目前性能最强的芯片,骁龙8也是各大手机厂商最好的选择,那么本月都有哪些骁龙8手机呢?小宅给小伙伴们盘点一下。首8月新机前瞻,六款旗舰逐一登场,款款亮点十足步入8月份市场又将迎来多款新机,对于还在犹豫不知道该选择哪款手机的朋友,可以考虑瞧一瞧将会在8月份推出的手机,款款亮点十足。8月2日motoX30Pro新品发布会预计起售价2999
阳事不举,肾虚无力,一剂振阳汤,温阳益肾,振奋起事古代医家古籍对于男子阳事不举病因的论述,较为全面的当属黄帝内经。1。有责之于气虚过甚气大衰而不起不用2。有归于寒热所伤伤于寒则阴缩入,伤于热则纵挺不收3。归为悲恐多思等负面情绪所致三分钟讲透经典仲景左归丸早泄腰酸腿软,怎么办?提到滋阴补肾的药物,不少人第一反应会想到六味地黄丸。其实还有一个药左归丸,也是滋阴补肾的经典名方。那么左归丸适合什么样的症状使用,能治疗哪些疾病呢?左归丸是补贵州4款尴尬酒,在省内是当地人酒桌常客,在外省却没人喝贵州4款尴尬酒,在省内是当地人酒桌常客,在外省却没人喝几十年以来,贵州的白酒产量一直都位列前三居高不下,不仅产量高,白酒品牌也多,而且酒质都很不错,但这只是在本地,外省人可不这么认四川麻辣烫,为啥东北最正宗?不久前,某知名麻辣烫品牌首次公开发行境外上市外资股的相关申请报告获得批复,令拥有超过300家麻辣烫相关企业被称为麻辣烫之乡的哈尔滨宾县,成为一时热点。一道四川街头小吃,为啥会在千里预防感冒咳嗽一起来做个姜糖片最近咳嗽发烧的人越来越多了,很多人都害怕自己阳了。结果弄得很焦虑,吃不下睡不着的,一点小病就跟快没命一样。我觉得还是食疗比吃药好。是药三分毒,今天跟大家分享一种人人都吃得起的生姜。超市4款廉价酒,遇到别忽视,都是不含香精的纯酿,你喝过吗大口吃肉,大碗喝酒,是古人享受生活的一种方式,甚至大诗人白居易因买不起酒喝,还把衣服当了去换酒喝,可见酒在人们生活中的重要地位。到了如今,大家的生活水平越来越好,喝酒也不再是一件奢天然青霉素找着啦!搭配这两样炒一锅,鲜香可口,贼香贼下饭天然青霉素找着啦!搭配这两样炒一锅,鲜香可口,贼香贼下饭人间大事,不外乎吃喝二字。平平淡淡的两个字,却包含了种种对于吃吃喝喝,每个人的理解意义不同,执行的力度也各不相同有的人热衷于海南博鳌乐城先行区内再完成一台国内首例手术海南医学院第一附属医院乐城医院外景。博鳌乐城国际医疗旅游先行区管理局供图中国青年报客户端讯(中青报中青网记者任明超)近日,位于博鳌的海南医学院第一附属医院乐城医院内,完成了一台注射中科大旗案例入选2022年成都市元宇宙典型应用场景名单近日,2022年成都市元宇宙典型应用场景入选名单正式公布,共涉及45个案例。其中,由成都中科大旗软件股份有限公司(以下简称中科大旗)申报的元宇宙黄龙景区智慧文旅场景应用案例入选。随不要折腾您自己,不要起幺蛾子,不要去搞您智力范围以外的东西这个世界只有一种定义,谁的财富多,谁正确。这是唯一的定义。您没有义务教育任何人,您不用搭理任何人,您不用管任何人高兴还是不高兴,您不用给任何人脸面,您不是他们的爹妈,他们更不是您的用ChatGPT写物联网专业稿子是什么水平?导读这下是真的要失业了?上周,大家的朋友圈有没有被ChatGPT聊天机器人刷屏过?这是美国OpenAI公司推出的一款基于AI的对话系统。据官方介绍,ChatGPT能够以对话形式进行