【数据库】键值型数据库 Redis

1.定义

Redis 是开源免费的,遵守 BSD 协议的,高性能的键值型数据库。键值型数据库也称为 Key-Value 数据库,简称 KV 数据库。是一种非关系数据库(NoSQL),对键值集合进行存储、检索和管理的一类数据库。

2.特性

  • 所有数据是存放在内存中的,查找速度快,类似于HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
  • 使用单线程架构,避免了多线程可能产生的竞争开销;
  • 数据结构简单,对数据操作也简单;
  • 所有操作都是原子性,支持事务。

3.原理

3.1.文件事件

文件事件是对连接套接字(socket)操作的一个抽象。当端口监听套接字准备新连接,或者连接套接字准备好读取请求、写入响应、关闭时,就会产生一个文件事件。Redis 的文件事件采用典型的 Reactor 模式进行处理。Redis 文件事件处理机制分为 4 部分:连接 socket、I/O 多路复用程序、文件事件分派器、事件处理器。
【数据库】键值型数据库 Redis_第1张图片
Redis 的 I/O 多路复用程序的所有功能都是通过包装常见的 select、epoll、evport 和 kqueue 这些 I/O 多路复用函数库来实现的。编译时,会按照性能和系统平台,选择最佳的 I/O 多路复用函数作为底层实现。如果当前编译环境没有上述函数,就会选择 select 作为底层实现方案。
Redis 中的文件事件分派器是 aeProcessEvents 函数。它会首先计算最大可以等待的时间,然后利用 aeApiPoll 等待文件事件的发生。如果在等待时间内,一旦 I/O 多路复用程序产生了事件通知,则会立即轮询所有已产生的文件事件,并将文件事件放入结构数组中。每个文件事件会记录 socket 及 Redis 读写事件类型。
Redis 中文件事件函数的注册和处理主要分为 3 种:
连接处理函数 acceptTcpHandler,对监听的 socket 注册读事件,事件处理器函数在有新连接进入时,会被派发器派发读任务。在处理该读任务时会建立新连接,获取调用方的 IP 及端口,并对新连接创建一个 client 结构;
请求处理函数 readQueryFromClient,连接函数在创建 client 时,会对新连接 socket 注册一个读事件,该读事件的事件处理器就是 readQueryFromClient。readQueryFromClient 会从连接 socket 读取数据,存入 client 的 query 缓冲,然后进行解析命令尝试解析。解析完毕后,client 会根据请求命令从命令表中获取到对应的命令,如果命令存在。则开始校验请求的参数,以及当前的内存、磁盘及其他状态,完成校验后,然后真正开始执行命令,最后将执行结果作为响应写入 client 的写缓冲中;
当需要发送响应给 client 时,Redis 事件循环中会对 client 的连接 socket 注册写事件,这个写事件的处理函数就是sendReplyToClient。当 client fd 可进行写操作时,就会触发写事件,该函数就会将写缓冲中的数据发送给调用方。

3.2.时间事件

Redis 中的时间事件是指需要在特定时间执行的事件。分为两类:

  • 单次时间,即执行完毕后,该时间事件就结束了;
  • 周期性事件,在事件执行完毕后,会继续设置下一次执行的事件,从而在时间到达后继续执行,并不断重复。

时间事件主要有五个属性组成:

  • 事件 ID:Redis 为时间事件创建全局唯一 ID,该 ID 按从小到大的顺序进行递增。
  • 执行时间 when_sec 和 when_ms:精确到毫秒,记录该事件的到达可执行时间。
  • 时间事件处理器 timeProc:在时间事件到达时,Redis 会调用相应的 timeProc 处理事件。
  • 关联数据 clientData:在调用 timeProc 时,需要使用该关联数据作为参数。
  • 链表指针 prev 和 next:它用来将时间事件维护为双向链表,便于插入及查找所要执行的时间事件。

3.3.回收淘汰策略

  • volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
  • allkeys-lru:从所有数据集中挑选最近最少使用的数据淘汰
  • allkeys-random:从所有数据集中任意选择数据进行淘汰
  • noeviction:禁止驱逐数据,需要先设置最大内存,如果内存不足,会触发选择的过期淘汰策略

如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低, 则使用 allkeys-lru;如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用 allkeys-random。

3.4.过期键删除策略

3.4.1.定时删除

在设置键的过期时间的同时创建一个定时器。让定时器在键的过期时间来临时,立即执行对键的删除操作。对内存友好,但会占用大量的 CPU 资源去处理过期的数据,影响缓存的响应时间和吞吐量。

3.4.2.惰性删除

放任键过期不管,每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。最大化地节省CPU资源,却对内存非常不友好,极端情况可能出现大量的过期 key 没有再次被访问,从而不会被清除,占用大量内存。

3.4.3.定期删除

每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定.

3.5.持久化机制

Redis 的数据都在内存之中,如果出现断电等情况,将数据持久化到硬盘上是非常有必要的。但除了进行持久化外,用户还必须对持久化得到的文件进行备份,最好是备份到不同的地方,这样才能尽量避免数据丢失事故发生。

3.5.1. RDB快照持久化

RDB(Redis DataBase)快照持久化是 Redis 默认采用的持久化方式。Redis 可以通过创建快照来获得存储在内存里面的数据。创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。

  • RDB 是一个非常紧凑的单一文件(dump.rdb),它保存了某个时间点的数据集,非常适用于数据集的备份,这样即使出了问题也可以根据需求恢复到不同版本的数据集;
  • RDB 是一个非常紧凑的单一文件,很方便传送到另一个远端数据中心,非常适用于灾难恢复;
  • 性能最大化,使用单独子进程来进行持久化,主进程不会进行任何 I/O 操作,I/O 最大化,保证了 redis 的高性能;
  • 与 AOF 相比,在恢复大的数据集的时候,RDB 方式会更快一些;
  • 数据安全性低。RDB 是间隔一段时间进行持久化,如果两次持久化之间 Redis 发生故障,会发生数据丢失。

3.5.2.AOF持久化

AOF (Append-Only File)持久化与 RDB 快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。默认情况下 Redis 没有开启 AOF 方式的持久化。
AOF 会记录客户端对 Redis 服务端的每一次写操作,并将这些写操作以 Redis 协议追加保存到后缀为 aof 的文件末尾。在 Redis 服务器重启时,会读取并加载 aof 文件,达到恢复数据的目的。
AOF 虽然可以将数据丢失降低到最小而且对性能影响也很小,但是极端的情况下,体积不断增大的 aof 文件很可能会用完硬盘空间。另外,如果AOF体积过大,那么还原操作执行时间就可能会非常长。因此,Redis 提供了压缩命令来减小 aof 文件的体积。

3.5.3.混合持久化

Redis 4.0 开始支持 RDB 和 AOF 的混合持久化,AOF 重写的时候就直接把 RDB 的内容写到 aof 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点,快速加载同时避免丢失过多的数据。

你可能感兴趣的:(数据库,数据库,redis)