《Redis设计与实现》2.单机数据库的实现

一、数据库

  1. redis的key过期时间设置:EXPIRE设置ttl秒,PEXPIRE设置ttl毫秒,EXPIREAT设置过期时间戳秒,PEXPIREAT设置过期时间戳毫秒。
  2. 保存过期时间:redis过期时间存放于expires字典中,其中都是转为PEXPIREAT命令存储的。
  3. 删除过期时间:PERSIST key
  4. 过期键删除策略:redis采用惰性删除+定期删除
    1. 定时删除:设置过期时间的同时,创建定时器,定时器在键过期时立即执行删除操作(内存友好,但CPU不友好,暂未实现)
    2. 惰性删除:获取key时,哦按段是否过期,过期则删除。
    3. 定期删除:每隔一段时间,对数据库检查一次,删除过期键。
  • 惰性删除如下
  • 定期删除如下
5. 过期键在RDB、AOF、复制中的处理
    RDB中的过期键处理:
  • SAVE或BGSAVE创建RDB,不会将过期key保存到RDB文件中。
  • master载入RDB文件,会过滤掉过期的key;slave载入RDB文件,全部载入,不过滤过期key。
    AOF中的过期键处理:
  • 保存时不做任何处理。
  • 在惰性删除或者定期删除时,会在AOF文件追加删除命令。
  • BGREWRITEAOF重写时,会检查过期key,过期的key不会写到AOF中。
    复制模式过期键处理:
  • 从服务器不处理过期key,而是等主服务器发送DEL命令。
  • GET key访问从服务器,key过期,依然返回key的值。
6. 数据库通知
notify-keyspace-event:
  • AKE:键空间通知、键事件通知
  • AK:键空间通知
  • AE:键事件通知
  • K$:和字符串键有关的键空间通知
  • E1:和列表键有关的键事件通知
 

二、RDB持久化

  1. RDB文件的创建与载入
    1. 创建:SAVE   BGSAVE
    2. 载入:开启了AOF,优先使用AOF恢复;否则使用RDB恢复。
  2. 自动间隔性保存
    1. save 900 1 、save 300 10 、 save 60 10000,900秒之内至少1次修改,300秒内至少10次修改,60秒内至少10000次修改,满足其一自动执行BGSAVE
    2. dirty计数器与lastsave属性
      1. dirty:上次SAVE后多少次修改
      2. lastsave:上一次SAVE的时间
  3. RDB文件结构
    1. REDIS|db_version|databases|EOF|check_sum,例如”REDIS”|”0006”|EOF|2826376271
      1. REDIS就是常量REDIS五个字符
      2. db_version一个整数,版本号,例如0006
      3. databases一个或多个数据库,也可为空,结构SELECTDB|db_number|key_value_pairs
        1. SELECTDB:常量
        2. db_number:数据库号,用于SELECT db_number切换数据库
        3. key_value_pairs:EXOIRETIME_MS|ms|TYPE|key|value,在开启压缩后,大于20字节的字符串value对象会被压缩。
      4. EOF1字节,代表文件正文内容结束
      5. check_sum8字节,校验和
    2. 分析RDB文件
      1. R E D I S 0 0 0 6 377 334 263 C 360 Z 334 362 V
        1. R E D I S 常量;0006 版本;337 EOF常量;334 263 C 360 Z 334 362 V:8字节校验和。
      2. R E D I S 0 0 0 6 376 \0 \0 003 M S G 005 H E L L O 337 207 Z = 304 F T L 343
        • R E D I S 常量;0006 版本;336 SELECTDB常量;\0 数据库号;\0 TYPE常量;003 key长度;MSG key值;005 value长度;HELLO value值;337 EOF常量;207 Z = 304 F T L 343 8字节校验和。

三、AOF持久化

  1. AOF持久化实现:命令追加、文件写入、文件同步
    1. 命令追加:服务器执行完一个命令,会将该命令追加到aof_buf缓冲区。
    2. 文件写入与同步:Redis运行一个循环,会将aof_buf的内容写入文件,并判断是否需要同步文件,参数appendfsync设置。
      1. 写入与同步:操作系统写入文件并不是直接写入文件,而是写入缓冲区,待达到一定量或者时间或者主动同步,才会真正写入文件。
      2. always:每次写入后同步AOF文件。
      3. everysec:每次写入后判断上次同步距离时间,超过1s则执行AOF文件同步。
      4. no:每次写完后不同步,等待操作系统自己同步。
  2. AOF文件的载入与数据还原
    1. 读取AOF文件还原数据库
      1. 创建一个伪客户端
      2. 从AOF文件读取一条命令
      3. 使用伪客户端执行命令
      4. 重复2、3直到AOF的所有命令均执行完毕
  3. AOF重写(文件过大,重写会大大减少文件的大小)aof_write
    1. 创建一个新的AOF文件
    2. 以当前数据库状态为准,生成命令并写入AOF文件
    3. 命令过长,则拆分,依赖参数REDIS_AOF_REWRITEITEMS_PER_CMD,最大64的元素。
    4. 后台重写:BGREWRITEAOF,使用子进程处理AOF重写,父进程可以继续处理命令请求,子进程拥有服务器进程的数据副本,避免锁。
    5. 开启子进程处理AOF同时,也开启一个AOF重写缓冲区,当AOF重写完毕后,会将AOF重写缓冲区的内容写到新的AOF文件,然后重命名替换老的AOF文件。

四、事件

  1. 文件事件
                1. 处理器构成,如图
                2. I/O多路复用实现:底层使用select、epoll、evport、kqueue实现。
                3.常见文件处理器
                    1.连接应答处理器
                    2.命令请求处理器
                    3.命令回复处理器
                一次完整的事件:
    • Redis服务器正常运行,服务器的监听套接字的AE_READABLE事件处于监听下,并对应连接应答处理器;
    • 当一个Redis客户端像服务器发起连接,监听套接字将产生AE_READABLE事件,触发连接应答处理器执行,处理器会对客户端应答,并创建客户端套接字、客户端状态,并将客户端套接字的AE_READABLE事件与命令请求处理器关联;
    • 客户端向服务器发送命令请求,客户端套接字产生AE_READABLE事件,触发命令请求处理器执行,执行命令产生命令回复,服务器将客户端套接字的AE_WRITABLE事件与命令回复处理器关联;
    • 客户端读取命令回复时,客户端套接字产生AE_WRITABLE事件,触发命令回复执行,将命令回复写入套接字,删除客户端套接字的AE_WRITABLE与命令回复处理器的关联。
  1. 时间事件(定时事件与周期事件)
 

五、客户端

PUBSUB与SCRIPT LOAD命令会导致数据库状态或者客户端状态变化,所以也会写入AOF文件。

六、服务端

命令执行器:
  1. 查找命令的实现:命令表查找
  2. 执行预备操作:检查cmd指针、参数、身份验证、内存占用、BGSAVE、订阅模式判断、是否正在载入数据、客户端是否阻塞与lua、是否开启了事务、是否有监视器
  3. 调用命令实现函数
  4. 执行后续工作:慢查询日志记录、cmd命令计数器修改calls、AOF缓冲、slave复制
  5. 回复客户端
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值