Redis为何这么快?(上)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 为啥就Redis这么突出?它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快数据结构键值对是按一定的数据结构来组织的,操作键值对最终就是对数据结构进行增删改查操作,所以高效的数据结构是Redis快速处理数据的基础

Redis到底快在哪?

它接收到一个键值对操作后,能以微秒级速度找到数据,并快速完成操作。

为啥就Redis这么突出?

  • 它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快
  • 数据结构
    键值对是按一定的数据结构来组织的,操作键值对最终就是对数据结构进行增删改查操作,所以高效的数据结构是Redis快速处理数据的基础

String(字符串)、List(列表)、Hash(哈希)、Set(集合)和Sorted Set(有序集合)只是Redis键值对中值的数据类型,即数据的保存形式。

本文的数据结构,是研究其底层实现。


底层数据结构一共6种:简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组。

image.png

List、Hash、Set和Sorted Set这四种数据类型都有两种底层实现结构。通常称为集合类型:一个K对应一个集合的数据。

这些数据结构都是V的底层实现,K.V之间用什么组织的?

为什么集合类型有这么多底层结构,是怎么组织数据的,都很快吗?

什么是简单动态字符串,和常用的字符串是一回事吗?

Redis中有哪些潜在的“慢操作”,最大化Redis的性能优势。

键和值用什么结构组织?

为了实现从K到V快速访问,Redis使用哈希表保存所有KV对。

其实就是一个数组,数组元素称为哈希桶。一个哈希表由多个哈希桶组成,每个哈希桶中保存KV对。


如果值是集合类型,数组元素的哈希桶怎么保存呢的?

哈希桶中的元素保存的并非值本身,而是指向具体值的指针。即不管值是String,还是集合类型,哈希桶中的元素都是指向它们的指针。


哈希桶中的entry元素中保存了*key和*value,分别指向实际的K、V。

即使值是个集合,也可通过*value指针查到。

image.png

因为这哈希表保存了所有的键值对,所以,我也把它称为全局哈希表。

全局指Redis数据库中的所有kv,是由一个哈希表来索引的。通过在这个哈希表中查询key,就可以找到对应v。然后根据v具体类型(如Hash,Set,List),再通过v的底层数据结构来读取具体的value数据,例如List通过双向链表来读取数据。


哈希表造就O(1)快速查找KV对,只需计算K的哈希值,即可知其对应哈希桶位置,然后就能访问相应entry元素。


这个查找过程主要依赖哈希计算,和数据量无直接关系。不管哈希表有10万个K还是100万,只需一次计算,就能找到对应K。


若你只是了解哈希表的O(1)复杂度和快速查找特性,那当你往Redis写入大量数据后,就可能发现操作有时候会突然变慢。

因为你忽略了潜在风险:哈希表冲突问题和rehash可能带来操作阻塞。

为什么哈希表操作变慢了?

当你往哈希表中写入更多数据,就会哈希冲突。Redis通过链式哈希解决:同一哈希桶中的多个元素用链表保存。

entry1、entry2和entry3都要保存在哈希桶3:entry1会通过一个*next指向entry2,以此类推。这就形成了一个链表,也叫哈希冲突链。

image.png

哈希表数据越多,哈希冲突可能也越多,导致某些哈希冲突链过长,该链上的元素查找耗时长,效率降低。这对求“快”的Redis无法接受。

所以,Redis会对哈希表做

rehash

增加现有哈希桶数量,让逐渐增多的entry元素能在更多的桶之间分散保存,减少单个桶中的元素数量,从而减少单个桶中的冲突。


为使rehash操作更高效,Redis默认使用了两个全局哈希表:刚插入数据时,默认使用哈希表1,哈希表2尚未被分配空间。

随着数据逐步增多,Redis开始执行rehash:

  1. 给哈希表2分配更大的空间,例如是当前哈希表1大小的两倍
  2. 把哈希表1中的数据重新映射并拷贝到哈希表2中
  3. 释放哈希表1的空间

至此,即可从哈希表1切换到哈希表2:

  • 更大的哈希表2保存数据
  • 哈希表1留作下次rehash扩容备用

step2涉及大量数据拷贝,若一次性把哈希表1中的数据都迁移完,会造成Redis线程阻塞,无法服务其他请求,Redis就无法快速访问数据了。为解决该问题,Redis采用渐进式rehash

step2拷贝数据时,Redis仍可正常处理客户端请求:

  • 每处理一个请求时,从哈希表1中的第一个索引位置开始,顺带将该索引位置的所有节点复制到哈希表2
  • 等到处理下一个请求时,再复制哈希表1中的下一个索引位置的节点们

image.png

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

对String,找到哈希桶就能直接增删改查了,所以,哈希表的O(1)操作复杂度也就是它的复杂度了。

但对集合类型,即使找到哈希桶了,还要在集合中进步操作。

dict的渐进式rehash是为了避免扩容时的整体拷贝,这会给内存带来较大压力。

相关实践学习
基于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
目录
相关文章
|
NoSQL Redis 数据库
Redis为何这么快?(下)
为啥就Redis这么突出? 它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快 数据结构 键值对是按一定的数据结构来组织的,操作键值对最终就是对数据结构进行增删改查操作,所以高效的数据结构是Redis快速处理数据的基础
145 0
Redis为何这么快?(下)
|
缓存 NoSQL Redis
|
存储 NoSQL Redis
Redis 为什么这么快?
本文内容思维导图如下: 1、简介和应用 Redis是一个由ANSI C语言编写,性能优秀、支持网络、可持久化的K-K内存数据库,并提供多种语言的API。它常用的类型主要是 String、List、Hash、Set、ZSet 这5种。
7874 0
|
3月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
117 1
|
14天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
158 85
|
3月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
85 6
|
12天前
|
缓存 监控 NoSQL
Redis经典问题:缓存穿透
本文详细探讨了分布式系统和缓存应用中的经典问题——缓存穿透。缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致大量请求直接落到数据库上,可能引发数据库崩溃或性能下降。文章介绍了几种有效的解决方案,包括接口层增加校验、缓存空值、使用布隆过滤器、优化数据库查询以及加强监控报警机制。通过这些方法,可以有效缓解缓存穿透对系统的影响,提升系统的稳定性和性能。
|
2月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
2月前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构
|
2月前
|
缓存 NoSQL Redis
Redis 缓存使用的实践
《Redis缓存最佳实践指南》涵盖缓存更新策略、缓存击穿防护、大key处理和性能优化。包括Cache Aside Pattern、Write Through、分布式锁、大key拆分和批量操作等技术,帮助你在项目中高效使用Redis缓存。
332 22