首页 > 数据库 >Redis 为什么这么快?

Redis 为什么这么快?

时间:2023-08-28 23:33:26浏览次数:32  
标签:为什么 哈希 这么 Redis 内存 key 数据 硬盘

前言

  作为一名后端软件工程师,工作中你肯定和 Redis 打过交道。但是Redis 为什么快呢?很多人只能答出Redis 因为它是基于内存实现的,但是对于其它原因都是模棱两可。

那么今天就一起来看看是Redis 为什么快吧:

 

              Redis 为什么这么快?

 

一、基于内存实现

  Redis 是基于内存的数据库,那不可避免的就要与磁盘数据库做对比。对于磁盘数据库来说,是需要将数据读取到内存里的,这个过程会受到磁盘 I/O 的限制。而对于内存数据库来说,本身数据就存在于内存里,也就没有了这方面的开销。

通过下面的表格我们可以知道读取内存和读取磁盘的性能差距。

计算机设备

读取的速度

类比

机械硬盘

0.1G/S

以机械盘为基准

固态盘

1.3G/S

13倍机械硬盘

内存

30G/S

300倍机械硬盘

L3

190G/S

1900倍机械硬盘

L2

200G/S

2000倍 机械硬盘

L1

800G/S

8000倍机械硬盘

 

二、高效存储结构

  为了实现从键到值的快速访问,Redis 使用了一个哈希表来保存所有键值对。一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。所以,我们常说,一个哈希表是由多个哈希桶组成的,每个哈希桶中保存了键值对数据。

                  全局哈希表

 

  哈希桶中的 entry 元素中保存了key和value指针,分别指向了实际的键和值,因为其value的多样性,哈希表中存储的并不是具体的值,而是一个内存引用地址,在通过内存引用的地址查找到对应的具体的值。这样一来,即使value是一个集合,也可以通过*value指针被查找到。因为这个哈希表保存了所有的键值对,所以,我也把它称为全局哈希表。

  哈希表的最大好处很明显,就是让我们可以用 O(1) 的时间复杂度来快速查找到键值对:我们只需要计算键的哈希值,就可以知道它所对应的哈希桶位置,然后就可以访问相应的 entry 元素。但当你往 Redis 中写入大量数据后,就可能发现操作有时候会突然变慢了。这其实是因为你忽略了一个潜在的风险点,那就是哈希表的冲突问题和 rehash 可能带来的操作阻塞。

  当你往哈希表中写入更多数据时,哈希冲突是不可避免的问题。这里的哈希冲突,两个 key 的哈希值和哈希桶计算对应关系时,正好落在了同一个哈希桶中。

                  哈希表的哈希冲突

 

  Redis 解决哈希冲突的方式,就是链式哈希。链式哈希也很容易理解,就是指同一个哈希桶中的多个元素用一个链表来保存,它们之间依次用指针连接。

 

三、单线程避免了上下文前切换

  省去了很多上下文切换的时间以及CPU消耗,不存在竞争条件,不用去考虑各种锁的问题,不存在加锁释放锁操作,也不会出现死锁而导致的性能消耗。

 

四、使用基于IO多路复用机制的线程模型,可以处理并发的链接。

  Redis采用了epoll 模型进行IO多路复用。Java中也有类似的模型比如NIO,才epoll模型之前还有selector、poll这里不多讲解,epoll模型可以参考下图:

                  epoll 模型

 

五、渐进式ReHash

  Redis是当然如果这个数组一直不变,那么hash冲突会变很多,这个时候检索效率会大打折扣,所以Redis就需要把数组进行扩容(一般是扩大到原来的两倍),但是问题来了,扩容后每个hash桶的数据会分散到不同的位置,这里设计到元素的移动,必定会阻塞IO,所以这个ReHash过程会导致很多请求阻塞。

  为了避免这个问题,Redis 采用了渐进式 rehash。

  首先、Redis 默认使用了两个全局哈希表:哈希表 1 和哈希表 2。一开始,当你刚插入数据时,默认使用哈希表 1,此时的哈希表 2 并没有被分配空间。随着数据逐步增多,Redis 开始执行 rehash。

  1、给哈希表 2 分配更大的空间,例如是当前哈希表 1 大小的两倍

  2、把哈希表 1 中的数据重新映射并拷贝到哈希表 2 中

  3、释放哈希表 1 的空间

   在上面的第二步涉及大量的数据拷贝,如果一次性把哈希表 1 中的数据都迁移完,会造成 Redis 线程阻塞,无法服务其他请求。此时,Redis 就无法快速访问数据了。

              渐进式rehash

 

  在Redis 开始执行 rehash,Redis仍然正常处理客户端请求,但是要加入一个额外的处理:

  处理第1个请求时,把哈希表 1中的第1个索引位置上的所有 entries 拷贝到哈希表 2 中

  处理第2个请求时,把哈希表 1中的第2个索引位置上的所有 entries 拷贝到哈希表 2 中

  如此循环,直到把所有的索引位置的数据都拷贝到哈希表 2 中。

  这样就巧妙地把一次性大量拷贝的开销,分摊到了多次处理请求的过程中,避免了耗时操作,保证了数据的快速访问。

  所以这里基本上也可以确保根据key找value的操作在O(1)左右。

  过这里要注意,如果Redis中有海量的key值的话,这个Rehash过程会很长很长,虽然采用渐进式Rehash,但在Rehash的过程中还是会导致请求有不小的卡顿。并且像一些统计命令也会非常卡顿:比如keys

