写点什么

redis-- 数据库实现

用户头像
en
关注
发布于: 3 小时前
redis--数据库实现

前言

学习了 redis 的 zset 结构以后也去看了 redis 其他数据结构的实现,但是真正要弄懂 redis 的优点,还是要从 redis 的运行方式来探究,才能学习更多。

1.redis 数据库结构

1.1 redis 所有键的存储方式

Redis 是一个键值对数据库服务器,服务器中的每个数据库都由一个 redis.h/redisDb 结构表示,其中 redisDb 结构的 dict 字典保存了数据库中所有键值对,我们称这个字典为键空间

  • 键空间的键就是数据库的键,每个键都是一个字符串对象。

  • 键空间的值就是数据库的值,每个值可以是字符串对象,列表对象,哈希表对象,集合对象和有序集合对象中的任意一种 Redis 对象

从 redis 数据库的结构方式可知,对数据库键中的任意一种增,删,改,查操作实际上都是针对的字典进行的操作。

1.2 redis 键的过期机制

已经知晓了 redis 数据库存储数据是通过键值对的方式,但是 redis 还有一个过期时间的功能,这个是如何实现的,他们又存储在什么地方呢?

1.2.1 过期时间存储

redisDb 结构体用 dict 字典存储键值对,用 expires 字典保存了数据库中所有键的过期时间,这个字典就是过期字典。

  • 过期字典的键是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)

  • 过期字典的值是一个 long long 类型的整数,这个整数保存了键所指向的数据库键的过期时间--一个毫秒精度的 unix 时间戳。

1.2.2 过期键删除

最简单的定时删除惰性删除都有他们自己的缺点

  • 定时删除,如果过期键太多,每次删除过程会占用大量的 cpu 时间,影响服务器的响应时间和吞吐量。

  • 惰性删除,如果有大量的过期 key 不被访问,就相当于内存泄漏,浪费太多内存,有内存泄漏的风险。

定期删除

  1. 每隔一段时间执行一次删除过期键的操作,并通过限制删除操作执行的时长和频率来减少删除对 cpu 时间的影响

  2. 通过定期删除过期键,减少了太多过期键的内存浪费。

redis 采用的是定期删除+惰性删除的综合方式

1.2.3 其他模块针对过期键的操作

1.2.3.1RDB

生成:已经过期的键不会再被保存到新创建的 RDB 文件中

载入:启动服务器的时候,如果服务器开启了 RDB,针对主服务器,会直接忽略已过期的键,从服务器会保存所有的键。

问题 1:为什么主的忽略从保存,而不是一起忽略呢?--》需要了解一下 redis 主从作用,及同步机制

会不会出现内存泄漏呢?

主先同步完了,主删除了,但是从还没有删除,rdb 载入的顺序?


1.2.3.2 AOF

写入:键过期无影响,当被定期或者惰性删除的时 6 候最加一条删除命令。

重写:已经过期的键不会被保存

1.2.3.3 复制

复制模式下,从服务器的过期键删除操作由主服务器决定。

  • 主服务器删除一个过期键,会显式的向所有从服务器发送一个DEL 命令,告知从去删除。

  • 从服务器执行客户端发送读命令,碰到过期键也不删除,继续像处理未过期的键一样来处理过期键。

  • 从只有接到主的删除后才删除。

这样可以保证主从一致性


2.redis 数据库持久化

2.1 RDB(Redis DataBase))持久化

2.1.1 设计原因

redis 是内存数据库,它将自己的数据库状态储存在内存里,为了避免服务器进程退出导致数据丢失,Redis 提供了 RDB 持久化功能,这个功能可以将 Redis 在内存中的数据库状态保存在磁盘中,防止丢失。

2.1.2 RDB 的创建及载入

2.1.2.1 RDB 创建的两种命令

  • save:会阻塞 Redis 服务器进程,直到 RDB 创建完毕位置,在服务器进程阻塞期间,服务器无法处理任何命令请求。

  • bgsave:会派生出一个子进程,然后由子进程负责创建 RDB 文件,服务器进程(父进程)继续处理命令请求

在日常应用上Redis允许用户通过设置服务器的save选项让服务器每隔一度啊时间自动执行一次BGSAVE命令。(如多长时间内进行了多少次操作)


2.1.2.2 RDB 的载入

只要 redis 在启动的时候检测到 EDB 文件的存在,就会自动载入 RDB 文件。

ps:如果服务器开启了 AOF 持久化功能,那么优先使用 AOF 文件还原数据库状态(AOF 的更新频率更快)

服务器在载入 RDB 文件的时候会一直处于阻塞状态。

2.1.2.3 RDB 文件结构

2.2 AOF(Append Only File)持久化

2.2.1 持久化原理

与 RDB 保存数据库中键值对不通,AOF 是通过保存 Redis 服务所执行的写命令来记录数据库状态的。

2.2.2 AOF 持久化的实现

2.2.2.1 命令追加

服务器执行一个写命令之后会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区末尾。

2.2.2.2 写入与同步

redis 服务器进程就是一个事件循环,用户的一个命令就是一个事件循环,当一个事件循环结束以后就会调用函数,看是否需要将 aof_buf 缓冲区的内容写入 AOF 文件。

为了提高文件写入效率,中间层加缓冲区的思想在操作系统是被广泛应用的。

2.2.3 载入和数据还原

AOF 包含了重建数据库所需的所有写命令,所以服务器只要读入并重新执行一遍 AOF 写命令即可。

2.2.4 AOF 重写

因为 AOF 存储的是写命令,所以会出现冗余浪费,如一个字符串对象使用了多条命令,为了防止这种场景,提供了 AOF 重写功能。

重写原理:首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令,这就是 AOF 充血功能的实现原理。

AOF 也提供了后台重写功能,在后台重写过程后,主进程执行的命令会被存储AOF缓冲区AOF重写缓冲区,当重写结束,重写 AOF 接收重写缓冲区内容覆盖原先的 AOF 文件。


参考文档

1.redis 设计与实现

2.https://github.com/sripathikrishnan/redis-rdb-tools/wiki/Redis-RDB-Dump-File-Format

3.http://oldblog.antirez.com/post/redis-persistence-demystified.html


用户头像

en

关注

努力分享对他人有价值的知识 2018.06.14 加入

还未添加个人简介

评论

发布
暂无评论
redis--数据库实现