Redis学习(二)--为什么使用缓存

本文探讨了使用缓存技术的原因,主要为减轻数据库压力和提升应用响应速度。介绍了主流应用架构中缓存层的作用,以及Redis与Memcache作为缓存中间件的比较。Redis因其丰富的数据类型、持久化存储、主从支持和分片等功能成为高性能场景的选择。文章还深入解释了Redis为何能实现高QPS,关键在于基于内存、简单的数据结构、单线程模型和多路I/O复用技术。
摘要由CSDN通过智能技术生成

1.为什么使用缓存技术?

   Mysql和Oracle数据都是存放在磁盘中,虽然在数据库层中也做了对应缓存,但数据库层次的缓存一般仅针对于查询的内容。一般只有表中数据没有发生变更的时候,数据库中的cache才会发生作用。但这并不能减少业务系统对数据库产生的增、删、改、查的IO压力。因此缓存数据库应运而生,该技术实现了对热点数据的高速缓存,提高应用的响应速度,极大缓解后端数据库的压力 。

2.主流应用架构

   一般为了提升性能都会在客户端和存储层之间添加一个缓存层。

(1)当客户端向后端发送请求的时候,会先去缓存中查,看看有没有相关的数据。

(2)如果有相关数据,就将数据直接返回,减轻了存储层的压力。

(3)如果缓存中没有相关数据。

(4)则穿透缓存,再去存储层中查询

(5)如果在存储层中找到相关数据,则将该数据回写回缓存层中,以便下次客户端再次请求同样数据时,可以快速的从缓存层返回。回写的过程就是所谓的回种。

(6)将结果返回至客户端,完成一次请求、响应的操作。

(7)当我们发现存储层挂掉时,或者没办法提供服务时,可以让客户端请求直接打在缓存层上。

(8)不管有没有数据都直接返回,在有损的情况下,对外提供服务。

3.缓存中间件--Memcache和Redis

Memcache:代码层次类似于hash。

  • 支持简单的数据类型;
  • 不支持数据持久化存储;
  • 不支持主从;
  • 不支持分片。

Redis:

  • 数据类型丰富(支持set、list等类型);
  • 支持数据磁盘持久化存储;
  • 支持主从;
  • 支持分片。

建议有持久化需求、或者对数据结构和处理有高级要求的应用,应选择redis。

其他简单的key-value存储,选择Memcache。

4.为什么redis能这么快?

100000+QPS(QPS即query per second,每秒内查询次数)。

  • 完全基于内存。

       绝大部分请求是存粹的内存操作,执行效率高。不会受到硬盘IO速度的限制,所以速度极快(采用单进程、单线程模型的key-         value数据库);

  • 数据结构简单,对数据操作也简单。                                                                                                                                           

        redis不使用表,他的数据库不会预定义或者强制去要求用户对redis存储的不同数据进行关联。因此性能相比于关系型数据库要高出不止一个量级。其存储结构就是键值对,类似于hashmap,hashmap的优势就是查找和操作时间的复杂度都是O(1);

  • 采用单线程,单线程也能处理高并发请求,想多核也可启动多实例。

       ​​​一般在面对多并发的请求时候,首先想到的是用多个线程来处理,将IO线程与业务线程分开,业务线程使用线程池,避免频繁创建和销毁线程,即便是一次请求阻塞了也不会影响到其他请求。为什么redis会反其道而为之,准确来说redis的单线程结构是指其主线程是单线程的,这里主线程包括IO事件的处理以及IO对应的相关请求的业务的处理,此外主线程还负责过期键的处理,复制协调、集群协调等等,这些除了IO事件之外的逻辑,会被封装成周期性的任务,由主线程周期性的处理,正因为采用单线程的设计,对于客户端的所有读写请求都有一个主线程串行的处理,因此多个客户端同时对一个键进行写操作的时候,就不会有并发的问题,避免了频繁的上下文切换和锁竞争,使得redis执行起来效率更高。

       那么单线程可以处理高并发的请求吗?当然可以了,redis都实现了。

       首先,并发并不是并行,并行性意味着服务器能够同时执行几个事情,具有多个计算单元。而并发性IO流,意味着能够让一个计算单元来处理来自多个客户端的流请求,redis使用单线程配合着IO多路复用,将能大幅度的提升性能。在多核CPU流行的今天,只有一个线程,只用一个核,多少让人感觉很浪费,并且是否没法让CPU利用其它的计算能力,其实大家大可不必担心,因为redis早已对相关问题进行验证,在实际的测试中发现,redis支持的QPS相当高,并且在QPS峰值时候CPU也并没有被跑满,只是由于网络等原因,导致并发处理量等不能进一步上升,因此CPU并不是制约redis的性能瓶颈,此外大家依旧可以在多核的服务器中启动多个redis实例,来利用多核的特性。大家需要注意的是,这里我们一直强调的单线程,只是在处理我们的网络请求的时候,只有一个单线程来处理。一个正式的redis server在运行的时候,肯定不止是一个线程的,例如redis进行持久化时候,会根据实际情况,以子进程或者子线程的方式执行。

  • 使用多路I/O复用模型,非阻塞IO。

       redis是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或者输出都是阻塞的,所以I/O操作,在一般情况下,往往不能直接返回,这会导致某一文件的I/O阻塞,进而导致整个进程无法对其它客户端提供服务,而I/O多路复用就是为了解决这个问题而出现的。

