<div id="article_content" class="article_content clearfix">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-b3c43d3711.css">
<div id="content_views" class="htmledit_views">
<h3><a name="t0"></a>一、Redis有多快?</h3>
<p style="text-indent:33px;">Redis是基于内存运行的高性能 K-V 数据库,官方提供的测试报告是单机可以支持约10w/s的QPS</p>
<p style="text-indent:33px;"><img alt="这里写图片描述" height="261" src="https://img-blog.csdn.net/2018030715491722?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDg3MDUxOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" width="436"></p>
<p> </p>
<h3><a name="t1"></a>二、<strong>Redis为什么这么快?</strong></h3>
<p>(1)完全基于内存,数据存在内存中,绝大部分请求是纯粹的内存操作,非常快速,跟传统的磁盘文件数据存储相比,避免了通过磁盘IO读取到内存这部分的开销。</p>
<p>(2)<a href="https://so.csdn.net/so/search?q=%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84&spm=1001.2101.3001.7020" target="_blank" class="hl hl-1" data-report-click="{"spm":"1001.2101.3001.7020","dest":"https://so.csdn.net/so/search?q=%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84&spm=1001.2101.3001.7020","extra":"{\"searchword\":\"数据结构\"}"}" data-tit="数据结构" data-pretit="数据结构">数据结构</a>简单,对数据操作也简单。Redis中的数据结构是专门进行设计的,每种数据结构都有一种或多种数据结构来支持。Redis正是依赖这些灵活的数据结构,来提升读取和写入的性能。</p>
<p>(3)采用单线程,省去了很多上下文切换的时间以及CPU消耗,不存在竞争条件,不用去考虑各种锁的问题,不存在加锁释放锁操作,也不会出现死锁而导致的性能消耗。</p>
<p><span style="color:#f33b45;">(4)使用基于IO多路复用机制的线程模型</span>,可以处理并发的链接。</p>
<p style="text-indent:33px;">Redis 基于 Reactor 模式开发了自己的网络事件处理器,这个处理器被称为文件事件处理器 file event handler。由于这个文件事件处理器是单线程的,所以Redis才叫做单线程的模型,但是它采用IO多路复用机制同时监听多个Socket,并根据Socket上的事件来选择对应的事件处理器进行处理。文件事件处理器的结构包含4个部分,线程模型如下图:</p>
<blockquote>
<ul><li>多个Socket</li><li>IO多路复用程序</li><li>文件事件分派器</li><li>事件处理器(命令请求处理器、命令回复处理器、连接应答处理器)</li></ul>
</blockquote>
<p style="text-indent:33px;"><img alt="" height="385" src="https://img-blog.csdnimg.cn/20210603044938131.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3NDUyMzM3MDA=,size_16,color_FFFFFF,t_70" width="635"></p>
<p style="text-indent:33px;"><img alt="" height="298" src="https://img-blog.csdnimg.cn/20210603045258248.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3NDUyMzM3MDA=,size_16,color_FFFFFF,t_70" width="769"></p>
<p style="text-indent:33px;">多个 Socket 可能会产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个Socket,将Socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。</p>
<p style="text-indent:33px;">Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返回结果三个过程。其中执行命令阶段,由于Redis是单线程来处理命令的,所有每一条到达服务端的命令不会立刻执行,所有的命令都会进入一个队列中,然后逐个被执行。并且多个客户端发送的命令的执行顺序是不确定的。但是可以确定的是不会有两条命令被同时执行,不会产生并发问题,这就是Redis的单线程基本模型。</p>
<blockquote>
<p>多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,然后程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。</p>
<p>这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个客户端的网络IO连接请求(尽量减少网络 IO 的时间消耗)</p>
</blockquote>
<p>(5)Redis直接自己构建了VM 机制 ,避免调用系统函数的时候,浪费时间去移动和请求</p>
<p> </p>
<h3><a name="t2"></a>三、为什么Redis是单线程?</h3>
<p style="text-indent:33px;">这里我们强调的<span style="color:#f33b45;">单线程,指的是网络请求模块使用一个线程来处理,即一个线程处理所有网络请求,其他模块仍用了多个线程</span>。</p>
<p style="text-indent:33px;">那为什么使用单线程呢?官方答案是:因为CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。</p>
<p style="text-indent:33px;"><span style="color:#4d4d4d;">但是,我们使用单线程的方式是无法发挥多核CPU 性能,不过我们可以通过在单机开多个Redis 实例来解决这个问题</span></p>
<p style="margin-left:0px;"> </p>
<h3 style="margin-left:0px;"><a name="t3"></a>四、Redis6.0 的<a href="https://so.csdn.net/so/search?q=%E5%A4%9A%E7%BA%BF%E7%A8%8B&spm=1001.2101.3001.7020" target="_blank" class="hl hl-1" data-report-click="{"spm":"1001.2101.3001.7020","dest":"https://so.csdn.net/so/search?q=%E5%A4%9A%E7%BA%BF%E7%A8%8B&spm=1001.2101.3001.7020","extra":"{\"searchword\":\"多线程\"}"}" data-tit="多线程" data-pretit="多线程">多线程</a>:</h3>
<p style="text-indent:0;"><strong>1、Redis6.0 之前为什么一直不使用多线程?</strong></p>
<p style="text-indent:33px;">Redis使用单线程的可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。</p>
<p style="text-indent:0;"><strong><span style="color:#f33b45;">2、Redis6.0 为什么要引入多线程呢?</span></strong></p>
<p style="text-indent:33px;"><span style="color:#f33b45;">因为Redis的瓶颈不在内存,而是在网络I/O模块带来CPU的耗时,所以Redis6.0的多线程是用来处理网络I/O这部分,充分利用CPU资源,减少网络I/O阻塞带来的性能损耗。</span></p>
<p><strong>3、Redis6.0 如何开启多线程?</strong></p>
<p>默认情况下Redis是关闭多线程的,可以在conf文件进行配置开启:</p>
<blockquote>
<p>io-threads-do-reads yes</p>
<p>io-threads 线程数</p>
<p>## 官方建议的线程数设置:4核的机器建议设置为2或3个线程,8核的建议设置为6个线程,线程数一定要小于机器核数,尽量不超过8个。</p>
</blockquote>
<p><strong>4、多线程模式下,是否存在线程并发安全问题?</strong></p>
<p>如图,一次redis请求,要建立连接,然后获取操作的命令,然后执行命令,最后将响应的结果写到socket上。</p>
<p><img alt="" height="312" src="https://img-blog.csdnimg.cn/20210201030222228.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3NDUyMzM3MDA=,size_16,color_FFFFFF,t_70" width="646"></p>
<p>在redis的多线程模式下,获取、解析命令,以及输出结果着两个过程,可以配置成多线程执行的,因为它毕竟是我们定位到的主要耗时点,但是命令的执行,也就是内存操作,依然是单线程运行的。所以,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行,也就<span style="color:#f33b45;">不存在并发安全问题。</span></p>
<p> </p>
</div><div><div></div></div>
</div>
Redis为什么这么快?
最新推荐文章于 2024-07-08 22:30:11 发布