1.数据库的结构

Redis 中的每个数据库,都由一个 redis.h/redisDb 结构表示。

typedef struct redisDb {
// 保存着数据库以整数表示的号码
int id;
// 保存着数据库中的所有键值对数据
// 这个属性也被称为键空间(key space)
dict *dict;
// 保存着键的过期信息
dict *expires;
// 实现列表阻塞原语,如 BLPOP,可用于列表
dict *blocking_keys;
dict *ready_keys;
// 用于实现 WATCH 命令,可用于事务
dict *watched_keys;
} redisDb;

Redis有id 、dict 和 expires 三个重要属性:

  • id 保存数据库的号码。Redis 服务器初始化时, 它会创建出 redis.h/REDIS_DEFAULT_DBNUM 个数据库, 并 将所有数据库保存到 redis.h/redisServer.db 数组中, 每个数据库的 id 为从 0 到 REDIS_DEFAULT_DBNUM - 1 的值。当执行 SELECT number 命令时,程序直接使用 redisServer.db[number] 来切换数据库。
  • dict 保存着数据库的所有键值对数据。Redis的结构可以看成字典的嵌套,类似json的数据结构。dict的内部依然是字典结构,dict的key是字符串对象,表示name,dict的值则是从string到sort-set中的任意一种对象。而删除数据库的健,实际上就是删除dict中对应的健对象和值对象。
  • expires也是一个字典,保存键的过期时间,注意只保存设置过的过期时间,如果没设置,则默认为永久。

1.1 字典的底层实现

hashtable

冲突解决:链表

扩容:渐进式hash,方法是复制出一个hash表,重算hash值(java8已不再重算)。重点是,扩容和收缩不是一次性完成,而是分多次完成。期间,字典的删改查操作可以在两个hashtable上进行,则增加操作只在新hashtable上进行。当字典中保存的数据很多事,可以避免扩容影响性能。

2.过期键的检查和清除

根据不同的清楚策略,通过expires 字典来检查键是否过期:

  • 检查键是否存在于 expires 字典:如果存在,那么取出键的过期时间。
  • 判断当前 UNIX 时间是否大于键的过期时间,如果是,那么键已经过期。

过期键的清除有三种方式:定时删除、惰性删除和定期删除。

2.1 定时删除

创建一个定时事件,由事件处理 器自动执行键的删除操作。

优点:对内存友好

缺点:可能占用大量cpu时间

2.2 惰性删除

每次从dict字典取出键值时,检查是否过期,如果过期则删除,并返回空。

优点:对cpu友好

缺点:过期键占用内存

核心是 db.c/expireIfNeeded 函数。在读取或写入数据库之前,调用 expireIfNeeded 对输入键进行检查。如果输入键已经过期的话,那么将键、键的值、键保存在 expires 字典中的过期时间都删除掉。

2.3 定期删除

是上面两个策略的结合。每隔一段时间,对 expires 字典进行检查,并执行惰性删除。

核心是redis.c/activeExpireCycle,每当 Redis 的例行处理程序 serverCron 执行时,activeExpireCycle 都会被调用。这个函数在规定的时间限制内,尽可能地遍历各个数据库的 expires 字典,随机地检查一部分键的过期时间,并删除过期键。

2.4 对RDB、AOF和复制的影响

RDB:在创建新的 RDB 文件时,程序会对键进行检查,过期的键不会被写入到更新后的 RDB 文件 中。

AOF:当过期键被惰性删除、或者定期删除后,程序会向 AOF 文件追加一条 DEL 命令,来显式地记录该键已被删除。

复制:当服务器带有附属节点时,过期键的删除由主节点统一控制。主节点再删除过期键后,会会显式地向所有附属节点发送一 个 DEL 命令。附属节点只按DEL命令行动,当它自己碰到过期键时,只向主节点返回键已过期。

3.持久化机制

把数据由内存同步到磁盘,会Fork一个子进程来异步的完成。有三种方式,RDB、AOF和混合方式。

3.1 RDB方式

即快照,定期一次全量备份,将所有缓存进行序列化存到磁盘。

优势:灾难恢复、性能好

劣势:1、归档前断线,则这个归档周期的数据无法恢复。2、子进程工作,如果数据量大,可能影响性能。

配置:

1、修改redis.conf中的save时间:

第一个save的表示每900秒,至少一个key发生变化,则归档一次。第二个save则表示每300秒,至少10个key变化,则归档。第三个同理,是为了应对短时间内的大量服务。

2、也可以修改rdb文件的命名和保存路径:

3.2 AOF方式

以redis网络协议的格式记录对数据库进行的写命令。

优势:append模式写日志,即使宕机,不会影响已记录的日志。

劣势:同数量的数据集,AOF体量比RDB大,效率低。

配置:

在redis.conf中允许打开AOF模式,改为yes:

配置AOF的同步方式,always表示每次修改都要追加日志:

AOF的原理,两个核心函数:

save():aof_buf -> aof文件

write():aof文件 -> 磁盘

共三种模式,第二种综合性性能较好。

3.3 混合方式

增大定期归档的时间跨度,归档间隔期,用AOF记录修改命令。

4.事件

文件事件和时间事件

4.1 文件事件

Redis使用socket进行client和server的通信,来完成实现高效的命令请求处理。采用非阻塞、多路复用IO模式。

在多个客户端中实现多路复用,接受它们发来的命令请求,并将命令的执 行结果返回给客户端。

Redis 将这类因为对套接字进行多路复用而产生的事件称为文件事件。文件事件分为读事件和写事件。

读事件实现了命令请求的接收,生命周期与该客户端和服务器的连接状态相同。