(1)FD:File Descriptor,文件描述符。

         一个打开的文件通过唯一的描述符进行引用,该描述符是打开文件的源数据到文件本身的映射。

         在Linux内核中,这个描述符称为文件描述符,文件描述符用一个整数来表示。

(2)传统的阻塞I/O模型

         当使用read或者write对某一个文件描述符FD进行读写时,如果当前FD不可读,或者不可写,整个redis服务就不会对其它的操作做出响应,导致整个服务不可用,这也就是传统意义上的,也就是我们在编程中使用最多的阻塞模型。阻塞模型虽然在开发中非常常见,也非常易于理解,但是他会影响其它FD对应的服务,所以在需要处理多个客户端任务的时候,往往都不会使用阻塞模型,此时,需要一种更高效率的I/O模型来支持redis的高并发处理,这里涉及的就是I/O多路复用模型。

(3)Select系统调用--I/O多路复用模型中最终要的函数调用

         select方法能够同时监控多个文件描述符的可读和可写操作,当其中的某些文件描述符可读、可写状态时,select方法就会返回可读、可写的文件描述符个数。select是负责监听文件是否可读、可写。监听的任务交给selector之后,程序又可以继续进行别的事情而不被阻塞了。

(4)多路I/O复用模型

         Redis采用的I/O多路复用函数:epoll/kqueue/evport/select

         epoll/kqueue/evport相比于select性能更为优秀,同时也能支撑更多的服务。

  •   因地制宜(根据编译平台的不同);
  •   优先选择时间复杂度为O(1)的I/O多路复用函数作为底层实现

         包括Linux中的epoll和macOs中的kqueue等,上述的这些函数都使用了内核内部的结构,并且能够服务几十万的文件描述符,性能比select优秀 ;

  • 以时间复杂度为O(n)的select作为保底

       因为select函数是作为poxy标准中的系统调用,在不同版本的操作系统上都会实现,以此作为保底方案,因为在当前的编译环境中没有epoll/kqueue/evport等比select更优秀的函数,将会选择select作为备选方案。由于其在使用时会扫描全部的监听的描述符,因此其时间复杂度较差,通常为O(n)

  • 基于react设计模式监听I/O事件。

       使用react设计模式来实现文件事件处理器的,文件事件处理器使用I/O多路复用模块,同时监听多个FD。当accept、read、write和close文件事件产生时,文件事件处理器就会回调FD绑定的事件处理器。虽然整个文件事件处理器是在单线程上运行的,但是通过I/O多路复用模块的引用,实现了同时对多个FD读写的监控,提高了网络通信模型的性能,同时也可以保证整个redis服务实现的简单。 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值