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哨兵原理及持久化机制 在这个系列里, ...
随机推荐
- 【C++】禁用/启用笔记本键盘工具(含源码)
目录 前言 简单介绍注册表 (1)根键 (2)子键 (3)键值项 操作注册表的几个API函数 (1)打开一个键 (2)查询某一个键值 (3)设置一个键值 (4)新建指定键 (5)删除注册表指定键下的值 ...
- selenium模拟不同浏览器的方式
from selenium import webdriver # 使用Firefox手机浏览器 user_agent = "Mozilla/5.0 (iPad; CPU OS 12_1 li ...
- Go语言协程并发---原子操作
package main import ( "fmt" "sync/atomic" ) /* 用原子来替换锁,其主要原因是: 原子操作由底层硬件支持,而锁则由操 ...
- V $ BACKUP_DATAFILE
V$BACKUP_DATAFILE 从控制文件显示有关备份集中的控制文件和数据文件的信息. 柱 数据类型 描述 RECID NUMBER 备份数据文件记录ID STAMP NUMBER 备份数据文件记 ...
- 从7nm到5nm,半导体制程
从7nm到5nm,半导体制程 芯片的制造工艺常常用XXnm来表示,比如Intel最新的六代酷睿系列CPU就采用Intel自家的14nm++制造工艺.所谓的XXnm指的是集成电路的MOSFET晶体管栅极 ...
- 浅谈Gson和fastjson使用中的坑
相信大家在代码编写中都用过Gson和fastjson吧,用来进行 Java对象和json字符串之间的转换. 本篇文章就主要介绍博主在工作中使用这两款工具时遇到的坑和对应的解决办法. 觉得有用的可以点个 ...
- Hash源码注释解析
部分代码注释解析: 1 import java.io.IOException; 2 import java.io.InvalidObjectException; 3 import java.io.Se ...
- UF_DRF 制图符号标注尺寸
Open C uc5530uc5531uc5532uc5533uc5534uc5540uc5541uc5542uc5543uc5550uc5551uc5563uc5566uf5505uf5506uf5 ...
- 深入理解Spring的两大特征(IOC和AOP)
一.spring 的优点? 1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很 ...
- 01 . Varnish简介,原理,配置缓存
简介 Varnish是高性能开源的反向代理服务器和HTTP缓存服务器,其功能与Squid服务器相似,都可以用来做HTTP缓存.可以安装 varnish 在任何web前端,同时配置它缓存内容.与传统的 ...