按照Redis的配置每个实例能存储的最大的key的数量为2的32次方,即2.5亿,但是尽量把key的数量控制在千万以下,这样就可以避免Rehash导致的卡顿问题,如果数量确实比较多,建议采用分区hash存储。

 

六、缓存时间戳

  我们平常使用系统时间戳时, 常常是不假思索地使用System.currentTimeMillis()或者new Date() .getTime() 来获取系统的毫秒时间戳。但是Redis不能这样做,因为每一次获取系统时间戳都是一次系统调用,而且每次去系统调用是比较费时间的,作为单线程的Redis是无法承受的,所以它需要对于时间戳进行一次缓存,由一个定时任务进行每毫秒更新时间戳,从而获取时间戳都是直接从缓存就取出。

标签:为什么,哈希,这么,Redis,内存,key,数据,硬盘
From: https://www.cnblogs.com/fhey/p/17663668.html

相关文章

  • Redis数据持久化介绍
    Redis存储配置数据持久化,开启aof后,配置了aof重写规则,但aof文件仍然持续增长,当aof数据文件增长过大时,需要进行手动清理。本文意为手动清理aof文件提供帮助。同时对rdb和aof数据存储进行说明。1. Redis数据持久化介绍1.1. RDB数据存储RDB(RedisDatabase)通过快照的形式将数据保......
  • LongAdder高竞争环境下为什么比AtomicLong块
     LongAdderlongAdder=newLongAdder();longAdder.increment();//依次开始分析 LongAdder的基本思路是分散热点,将value值分散到一个Cell数组中。第一部分:LongAdder.add()   第二部分:Striped64.longAccumulateif((cs=cells)!=null||!casBase(b=base,......
  • Python分享之redis(3)
    3、List操作redis中的List在在内存中按照一个name对应一个List来存储lpush(name,values)#在name对应的list中添加元素,每个新的元素都添加到列表的最左边r.lpush("list_name",2)r.lpush("list_name",3,4,5)#保存在列表中的顺序为5,4,3,2rpush(name,values)#同lpush,但每个新的元素......
  • 新风机为什么会出现?
     新风机之所以会出现,是因为人们对于室内空气质量的重视与需求。随着社会的进步和人们生活水平的提高,人们更加注重健康和舒适的居住环境,而室内空气质量是其中一个重要的方面。1.空气污染问题:城市化进程加速,工业排放、交通尾气、建筑物密闭、家居装修等都导致了室内空气污染问题......
  • 为什么那么多人喜欢用云桌面
    说起云桌面我们会发现一个很奇怪的现象,那就是我们在网上经常能看到有人在吐槽云桌面的,说云桌面的性能差、价格贵和各种的不好用。虽然说网上有很多人都在吐槽云桌面,但是我们会发现使用它的用户却从来没有减少,而且咨询和使用云桌面的用户反而是越来越多的。为什么云桌面经常被吐槽,......
  • 为什么我们需要数据可视化?
    为什么我们需要数据可视化?这个问题在信息时代变得愈发重要。数据,如今已成为生活的一部分,我们每天都在产生大量的数据,从社交媒体到购物记录,从健康数据到工作表现,数据无处不在。然而,数据本身通常是冷冰冰的数字,对于大多数人而言,理解和分析这些数字可能并不容易。这就是数据可视化......
  • Redis缓存高可用集群(3.1)
    1、Redis集群方案比较哨兵模式在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般,特别是在主从切换的瞬间存在访问瞬断的情况......
  • 隧道代理 vs 免费代理:为什么应该选择隧道代理
    在互联网时代,我们经常需要使用各种工具来保护我们的网络安全和数据隐私。其中一种非常重要的工具就是代理服务器。而当涉及选择合适的代理服务器时,很多人会面临一个困境——是选择免费的还是付费并更加可靠稳定、功能强大的隧道式(Tunnel)服务呢?本篇文章将带您深入了解,并提供专业建议......
  • Redis从入门到放弃(11):雪崩、击穿、穿透
    1、前言Redis作为一款高性能的缓存数据库,为许多应用提供了快速的数据访问和存储能力。然而,在使用Redis时,我们不可避免地会面对一些常见的问题,如缓存雪崩、缓存穿透和缓存击穿。本文将深入探讨这些问题的本质,以及针对这些问题的解决方案。2、缓存雪崩2.1、问题描述在某个时间......
  • 为什么软件工程专业,在第3-4年级学费比较高?
    清华大学学生学费收费标准:美术学类、设计学类专业10000元人民币/学年,其他专业5000元人民币/学年。北京大学校本部学费收费标准:理科试验班类、文科试验班类、电子信息类、生物科学专业为5300元人民币/学年,其他专业5000元人民币/学年。计算机类也是5300/年。下面是第3-4......