学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • Java基础

  • Java集合

  • MySQL

  • Redis

    • Redis核心技术01-基础数据结构
      • Redis核心技术01-基础数据结构
      • 键值用什么结构组织
        • 哈希冲突
        • Rehash和渐进式 rehash
      • 集合数据操作效率
        • 压缩列表
        • 跳表
      • 数据结构的时间复杂度
      • 参考
    • Redis核心技术02-线程IO模型
    • Redis核心技术03-持久化
    • Redis核心技术04-数据同步
    • Redis核心技术05-哨兵机制
    • Redis核心技术06-哨兵集群
    • Redis核心技术07-切片集群
    • Redis核心技术08-String
    • Redis核心技术09-keys统计案例与方案
    • Redis核心技术10-GEO
    • Redis核心技术11-时间序列数据存储
    • Redis核心技术12-消息队列
    • Redis核心技术13-异步机制
    • Redis核心技术14-CPU结构对Redis性能影响
    • Redis核心技术15-应对变慢的Redis
    • Redis核心技术16-删除数据后内存占用率还是很高
    • Redis核心技术17-缓冲区
    • Redis核心技术18-Redis缓冲是如何工作的
    • Redis核心技术19-缓冲替换策略
    • Redis核心技术20-缓冲异常
    • Redis核心技术21-缓存污染
    • Redis核心技术22-无锁原子操作
    • Redis核心技术23-分布式锁
    • Redis核心技术24-事务机制
    • Redis核心技术25-主从同步与故障切换的坑
    • Redis核心技术26-脑裂问题
    • Redis核心技术27-Redis在秒杀场景的关键技术
  • JVM

  • 多线程

  • 计算机网络

  • Spring

  • Kafka

  • Elasticsearch

  • Python

  • 面试专题

  • 知识库
  • Redis
旭日
2023-03-26
目录

Redis核心技术01-基础数据结构

# Redis核心技术01-基础数据结构

Redis快的重要表现在:它接收到一个键值对操作后,能以微秒级别的速度找到数据,并快速完成操作。

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

image-20220519154547038

# 键值用什么结构组织

为了实现从键到值的快速访问,Redis使用一个哈希表来保存所有键值对。一个哈希表,其实就是一个数组,数组的每个元素为一个哈希桶,每个哈希桶保存了键值对数据。

但是哈希桶保存的键值对数据并非真正的数据,而是数据的指针,也就是说哈希桶中的元素都是指向它们的指针。

image-20220519155758716

哈希表的最大好处很明显,就是让我们可以用 O(1) 的时间复杂度来快速查找到键值对——我们只需要计算键的哈希值,就可以知道它所对应的哈希桶位置,然后就可以访问相应的 entry 元素,而entry元素中存储的键值地址。

# 哈希冲突

哈希表有一个问题:当数据量越来越多的时候,某两个数据计算出的哈希值可能相同,那么这两个值就会落到同一个哈希桶中。

Redis解决哈希冲突的方式就是链式哈希,也就是哈希表和链表相结合的方式。

image-20220519160425273

# Rehash和渐进式 rehash

哈希冲突链上的元素只能通过指针逐一查找再操作。如果哈希表里写入的数据越来越多,哈希冲突可能也会越来越多,这就会导致某些哈希冲突链过长,进而导致这个链上的元素查找耗时长,效率降低。

Redis 会对哈希表做 rehash 操作。rehash 也就是增加现有的哈希桶数量,让逐渐增多的 entry 元素能在更多的桶之间分散保存,减少单个桶中的元素数量,从而减少单个桶中的冲突。

为了使rehash操作更高效,Redis默认使用了两个全局哈希表:哈希表1和哈希表2。

一开始,当你刚插入数据时,默认使用哈希表 1,此时的哈希表 2 并没有被分配空间。随着数据逐步增多,Redis 开始执行 rehash,这个过程分为三步:

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

到此,我们就从哈希表1切换到哈希表2能够存储更多的数据,而原来的哈希表1留作下一次rehash扩容备用。

这个过程还存在一个问题:如果一次性把哈希表 1 中的数据都迁移完,会造成 Redis 线程阻塞,无法服务其他请求。此时,Redis 就无法快速访问数据了。

因此就要引入渐进式rehash,简单来说就是在第二步拷贝数据时,Redis 仍然正常处理客户端请求,每处理一个请求时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝到哈希表 2 中;等处理下一个请求时,再顺带拷贝哈希表 1 中的下一个索引位置的 entries。

image-20220519162902167

# 集合数据操作效率

对于String类型来说,找到哈希桶就能进行数据操作了,而对于集合类型来说,即使找到哈希桶还要在集中中再进一步操作。

一个集合类型的值,第一步是通过全局哈希表找到对应的哈希桶位置,第二步是在集合中再增删改查。

# 压缩列表

压缩列表实际上类似于一个数组,数组中的每一个元素都对应保存一个数据。和数组不同的是,压缩列表在表头有三个字段 zlbytes、zltail 和 zllen,分别表示列表长度、列表尾的偏移量和列表中的 entry 个数;压缩列表在表尾还有一个 zlend,表示列表结束。

image-20220519165939603

# 跳表

跳表在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位。

image-20220519170222393

# 数据结构的时间复杂度

image-20220519170429190

# 参考

Redis核心技术与实战 (opens new window)

#Redis
上次更新: 2024/06/29, 15:13:44
MySQL深入40-自增id用完如何处理
Redis核心技术02-线程IO模型

← MySQL深入40-自增id用完如何处理 Redis核心技术02-线程IO模型→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式