Redis 源码分析 RDB 持久化

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis 源码分析 RDB 持久化

原理


Redis 提供了 RDB 持久化功能,这个功能可以将 Redis 在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。


触发时机:手动触发、自动触发。


配置读取


redis.conf中 rdb 相关的配置如下:


rdbcompression 
  rdb 文件为了解约空间,支持压缩,要开启该功能
  需要在配置文件中设置参数 rdbcompression (默认开启的),
  当前开启参数后 redis 利用 lz 算法对
stop-writes-on-bgsave-error
  为了保证数据的一致性,redis 默认开启该选项
dbfilename
  rdb 文件名,默认 dump.rdb
save <seconds> <changes>
  指明 rdb 触发机制,表示 seconds 秒改变 changes 触发


mac 系统 brew 安装 rdb 文件位置:


image.png


rdb 文件查看


od -c dump.rdb


➜  redis od -c dump.rdb
0000000    R   E   D   I   S   0   0   0   9 372  \t   r   e   d   i   s
0000020    -   v   e   r 005   6   .   0   .   9 372  \n   r   e   d   i
0000040    s   -   b   i   t   s 300   @ 372 005   c   t   i   m   e 313
0000060  313   x   '   b 372  \b   u   s   e   d   -   m   e   m 302 300
0000100    B 020  \0 372  \f   a   o   f   -   p   r   e   a   m   b   l
0000120    e 300  \0 376  \0 373 001  \0 370   "  \0 003   m   s   g 300
0000140  001 377   9   3 235 231   R 251   \   N                        
0000152


手动触发


Redis 可以执行 SAVEBGSAVE进行手动触发 RDB 持久化操作。


  • SAVE 命令会阻塞 Redis 服务进程,直到 RDB 文件常见完毕。


  • BGSAVE 不会阻塞服务器进程,会创建一个子进程,子进程负责创建 RDB 文件。


RDB 文件的创建是由 rdb.c/rdbSave函数完成,具体代码如下:


/* Save the DB on disk. Return C_ERR on error, C_OK on success. */
int rdbSave(char *filename, rdbSaveInfo *rsi) {
    char tmpfile[256];
    char cwd[MAXPATHLEN]; /* Current working dir path for error messages. */
    FILE *fp = NULL;
    rio rdb;
    int error = 0;
    snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
    fp = fopen(tmpfile,"w");
    if (!fp) {
        char *cwdp = getcwd(cwd,MAXPATHLEN);
        serverLog(LL_WARNING,
            "Failed opening the RDB file %s (in server root dir %s) "
            "for saving: %s",
            filename,
            cwdp ? cwdp : "unknown",
            strerror(errno));
        return C_ERR;
    }
    rioInitWithFile(&rdb,fp);
    startSaving(RDBFLAGS_NONE);
    if (server.rdb_save_incremental_fsync)
        rioSetAutoSync(&rdb,REDIS_AUTOSYNC_BYTES);
    if (rdbSaveRio(&rdb,&error,RDBFLAGS_NONE,rsi) == C_ERR) {
        errno = error;
        goto werr;
    }
    /* Make sure data will not remain on the OS's output buffers */
    if (fflush(fp)) goto werr;
    if (fsync(fileno(fp))) goto werr;
    if (fclose(fp)) { fp = NULL; goto werr; }
    fp = NULL;
    /* Use RENAME to make sure the DB file is changed atomically only
     * if the generate DB file is ok. */
    if (rename(tmpfile,filename) == -1) {
        char *cwdp = getcwd(cwd,MAXPATHLEN);
        serverLog(LL_WARNING,
            "Error moving temp DB file %s on the final "
            "destination %s (in server root dir %s): %s",
            tmpfile,
            filename,
            cwdp ? cwdp : "unknown",
            strerror(errno));
        unlink(tmpfile);
        stopSaving(0);
        return C_ERR;
    }
    serverLog(LL_NOTICE,"DB saved on disk");
    server.dirty = 0;
    server.lastsave = time(NULL);
    server.lastbgsave_status = C_OK;
    stopSaving(1);
    return C_OK;
// 出错处理
werr:
    serverLog(LL_WARNING,"Write error saving DB on disk: %s", strerror(errno));
    if (fp) fclose(fp);
    unlink(tmpfile);
    stopSaving(0);
    return C_ERR;
}


