为何redis是单线程的以及为何这么快?

官网的说法


咱们先来认真看一下官网的说法。翻译过来大意以下:
CPU并非您使用Redis的瓶颈,由于一般Redis要么受内存限制,要么受网络限制。例如,使用在通常Linux系统上运行的流水线Redis每秒能够发送一百万个请求,所以,若是您的应用程序主要使用O(N)或O(log(N))命令,则几乎不会使用过多的CPU 。
可是,为了最大程度地利用CPU,您能够在同一服务器上启动多个Redis实例,并将它们视为不一样的服务器。在某个时候,单个实例可能还不够,所以,若是您要使用多个CPU,则能够开始考虑更早地分片的某种方法。
可是,在Redis 4.0中,咱们开始使Redis具备更多线程。目前,这仅限于在后台删除对象,以及阻止经过Redis模块实现的命令。对于未来的版本,计划是使Redis愈来愈线程化。
既然redis的瓶颈不是cpu,那么在单线程能够实现的状况下,天然就使用单线程了。redis

本身的解读

咱们知道redis是基于内存的。那么咱们接下来要了解一个问题多线程cpu和内存直接操做差多少?
多线程操做就是使用多个cpu模拟多个线程,对redis进行操做。这样会形成一个巨大的问题,就是cpu的上下文切换问题。cpu的上下文切换的效率比直接在内存中进行读取差的不少。redis使用单个cpu绑定一个内存,针对内存的处理就是单线程的,这样避免了上下文的切换,因此很是的快。
一次cpu的切换时间大约是1500ns。从内存中读取1mb的连续数据,耗时大约是250us。若是1mb的数据被多个线程读取了1000次。那么就是有1000次时间的上下文切换。因而就是1500ns*1000=1500us。结果显而易见。1500us和250us差的仍是不少的。
那么redis采起单线程还避免了不少问题。若是redis使用多线程来进行,那么就要考虑多线程带来的数据安全问题,若是咱们在操做redis的list,hash等数据结构的时候。多线程就可能存在数据不安全的状况,这是就要加锁。一旦加锁就影响了程序的执行速度。数据库

磁盘读取和内存读取的区别

【IOPS(Input/Output Operations Per Second)是一个用于计算机存储设备(如硬盘(HDD)、固态硬盘(SSD)或存储区域网络(SAN))性能测试的量测方式】
【吞吐量是指对网络、设备、端口、虚电路或其余设施,单位时间内成功地传送数据的数量(以比特、字节、分组等测量)】
内存是一个 IOPS 很是高的系统,由于我想申请一块内存就申请一块内存,销毁一块内存我就销毁一块内存,内存的申请和销毁是很容易的。并且内存是能够动态的申请大小的。
磁盘的特性是:IPOS很低很低,但吞吐量很高。这就意味着,大量的读写操做都必须攒到一块儿,再提交到磁盘的时候,性能最高。为何呢?
若是我有一个事务组的操做(就是几个已经分开了的事务请求,好比写读写读写,这么五个操做在一块儿),在内存中,由于IOPS很是高,我能够一个一个的完成,可是若是在磁盘中也有这种请求方式的话,
我第一个写操做是这样完成的:我先在硬盘中寻址,大概花费10ms,而后我读一个数据可能花费1ms而后我再运算(忽略不计),再写回硬盘又是10ms ,总共21ms
第二个操做去读花了10ms, 第三个又是写花费了21ms ,而后我再读10ms, 写21ms ,五个请求总共花费83ms,这仍是最理想的状况下,这若是在内存中,大概1ms不到。
因此对于磁盘来讲,它吞吐量这么大,那最好的方案确定是我将N个请求一块儿放在一个buff里,而后一块儿去提交。
方法就是用异步:将请求和处理的线程不绑定,请求的线程将请求放在一个buff里,而后等buff快满了,处理的线程再去处理这个buff。而后由这个buff 统一的去写入磁盘,或者读磁盘,这样效率就是最高。
对于慢速设备,这种处理方式就是最佳的,慢速设备有磁盘,网络 ,SSD 等等。缓存

为何单核cpu绑定一块线程内存效率最高

咱们不能任由操做系统负载均衡,由于咱们本身更了解本身的程序,因此咱们能够手动地为其分配CPU核,而不会过多地占用CPU”,默认状况下单线程在进行系统调用的时候会随机使用CPU内核,为了优化Redis,咱们可使用工具为单线程绑定固定的CPU内核,减小没必要要的性能损耗!
redis做为单进程模型的程序,为了充分利用多核CPU,经常在一台server上会启动多个实例。而为了减小切换的开销,有必要为每一个实例指定其所运行的CPU。
Linux 上 taskset 能够将某个进程绑定到一个特定的CPU。你比操做系统更了解本身的程序,为了不调度器愚蠢的调度你的程序,或是为了在多线程程序中避免缓存失效形成的开销。安全

redis的多线程状况

一个redisserver运行的时候,不是单线程的,好比进行rdb备份的时候,就是fork出了一个子进程来进行实现。
能够经过 ps -ef | grep redis 来查看到redis的进程pid。
再使用ps -T -p pid 来查看当前pid下面的线程数。

ps命令的“-T”参数表示显示线程(Show threads, possibly with SPID column.)“SPID”栏表示线程ID,而“CMD”栏则显示了线程名称。服务器

redis的内存模式为何比数据库磁盘块

磁盘数据库的形式,当咱们找数据的时候,先找到索引,经过索引而后关联到磁盘的数据。若是使用内存的方式,能够直接从内存中读取数据。减小了硬盘的io。不受硬盘的读取速度影响。网络

redis的单线程到底有多快


redis的每秒查询次数能够达到10w+。可是随着链接数的增长,每秒的查询数会进行减小。通一个服务器多个链接数致使。数据结构

为何内存读取比硬盘快

两种的方式不一样。内存是一种半导体的存储器,是ram。内存中的数据是电,一旦断电内存中的数据就会消失。内存没有机械结构。
硬盘是一种机械结构。查找数据的时候,磁盘要运动到想应的位置。磁头读取磁盘里的数据。多线程

redis单线程的优点和劣势

优点

代码更清晰,处理逻辑更简单。
不用去考虑各类锁的问题,不存在加锁、释放锁操做,没有由于可能出现死锁而致使的性能消耗。
不存在“多进程或者多线程致使的切换”而消耗CPU。负载均衡

劣势

没法发挥多核CPU性能,不过能够经过在单机开多个Redis实例来完善。异步

redis的多路io复用

redis 采用网络IO多路复用技术,来保证在多链接的时候系统的高吞吐量。
多路-指的是多个socket网络链接,复用-指的是复用一个线程。多路复用主要有三种技术:select,poll,epoll。epoll是最新的、也是目前最好的多路复用技术。
采用多路I/O复用技术:其一,可让单个线程高效处理多个链接请求(尽可能减小网络IO的时间消耗)。其二,Redis在内存中操做数据的速度很是快(内存里的操做不会成为这里的性能瓶颈)。主要以上两点造就了Redis具备很高的吞吐量。
采用多路 I/O 复用技术可让单个线程高效的处理多个链接请求。

redis为何是单线程及为何快的总结

一、Redis是纯内存数据库,通常都是简单的存取操做,线程占用的时间不少,时间的花费主要集中在IO上,因此读取速度快。 二、Redis使用的是非阻塞IO、IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减小了线程切换时上下文的切换和竞争。 三、Redis采用了单线程的模型,保证了每一个操做的原子性,也减小了线程的上下文切换和竞争。 四、Redis避免了多线程的锁的消耗。 五、Redis采用本身实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。

相关文章
相关标签/搜索