菜单

Administrator
发布于 2026-05-16 / 2 阅读
0
0

Redis中的数据库及持久化操作

Redis中的数据库及持久化操作

一、Redis服务器中的数据库

我们应该都用过MySQL,MySQL我们可以在里边创建好几个库。同样地,Redis服务器中也有数据库这么一个概念。如果不指定具体的数量,默认会有16个数据库。

通过SELECT命令可以切换到0~15的数据库。这说明,数据库与数据库之间的数据是隔离的。

1.1Redis数据库的原理

Redis服务器用redisServer结构体来表示,其中redisDb是一个数组,用来保存所有的数据库,dbnum代表数据库的数量(默认是16)

struct redisServer{  
    //redisDb数组,表示服务器中所有的数据库
    redisDb *db;  
    //服务器中数据库的数量
    int dbnum;  
}; 

Redis客户端通过redisClient结构体来表示:

typedef struct redisClient{  
    //客户端当前所选数据库
    redisDb *db;  
}redisClient;

Redis中对每个数据库用redisDb结构体来表示:

typedef struct redisDb { 
    int id;         // 数据库ID标识
    dict *dict;     // 键空间,存放着所有的键值对              
    dict *expires;  // 过期哈希表,保存着键的过期时间                          
    dict *watched_keys; // 被watch命令监控的key和相应client    
    long long avg_ttl;  // 数据库内所有键的平均TTL(生存时间)     
} redisDb;

从代码上我们可以发现最重要的应该是dict *dict,它用来存放着所有的键值对。对于dict数据结构(哈希表)我们在上一篇也已经详细说了。一般我们将存储所有键值对的dict称为键空间。

1.2键的过期时间

Redis是基于内存,内存是比较昂贵的,容量肯定比不上硬盘的。因为我们的内存是有限的。所以我们会干掉不常用的数据,保留常用的数据。这就需要我们设置一下键的过期(生存)时间了。

设置键的生存时间可以通过EXPIRE或者PEXPIRE命令。
设置键的过期时间可以通过EXPIREAT或者PEXPIREAT命令。

过期策略

删除策略可分为三种:

  1. 定时删除(对内存友好,对CPU不友好)

    • 到时间点上就把所有过期的键删除了。
  2. 惰性删除(对CPU极度友好,对内存极度不友好)

    • 每次从键空间取键的时候,判断一下该键是否过期了,如果过期了就删除。
  3. 定期删除(折中)

    • 每隔一段时间去删除过期键,限制删除的执行时长和频率。

Redis采用的是惰性删除+定期删除两种策略。

内存淘汰机制

如果定期删除漏掉了很多过期key,也没及时去查(没走惰性删除),大量过期key堆积在内存里,导致redis内存块耗尽了,咋整?

我们可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略。Redis的内存淘汰机制有以下几种:

  • noeviction:不淘汰
  • allkeys-lru:在所有key中LRU淘汰
  • allkeys-random:随机删除一部分key
  • volatile-lru:在设置了过期时间的key中LRU淘汰
  • volatile-random:随机删除一部分设置了过期时间的key
  • volatile-ttl:优先删除TTL更短的key

二、Redis持久化

Redis提供了两种不同的持久化方法来讲数据存储到硬盘里边:

  • RDB(基于快照):将某一时刻的所有数据保存到一个RDB文件中。
  • AOF(append-only-file):当Redis服务器执行写命令的时候,将执行的写命令保存到AOF文件中。

2.1RDB(快照持久化)

RDB持久化可以手动执行,也可以根据服务器配置定期执行。

有两个命令可以生成RDB文件:

  • SAVE:会阻塞Redis服务器进程,服务器不能接收任何请求,直到RDB文件创建完毕为止。
  • BGSAVE:创建出一个子进程,由子进程来负责创建RDB文件,服务器进程可以继续接收请求。

Redis服务器在启动的时候,如果发现有RDB文件,就会自动载入RDB文件(不需要人工干预)

配置触发条件:

save 900 1              #在900秒(15分钟)之后,至少有1个key发生变化,
save 300 10            #在300秒(5分钟)之后,至少有10个key发生变化
save 60 10000        #在60秒(1分钟)之后,至少有10000个key发生变化

2.2AOF(文件追加)

AOF是通过保存Redis服务器所执行的写命令来记录数据库的数据的。

AOF持久化功能的实现可以分为3个步骤:

  1. 命令追加:命令写入aof_buf缓冲区
  2. 文件写入:调用flushAppendOnlyFile函数,考虑是否要将aof_buf缓冲区写入AOF文件中
  3. 文件同步:考虑是否将内存缓冲区的数据真正写入到硬盘

flushAppendOnlyFile函数的行为由服务器配置的appendfsyn选项来决定的:

appendfsync always     # 每次有数据修改发生时都会写入AOF文件。
appendfsync everysec   # 每秒钟同步一次,该策略为AOF的默认策略。
appendfsync no         # 从不同步。高效但是数据不会被持久化。

AOF重写

AOF重写可以减少AOF文件的体积。Redis将AOF重写程序放到子进程里执行(BGREWRITEAOF命令)。

AOF后台重写

Redis将AOF重写程序放到子进程里执行,像BGSAVE命令一样fork出一个子进程来完成重写AOF的操作,从而不会影响到主进程。

2.3RDB和AOF对过期键的策略

RDB持久化对过期键的策略:

  • 执行SAVE或者BGSAVE命令创建出的RDB文件,程序会对数据库中的过期键检查,已过期的键不会保存在RDB文件中。
  • 载入RDB文件时,程序同样会对RDB文件中的键进行检查,过期的键会被忽略。

AOF持久化对过期键的策略:

  • 如果数据库的键已过期,但还没被惰性/定期删除,AOF文件不会因为这个过期键产生任何影响,当过期的键被删除了以后,会追加一条DEL命令来显示记录该键被删除了

复制模式:

  • 主服务器来控制从服务器统一删除过期键(保证主从服务器数据的一致性)

2.4RDB和AOF用哪个?

RDB和AOF并不互斥,它俩可以同时使用。

特性 RDB AOF
优点 载入时恢复数据快、文件体积小 丢失数据少(默认配置只丢失一秒的数据)
缺点 会一定程度上丢失数据 恢复数据相对较慢,文件体积大

如果Redis服务器同时开启了RDB和AOF持久化,服务器会优先使用AOF文件来还原数据(因为AOF更新频率比RDB更新频率要高,还原的数据更完善)


评论