写事件实现了命令结果的返回。

4.2 时间事件

时间事件完成服务器的常规操作,分为单次执行事件和循环执行事件,服务器常规操作 serverCron 就是循环事件。

其实现结构是无序链表,所以查询的时间复杂度为O(N)。

文件事件和时间事件之间是合作关系:一种事件会等待另一种事件完成之后再执行,不会出现抢占情况。由于优先级的问题,时间事件的实际执行时间通常会比预定时间晚一些。

5.参考

《Redis设计和实现》黄健宏

《Redis实战》

Redis的结构和运作机制的更多相关文章

  1. Redis的内部运作机制

    本文将分五个部分来分析和总结Redis的内部机制,分别是:Redis数据库.Redis客户端.Redis事件.Redis服务器的初始化步骤.Redis命令的执行过程. 首先介绍一下Redis服务器的状 ...

  2. redis(一)内部机制的介绍和启动过程

    redis(一)内部机制的介绍和启动过程 redis的基本介绍 redis服务端 redis客户端 redis的持久化 redis中的文件事件和时间时间 redis的启动过程 redis的基本介绍 r ...

  3. Redis Cluster架构和设计机制简单介绍

    之前另一篇文章也介绍了 Redis Cluster (link,在文章的后半部分) 今天看到这一篇,简单说一下(http://hot66hot.iteye.com/blog/2050676) 作者的目 ...

  4. Redis短结构与分片

    本文将介绍两种降低Redis内存占用的方法——使用短结构存储数据和对数据进行分片. 降低Redis内存占用有助于减少创建快照和加载快照所需的时间.提升载入AOF文件和重写AOF文件时的效率.缩短从服务 ...

  5. AsyncLocal的运作机制和陷阱

    这是今天帮柠檬分析一个AsyncLocal相关的问题时发现的. 试想这个代码输出的值是多少? using System; using System.Threading; using System.Th ...

  6. JVM内存结构,运行机制

    三月十号,白天出去有事情出去了一天,晚上刚到食堂就接到阿里电话, 紧张到不行,很多基础的问题都不知道从哪里说了orz: 其中关于JVM内存结构,运行机制,自己笔记里面有总结的,可当天还是一下子说不出来 ...

  7. Redis系列之----Redis的两种持久化机制(RDB和AOF)

    Redis的两种持久化机制(RDB和AOF) 什么是持久化    Redis的数据是存储在内存中的,内存中的数据随着服务器的重启或者宕机便会不复存在,在生产环境,服务器宕机更是屡见不鲜,所以,我们希望 ...

  8. 《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注左上角编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的主从复制?哨兵机制? 在这个 ...

  9. 《【面试突击】— Redis篇》-- Redis哨兵原理及持久化机制

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis哨兵原理及持久化机制 在这个系列里, ...

随机推荐

  1. Google Hacking 搜索引擎攻击与防范

    Google Hacking,有时也会被称为 Google dorking,是一种利用谷歌搜索的高级使用方式进行信息收集的技术.这个概念最早在2000年由黑客 Johnny Long 提出并推广,一系 ...

  2. 【六】K8s-Pod 水平自动扩缩实践(简称HPA)

    一.概述 Pod 水平自动扩缩(Horizontal Pod Autoscaler)简称 HPA,HPA 可以根据 CPU 利用率进行自动伸缩 Pod 副本数量,除了 CPU 利用率,也可以基于其他应 ...

  3. MindSpore基准性能

    MindSpore基准性能 本文介绍MindSpore的基准性能.MindSpore网络定义可参考Model Zoo. 训练性能 ResNet 以上数据基于华为云AI开发平台ModelArts测试获得 ...

  4. AI芯片结构目标图形处理

    AI芯片结构目标图形处理 AI chip architecture targets graph processing 东京--AI处理器设计师Blaize,原名ThinCI(发音为"Thin ...

  5. mybatis学习——映射器(mappers)

    在定义 SQL 映射语句之前,我们需要告诉 MyBatis 到哪里去找到这些语句. 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射 ...

  6. C#搞跨平台桌面UI,分别实现Windows,Mac,Linux屏幕截图

    搞跨平台IM,截图功能少不了. Windows 创建GDI的兼容位图,把桌面的图像通过BitBlt拷贝到兼容位图里,通过兼容位图的数据指针创建Bitmap对象,由于兼容位图的内存是非托管的,Bitma ...

  7. 【SQLite】教程03-SQLite语法

    注释: sqlite>.help -- 这是一个简单的注释 SQLite ANALYZE 语句: 收集有关表和索引的统计信息,并将收集的信息存储在数据库的内部表中 ANALYZE; or ANA ...

  8. 关于web移动端定位

    最近在做一个搜索附近3公里所有超市信息(已经录入数据库的超市信息)的功能.思路很简单只是获取用户当前地理位置(经纬度),通过sql语句筛选出3公里范围内的所有超市信息,然后传递到前台页面展示出来.但是 ...

  9. 题解 P3605 [USACO17JAN]Promotion Counting P

    分块\(yyds\) ----关于线段树合并的题我用分块过掉这件事 题目传送门 先说正解 正解当然是线段树合并等一类做法了 至于解析...出门右转题解区第一篇 (就是他让我看不懂,然后用分块打的\(Q ...

  10. csp-s模拟测试49(9.22)养花(分块/主席树)·折射(神仙DP)·画作

    最近有点头晕........... T1 养花 考场我没想到正解,后来打的主席树,对于每个摸数查找1-(k-1),k-(2k-1)...的最大值,事实上还是很容易被卡的但是没有数据好像还比较友善, 对 ...