Redis的结构和运作机制
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的结构和运作机制的更多相关文章
- Redis的内部运作机制
本文将分五个部分来分析和总结Redis的内部机制,分别是:Redis数据库.Redis客户端.Redis事件.Redis服务器的初始化步骤.Redis命令的执行过程. 首先介绍一下Redis服务器的状 ...
- redis(一)内部机制的介绍和启动过程
redis(一)内部机制的介绍和启动过程 redis的基本介绍 redis服务端 redis客户端 redis的持久化 redis中的文件事件和时间时间 redis的启动过程 redis的基本介绍 r ...
- Redis Cluster架构和设计机制简单介绍
之前另一篇文章也介绍了 Redis Cluster (link,在文章的后半部分) 今天看到这一篇,简单说一下(http://hot66hot.iteye.com/blog/2050676) 作者的目 ...
- Redis短结构与分片
本文将介绍两种降低Redis内存占用的方法——使用短结构存储数据和对数据进行分片. 降低Redis内存占用有助于减少创建快照和加载快照所需的时间.提升载入AOF文件和重写AOF文件时的效率.缩短从服务 ...
- AsyncLocal的运作机制和陷阱
这是今天帮柠檬分析一个AsyncLocal相关的问题时发现的. 试想这个代码输出的值是多少? using System; using System.Threading; using System.Th ...
- JVM内存结构,运行机制
三月十号,白天出去有事情出去了一天,晚上刚到食堂就接到阿里电话, 紧张到不行,很多基础的问题都不知道从哪里说了orz: 其中关于JVM内存结构,运行机制,自己笔记里面有总结的,可当天还是一下子说不出来 ...
- Redis系列之----Redis的两种持久化机制(RDB和AOF)
Redis的两种持久化机制(RDB和AOF) 什么是持久化 Redis的数据是存储在内存中的,内存中的数据随着服务器的重启或者宕机便会不复存在,在生产环境,服务器宕机更是屡见不鲜,所以,我们希望 ...
- 《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注左上角编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的主从复制?哨兵机制? 在这个 ...
- 《【面试突击】— Redis篇》-- Redis哨兵原理及持久化机制
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis哨兵原理及持久化机制 在这个系列里, ...
随机推荐
- 文字闪烁效果 CSS + HTML
文字闪烁效果 CSS 写在前面 好好学习,天天向上! 效果图 绝美的效果 实现过程 先给没字体添加一些普通的样式,颜色设置为透明 给文字设置一个动画效果,通过text-shadow属性来实现变亮的效果 ...
- 西门子 S7200 以太网模块连接组态王方法
北京华科远创科技有限研发的远创智控ETH-YC模块,以太网通讯模块型号有MPI-ETH-YC01和PPI-ETH-YC01,适用于西门子S7-200/S7-300/S7-400.SMART S7-20 ...
- 五种开源API网关实现组件对比
五种开源API网关实现组件对比 API 网关一些实现 使用一个组件时,尤其是这种比较流行的架构,组件肯定存在开源的,我们不必自己去从零开始去实现一个网关,自己开发一个网关的工作量是相当可观的, ...
- 解决maven依赖冲突问题
解决maven依赖冲突问题 1.idea 安装maven helper插件 2.打开pom.xml文件 底部多出一个Dependency Analyzer选项 点开这个选项 找到冲突,点击右键,选择E ...
- 旷视MegEngine数据加载与处理
旷视MegEngine数据加载与处理 在网络训练与测试中,数据的加载和预处理往往会耗费大量的精力. MegEngine 提供了一系列接口来规范化这些处理工作. 利用 Dataset 封装一个数据集 数 ...
- GPU加速:宽深度推理
GPU加速:宽深度推理 Accelerating Wide & Deep Recommender Inference on GPUs 推荐系统推动了许多最流行的在线平台的参与.随着为这些系统提 ...
- 孟老板 BaseAdapter封装(四) PageHelper
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
- linux环境下jmeter安装和运行
linux环境部署: 在Linux服务器先安装jdk:2.以jdk-8u172-linux-x64.tar.gz为例:下载地址:http://www.oracle.com/technetwork/ja ...
- python+selenium基础篇,By定位元素
1.By定位和find_element_by_XXXXXX是一样的,如下图所示,定位元素的方法都是一样的 2.使用By定位代码如下所示 from selenium import webdriver f ...
- 编译原理-文法(G)和语言(L)
1.设文法G2(S): S->AB A->aA|a B->bB|b G2(S)产生的语言是什么? 解:L(G2)={ambn|m,n≥1} 2.请给出产生语言为{anbn|n≥1}的 ...