V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
such
V2EX  ›  Redis

Redis5.0 RDB 文件超详细解析

  •  
  •   such ·
    8090lambert · 2019-09-30 17:54:01 +08:00 · 13334 次点击
    这是一个创建于 1879 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Redis RDB 介绍

    RDB 是 Redis 将 server 端的内存中的 k/v 对以二进制的方式,持久化存储的一种文件形式。 文件中,一般会以 对象的长度+对象 的格式来存储,只要根据这个格式,就能渐进的遍历整个文件。 Redis 还支持开启 LZF 的压缩算法,可以牺牲 CPU 时间,来减少 RDB 文件的大小;如果开启LZF并且超过20个 bytes 时, 会将压缩后的字符写入文件。

    RDB 文件格式

    ➜  go-redis-parser od -A x -t x1c -v ./teststub/dumpV9.rdb
    000000  52  45  44  49  53  30  30  30  39  fa  09  72  65  64  69  73
             R   E   D   I   S   0   0   0   9 372  \t   r   e   d   i   s
    000010  2d  76  65  72  05  35  2e  30  2e  35  fa  0a  72  65  64  69
             -   v   e   r 005   5   .   0   .   5 372  \n   r   e   d   i
    000020  73  2d  62  69  74  73  c0  40  fa  05  63  74  69  6d  65  c2
             s   -   b   i   t   s 300   @ 372 005   c   t   i   m   e 302
    000030  71  8a  8d  5d  fa  08  75  73  65  64  2d  6d  65  6d  c2  30
             q 212 215   ] 372  \b   u   s   e   d   -   m   e   m 302   0
    000040  e0  0f  00  fa  0c  61  6f  66  2d  70  72  65  61  6d  62  6c
           340 017  \0 372  \f   a   o   f   -   p   r   e   a   m   b   l
    000050  65  c0  00  fe  00  fb  06  00  f9  00  00  01  73  01  61  f9
             e 300  \0 376  \0 373 006  \0 371  \0  \0 001   s 001   a 371
    000060  03  0e  02  6c  69  01  11  11  00  00  00  0d  00  00  00  02
           003 016 002   l   i 001 021 021  \0  \0  \0  \r  \0  \0  \0 002
    000070  00  00  01  61  03  01  62  ff  f9  00  02  03  73  65  74  02
            \0  \0 001   a 003 001   b 377 371  \0 002 003   s   e   t 002
    000080  01  62  01  61  f9  00  0f  06  73  74  72  65  61  6d  01  10
           001   b 001   a 371  \0 017 006   s   t   r   e   a   m 001 020
    000090  00  00  01  6d  70  b5  4a  7e  00  00  00  00  00  00  00  00
            \0  \0 001   m   p 265   J   ~  \0  \0  \0  \0  \0  \0  \0  \0
    0000a0  40  52  52  00  00  00  18  00  03  01  00  01  02  01  84  6e
             @   R   R  \0  \0  \0 030  \0 003 001  \0 001 002 001 204   n
    0000b0  61  6d  65  05  83  61  67  65  04  00  01  02  01  00  01  00
             a   m   e 005 203   a   g   e 004  \0 001 002 001  \0 001  \0
    0000c0  01  87  4c  61  6d  62  65  72  74  08  1d  01  05  01  02  01
           001 207   L   a   m   b   e   r   t  \b 035 001 005 001 002 001
    0000d0  f2  33  8c  00  04  00  01  84  4a  61  63  6b  05  1a  01  05
           362   3 214  \0 004  \0 001 204   J   a   c   k 005 032 001 005
    0000e0  01  02  01  f2  9c  ad  00  04  00  01  83  54  6f  6d  04  1e
           001 002 001 362 234 255  \0 004  \0 001 203   T   o   m 004 036
    0000f0  01  05  01  ff  03  81  00  00  01  6d  70  b5  f8  1a  00  01
           001 005 001 377 003 201  \0  \0 001   m   p 265 370 032  \0 001
    000100  05  67  72  6f  75  70  00  00  00  00  f9  00  0c  04  7a  73
           005   g   r   o   u   p  \0  \0  \0  \0 371  \0  \f 004   z   s
    000110  65  74  15  15  00  00  00  12  00  00  00  04  00  00  01  61
             e   t 025 025  \0  \0  \0 022  \0  \0  \0 004  \0  \0 001   a
    000120  03  f2  02  01  62  03  f3  ff  f9  03  0d  01  68  11  11  00
           003 362 002 001   b 003 363 377 371 003  \r 001   h 021 021  \0
    000130  00  00  0d  00  00  00  02  00  00  01  61  03  01  61  ff  ff
            \0  \0  \r  \0  \0  \0 002  \0  \0 001   a 003 001   a 377 377
    000140  0e  e0  f7  31  2f  37  16  df
           016 340 367   1   /   7 026 337
    000148
    

    这是一个 version 9 的 RDB 文件

    魔数 Magic Number

    文件前 9 个字节是一个 魔数,5 个字节REDIS 和 4 个字节的版本号 009

    辅助字段 Aux Fields

    通用字符串字段,用于向 RDB 添加状态,Version 7 加入的,向后兼容。AUX 字段由两个字符串组成:键和值。 整理了下,除了 lua,有这些字段:

    • redis-ver:版本号
    • redis-bits:OS Arch
    • ctime:RDB 文件创建时间
    • used-mem:使用内存大小
    • repl-stream-db:在 server.master 客户端中选择的数据库
    • repl-id:当前实例 replication ID
    • repl-offset:当前实例复制的偏移量

    数据库索引

    fe(0xfe),fb(0xfb)是 10 进制的 254 和 251,在 RDB 分别对应着,SELECT_DBRESIZE_DB。 每一个 SELECTDB后都会紧跟着RESIZEDB,后者表示的是当前数据库hashtable键大小的提示,每次切换数据库时提前读到,避免不必要的rehash

    数据库键值对

    接下来,读到的就是Redis中所有存储着的K/V对: 类型对照表

    LFU/LRU Idle

    后面 f9(0xf9)是 10 进制的 249,是表示 key 对象的lfu_idle,这个字段是只有开启maxmemory-policy并且设置为volatile-lfuallkeys-lfu才会写入文件。 LRU的同理,不过前缀是 f8(0xf8),maxmemory-policy要设置为:allkeys-lruvolatile-lru

    String 结构

    00(0x00)是 10 进制的 0,表示string类型的对象,01 指key是一个字节长度:“s”, value 也是一个字节长度:“a”,

    List 结构

    0e(0x0e)是 10 进制的 14,表示list类型的对象(在 3.2 版本之前,是由ziplistlinkedlist结构保存,之后存储是quicklist); 2 个字节长度的key:"li", 下来分别是一个长度的items:"a" 和 "b"

    Set 结构

    2,表示Set类型对象,3 个长度 "set",两个members:"a" 和 "b"

    Stream 结构

    module 之后,redis 在 5.0 增加了新的数据类型 Stream,不了解的同学可以 Google 下,很多介绍的文章。根据作者自己说,它也是充分借鉴了 kafka 的设计思想,在已有 list 的基础上增加了另一种流式类型。 基本。
    0f(0x0f)是 10 进制的 15,是Stream类型的对象,5 个长度的key:"stream"。然后是 StreamId结构体, 6d 70 b5 4a 7e分别是 10 进制的( 109 112 181 74 126 ),二进制 01101101 01110000 10110101 01001010 01111110,因为毫秒是uint,加上符号位即:1 01101101 01110000 10110101 01001010 01111110 对应如图所示: first-entry 恰好是创建stream的毫秒数,后面跟着 8 位的随机数0;然后是entry结构,每个entry结构前面,也会有和streamId相同的messageId,这里就不具体逐位分析了。长度是 3,第一个字段:"name"; 第二个字段:"age",3 个entry分别是name:Lambert,age:29name:Jack,age:26name:Tom,age:30;下来是消费组Group,名为:group 的消费组,因为没有任何消费,所以偏移量pending entry list都是0

    ZSet 结构

    0c 是 10 进制的 12,以ziplist结构存储的Sortedset类型,4 个长度的key:"zset",接下来的 4 表示:4 个元素,zset会将memberscore一起保存,所以,就是 2 组members;分别是:{memeber:"a",score:1}{member:"b",score:2}

    Hash 结构

    0d(13) 是RDB_TYPE_HASH_ZIPLIST,表示是ziplist存储的hash类型数据,1 个长度的 key:”h”。 key后面的 2,存着hash结构的fieldvalue;在 field 和 value 前面的 1,分别是指各自的长度,都是 “a”

    文件 EOF

    ff(255) EOF,在所有数据写完结束后,会以一个 EOF 结尾

    CheckSum

    Version 5 开始,如果在配置文件中开启rdbchecksum yes,会在RDB文件的结尾处,用 8 个字节记录,通过CRC64算法计算的整个文件内容的校验和。

    2 条回复    2019-10-01 01:16:09 +08:00
    arloor
        1
    arloor  
       2019-09-30 23:10:31 +08:00 via iPad
    rdb.c 清清楚楚
    such
        2
    such  
    OP
       2019-10-01 01:16:09 +08:00 via iPhone
    @arloor 恩,没错
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3508 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:11 · PVG 19:11 · LAX 03:11 · JFK 06:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.