Redis为什么那么快

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: Redis为什么那么快

前言


Redis是一款开源的(BSD许可) 使用C语言编写的,基于内存的键值对(key,value) 数据库,其拥有多种数据类型,例如: 字符串、哈希、列表、集合 以及 有序集合 等,除此之外,还有 键过期、发布订阅等, 不仅如此,Redis好能够将内存数据落地到磁盘中,以防止机器故障导致数据丢失,所以其使用场景越来越多,从最开始单纯使用Redis做缓存,而后有艺高人胆大的人直接用Redis做主存,各位,有想过,Redis为什么会这么快么? 今天我们就来探究下Redis为什么这么快。


我们将从一下几个步骤来剖析一下Redis为什么这么快

  • 基于内存存储
  • 高效的数据结构




基于内存存储


存储设备层次

Redis之所以块,是因为将其所有的数据,都放置在内存中的,在此,我们看下存储设备层次结构图。

image.png




在如上层次结构中,由上至下,访问速度会越来越慢,容量则越来越大,这里主要来看下内存和本地硬盘的具体效率。

类型 访问时间 备注
内存 小于100ns 操作系统会将内存地址映射为虚拟的地址表,从而通过该地址进行访问的。
硬盘 小于3ms 操作系统通过控制驱动程序,将硬盘中的数据加载到内存,供程序访问。

其中寄存器和高速缓存是基于CPU的,而内存和硬盘,则需要通过数据总线进行相连接,所以将数据放置内存中,会比放置在磁盘中要快。


数据加载至CPU执行

我们再从执行过程来来看待 通过硬盘 执行程序 和 直接在内存中 访问数据

image.png


通过上面模型图,我们可以更加清晰明了的看懂。

当我们的数据在磁盘的时候

我们想要访问磁盘的数据,我们得先将通过磁盘驱动控制器,将数据通过I/0总线再通过I/O桥加载进内存,执行的时候,需要将主存储器中的数据通过系统总线,将数据加载进寄存器,进行处理。


当我们数据在主存储器的时候

我们仅需要将主存储器中的数据通过系统总线,将数据加载进寄存器,进行处理。



高效的数据结构

我们知道,Redis是键值对数据库,所以我们将从键 和 值,分别来分析下其数据结构。


如何存储键


整个Redis数据库,都可以将其称之为一个hash表,当我们存储key的时候,会进行hash计算,得到下标,而后进行存储,这里我们不妨提出2个问题。


  1. hashMap碰撞应当如何解决
  2. Redis中,hashmap如何进行扩缩容

如何解决hash碰撞

当遇到hashMap碰撞时,Redis采取的方法是通过拉链法来存储多个碰撞的key,当其链表长度大于1的时候,则需要进行遍历该链表从而得到我们需要查询的key


因为有Rehash这种情况一般而言是不存在的

假设我们查询juejin这个key,通过hash算法,我们定位到下标为0处,此时发现其链表大于1,发生了hash碰撞,则需要遍历整个链表来获取其值。

image.png

如何进行hashMap扩缩容

这里就介绍一下扩容,rehash

在介绍扩缩容方法的时候,我们要确定在什么时候进行扩容和缩容,一般而言,若hashmap中保存的个数已经大于hashmap大小的时候,此时则会进行扩容。


扩容,我们也称之为rehash,其大概原理如下。


前提

redis有一个标记是否rehash的变量:rehashidx,默认为-1.

若我们hashmap存储如下

绿色代表存储有数据

image.png


hashMap 存储的节点大于等于hashMap长度时,则会发生扩容,所谓扩容,就是在申请原有hashmap长度2倍的一个数组。此时再将redis变量rehashidx修改为0。此时就进入了rehash状态。

image.png


而后,进行增删改查的时候,都会进行一次rehash,所谓的rehash就是将old数据逐步迁移到new中,当old长度为0的时候,就代表rehash结束。

image.png


结束后,就将old数组释放掉,且将rehashidx置为-1



如何存储值

Redis中,我们有以下几种数据类型,分别是 字符串、哈希、列表、集合 以及 有序集合 等 ,其底层关系,我们对应出来后如下:

image.png


关于这点,我们想简单介绍下跳表。


所谓的跳表,其实是一种以空间换取时间的方法之一,其效率可以比肩红黑树,其构建要比红黑树简单的多。


我们来介绍下,为什么要有跳表。

对于一个有序的数组和有序的链表,我们不妨来分析一下几点。

例如数据如下:

image.png


我们不妨从增删改查来分析一下数组和链表的区别

类型 链表 数组
增加方便,无非新增节点而已 增加不方便,需要扩容数组
删除方便,删除节点修改指针而已 删除不方便,需要对数组缩容
方便,修改完毕后,重新排序即可 方便,修改完毕后,对数组重新排序即可
不方便,没办法做二分查找 方便,有多种查询方式,包括二分

从上述列表中,我们可以看出,在增删改中,链表都即为方便,唯独关于查询,链表由于不是通过下标进行存储的,所以没办法用类似于二分查找。


所以跳表,就是为了解决链表查询不方便的问题,其原理如下

image.png


我们再原始链表(黄色)的基础上,建立了多个索引,在查询的时候,我们先从最高层开始查询,若查询9,则查询路线为

image.png在原链表查询,查询路径为: 1 3 5 7 9需要查询5次,而通过跳表,查询路径为:5 9,只需要2次即可。



总结


我们在本篇文章介绍了redis为什么这么快,我们暂时归纳为2个原因


  • 基于内存存储
  • 有高效的数据结构

这里并没有提及redis单线程特性,因为我们认为Redis核心功能不采取多线程,原因是因为Redis的瓶颈不在Cpu上面,而在内存和网络上,所以这是不提及的原因。








相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
17天前
|
缓存 NoSQL 关系型数据库
记一次redis使用问题
记一次redis使用问题
10 0
|
8月前
|
存储 JSON NoSQL
redis中的value
需要注意的是,redis中的value是以二进制形式存储的,因此在存储和读取数据时需要进行序列化和反序列化操作。常用的序列化方式包括JSON、Protobuf、Msgpack等。示例代码如下
52 0
|
10月前
|
存储 NoSQL 算法
|
10月前
|
NoSQL 安全 Redis
|
10月前
|
缓存 NoSQL 关系型数据库
|
10月前
|
存储 缓存 NoSQL
|
消息中间件 缓存 NoSQL
Redis详解(一)冰叔带你了解Redis
Redis详解(一)冰叔带你了解Redis
161 0
|
存储 缓存 监控
|
存储 缓存 NoSQL
redis为什么这么快?
redis为什么这么快?