Redis为什么比MYSQL快
主要是基于几个方面,其中最重要的就是Redis底层的多路复用
1.Redis的读写是基于内存中的,相比数据库的读写是基于磁盘的,例如在数据库中数据是以树的形式存储的,每经过一个树节点即为一次IO操作,而Redis的读写不涉及磁盘,从操作上就比Mysql快了。 2.第二个方面,即数据结构方面。Redis存储数据是以K-V的形式存储,时间复杂度是O1,而Mysql的底层一般是B+树,时间复杂度是Ologn,所以相比Redis速度也没有它快。 3.第三个方面,也是比较片面的一个方面,即Redis是单线程操作的。 4.第四个方面,即Redis的多路复用。 Redis的TPS能够如此强大也是离不开它的这个多路复用的设计。Redis采用网络IO多路复用技术保证其TPS。 在了解Redis多路复用之前先了解下关于《计算机网络》 中的基础。
前面提到,Redis是单线程 的,所以在解决并发这一问题下无法使用多进程或者多线程的方式来解决。是通过网络IO多路复用来解决速度的问题的。通过这个技术可以解决系统内核换成IO数据,当前某个IO准备数据后系统通知本IO可读或者可写,这样就可以马上完成相应的IO操作,而不需要等待其系统完成相应的IO操作,也不需要因为等待IO操作而阻塞。
五种IO模型
阻塞IO模型
举例:老师让你去收作业,你即为线程,当你去找同学(内核)查看作业是否做完了,是否可以收取作业,这时作业没有做完,你就在那里等着。即为阻塞态。 原理:传统的IO模型,即在读写过程如果读写阻塞了,那整个线程就会发生阻塞。当用户线程IO请求之后,内核查看数据是否准备就绪,如果没有就绪,那就开始等待数据返回,而这时用户线程就处于阻塞状态,直到数据准备就绪之后,内核将数据拷贝到用户线程,返回结果给用户线程,然后解除阻塞状态。完成数据操作。这个过程就是阻塞IO,即发生了等待数据,整个线程就进入到《阻塞》状态
非阻塞IO模型
举例:你去收作业时,当同学(内核)中未有数据,你就回到座位了,当你等了一会再去收,如果同学(内核)准备好数据之后就将数据返回给你。 原理:当读写过程发生了阻塞,不进行等待,如果内核中数据未就绪,可以再次发送read操作,一旦内核数据准备好,并且再次受到read指令,即将数据拷贝到用户线程,然后返回数据。在这个模型中,用户线程需要不断访问内核数据是否准备就需要,也就是说,这个过程中,是占用CPU资源的,相比于阻塞态,同步阻塞是不占用CPU资源。所以当系统中非阻塞IO很多时会导致CPU占用率很高。
多路复用IO模型
举例:以一个同学或机器人(线程)代替你查看同学(内核)是否有作业需要提交,如果有,当你需要收作业的时候就可以直接取到内核的数据。 原理:在这个模型中,会有一个独立的线程,一直询问(轮询)多个socket的状态,当socket真正有读写操作时,才调用实际的IO进行读写。在这个模型中,一个线程管理多个socket,系统在需要读写操作时不需要再去创建新的进程或者线程去内核查看是否有数据返回。减少了CPU的支出。 注意在这个线程查询的过程中,线程是以轮询的方式进行查询的。
信号驱动IO模型
举例:当有同学(内核)有作业要提交时,举手(信号量)示意你,你再过去收。 原理:当用户发起一个IO请求,给相应的socket注册信号函数,当内核数据就绪时,会发一个信号量给用户线程,注意,这里是内核给线程发送信号量了,当用户线程接受到线程信号后会在函数里调用IO操作进行实际的IO请求操作。
异步IO模型
举例:你喊一声,一会收作业,然后你就去做你的事情了,当同学(内核)做完即举手,你就可以取回数据。 原理:异步IO模型称为业界理想的IO模型,当用户线程发起read指令,用户线程就可以去做其他操作了。而且当内核受到一个 asyn read之后会马上返回信息,这个信息即为ACK,说明read已经受到了。因此不会对用户线程进行任何的阻塞操作。当内核准备就绪,返回信号量给用户线程,而用户线程就可以去取数据了。
Redis的多路复用形式:select,poll,epoll 默认是epoll epoll相比其他两个优点在于epoll没有并发控制。 效率也高于select和poll 内存拷贝:epoll直接使用《内存共享》,通过传统的内存拷贝操作,效率更高。 除了Redis使用了多路复用,其他场景使用IO多路复用的举例: 如果一个服务器即要处理TCP又要解决UDP的请求,一般要使用I/O复用。 如果一个服务器处理多个服务或者应用了多种协议,也需要使用I/O复用。
|