redis为什么快

写在前面,这边只是我个人的推导思路,由于个人知识水平有限,怕误导人,故在此提醒,此文中的推导有可能是错误的,仅仅是一个个人思路记录

  

这个其实也是一个面试题

记得比较早之前,比较粗浅的几个回答是

  • redis基于内存,所以更快(内存比硬盘快)
  • redis是单线程,少了线程切换的花销,且其性能瓶颈在带宽(单线程减少了线程切换的时间花销,且在保证数据一致性上面就更简单些)

那么从新来推导下

所谓的是一种相对的概念,说白话点就是需要一个参照物,对比

那么redis是对比什么呢,首先本身redis是一个key-value的内存型数据库,也可以叫no-sql体系的数据库;所以一般可以参照的是sql型数据库-mysql、oracle

一、存储介质

  数据库都是用来存储数据的,那么数据存储的位置在哪

  • redis存储在内存(这里不涉及持久化的部分,redis也支持持久化)
  • mysql存储在硬盘

  

  内存和硬盘存在两个维度的指标

  • 寻址速度:找到指定数据的内存地址
  • 带宽  :同时流过的最大数据量

  很多人都会忽视的一点就是,只看到了内存比硬盘寻址快的一面,也就是单次操作的速度

  却没有注意到带宽的问题

  在高并发场景中,带宽就好比一个通道的大小。在流速相当的情况下,管道的宽度决定了总的性能

   这也是内存型数据库更适合用于高并发场景的原因,其极限带宽远大于硬盘(但实际场景中会受限于网络带宽),不过目前应对10K问题足够(即1w并发)

  

  ps:另外还有一点就是内存和硬盘存储的方式不同,一般硬盘需要建立索引,所以相同的数据,在内存中所占大小会更小

二、IO模型

  然后我们再来看下,redis和mysql的io模型

  • mysql  :bio,阻塞型的io;或者线程池的方式,类似于servlet的方式,一个请求一个线程的方式(源于其硬盘数据库的特性,即使一下子放进来太多的请求,实际上也处理不了)
  • redis   :多路复用的io模型,其与java的nio 的select api有些相似;

    与常规的请求轮询不同,常规的请求轮询是一个请求一个线程去轮询

    nio的select则是使用单独一个线程来管理多个socket(或者io流)

  ps:多路复用通常是解决A IO等待读取的时候,阻塞了B IO的读取这样的问题,也就是说,多路复用可以避免不同的IO操作之间的阻塞问题。

  1. redis在linux系统中一般使用了cpu内核所支持的epoll来做select操作,其特性是不需要轮询所有io流,只需要轮询有操作的流
  2. 在此基础上用零拷贝技术优化了内核态和用户态之间的数据拷贝和一致性问题(在内核和用户态之间开辟一个缓存区)
  3.  cpu的缓存 L1 L2是内核使用的,L3是共享的。redis通过限制在单核处理的方式还可以集中在L1 和 L2级别的缓存中处理,不需要处理多核间的数据一致性的问题【单核可能更快】

综上,可以看出redis的单进程、单线程、单实例,实际上利用了很多硬件层或者CPU层的特性

三、原生数据类型及其方法支持

redis之所以快,还和其的数据类型有关。有些nosql是不提供具体数据类型的

而redis在五种数据类型的基础上,提供了不少原生的操作方法,在网络资源的使用中得以减少资源的占用(比如一条操作方法的语句里面包含了五个基本操作语句,这样只需要请求一次网络资源就可以获取数据)

比如:

GETSET

 四、CAP(一致性【Consistency】、可用性【Availability】、分区容错性【Partition tolerance】)

redis实际上在一致性的要求偏低,可能连最终一致性都不能保证,存在丢失数据的可能性(虽然其也有基于日志的持久化方案,但明显redis更偏向于缓存服务器);

在舍掉一致性之后,redis可以提供高可用,高性能的架构特性

从目前来看,响应式的AIO是趋势。但受限于linux,目前其实并不直接支持(目前来看,其性能差异不是特别大)。

个人理解相当于订阅模式的一种实现:订阅了事件的,将被回调触发,而不需要主动轮询事件是否触发

原文地址:https://www.cnblogs.com/gabin/p/13657899.html