自动触发


Redis 支持用户通过设置服务器配置save 选项(在 redis.conf 中) ,让服务服务器每间隔一段事件自动执行一次 BGSAVE命令。


默认配置如下所示:


save 900 1
save 300 10
save 60 10000


那么只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行:


  • 服务器在 900 秒之内,对数据库进行了至少 1 次修改。


  • 服务器在 300 秒之内,对数据库进行了至少 10 次修改。


  • 服务器在 60 秒之内,对数据库进行了至少 10000 次修改。


服务器中会根据 save 选项设置的保存条件,设置服务器状态的 redisServer 结构的 saveparams 属性


struct redisServer {
  // 记录保存条件
    struct saveparam *saveparams;   /* Save points array for RDB */
}
// saveparam 定义
struct saveparam {
    time_t seconds;
    int changes;
};


总结


1、Redis 中提供了手动,自动两种方式来持久化数据,其实也是在性能和可靠性的折中处理。


2、自动持久化除了 saveparams数组之外,服务器状态还维持着一个dirty计数器,以及一个lastsave属性:


  • dirty 计数器记录距离上一次成功执行 SAVE 命令或者 BGSAVE 命令之后,服务器对数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、删除、更新等操作)。


  • lastsave 属性是一个UNIX时间戳,记录了服务器上一次成功执行 SAVE 命令或者 BGSAVE 命令的时间。


struct redisServer {
    // 修改计数器
    long long dirty;                /* Changes to DB from the last save */
    // 上次保存时间
    time_t lastsave;                /* Unix time of last successful save */
}


3、Redis 的服务器周期性操作函数 serverCron 默认每隔 100 毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是检查 save 选项所设置的保存条件是否已经满足,如果满足的话,就执行 BGSAVE 命令。


RDB 结构图


图例:


  1. 粉色框中字段为固定字符串


  1. 绿色框中字段为整数


  1. 紫色框中是拓展的数据


  1. 黄色框中value类型是一个枚举的常量


  1. 蓝色框中是实际存储的键值对数据


image.png


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
5天前
|
存储 缓存 NoSQL
Redis中的rdb和aof
本文深入探讨了Redis的持久化机制,包括RDB和AOF两种方式。详细解释了RDB的工作原理、优势和劣势,以及AOF的实现原理、配置选项、文件重写机制和三种数据同步方式,还介绍了AOF文件修复工具redis-check-aof的使用,并通过实例展示了如何开启和配置AOF持久化方式。
Redis中的rdb和aof
|
20天前
|
存储 NoSQL Redis
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
Redis持久化、RDB和AOF方案、Redis主从集群、哨兵、分片集群、散列插槽、自动手动故障转移
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
|
3天前
|
存储 缓存 NoSQL
Redis 大 Key 对持久化的影响及解决方案
Redis 大 Key 对持久化的影响及解决方案
10 1
|
3天前
|
存储 NoSQL 安全
8)详解 Redis 的配置文件以及数据持久化
8)详解 Redis 的配置文件以及数据持久化
9 0
|
3天前
|
存储 NoSQL Redis
Redis的RDB快照:保障数据持久性的关键机制
Redis的RDB快照:保障数据持久性的关键机制
10 0
|
3天前
|
存储 缓存 NoSQL
深入探究Redis的AOF持久化:保障数据安全与恢复性能的关键机制
深入探究Redis的AOF持久化:保障数据安全与恢复性能的关键机制
13 0
|
2月前
|
存储 缓存 NoSQL
【Azure Redis 缓存 Azure Cache For Redis】如何设置让Azure Redis中的RDB文件暂留更久(如7天)
【Azure Redis 缓存 Azure Cache For Redis】如何设置让Azure Redis中的RDB文件暂留更久(如7天)
|
2月前
|
NoSQL Redis
Redis 临时manifest修改问题之确保被持久化到磁盘如何解决
Redis 临时manifest修改问题之确保被持久化到磁盘如何解决
|
3月前
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
下一篇
无影云桌面