听小董谝存储七

目录
序章
一些设定
关于WAL
恢复
我爱glt
序章
前面几章 , 我们已经明白了层的读写流程 。但是我们还有问题如果机器断电了 , 数据怎么恢复 。
一些设定
首先我们得先确定下面几个问题
【听小董谝存储七】1 什么时候需要恢复数据?
当进程挂掉的时候
当机器直接死机了
2 什么时候恢复的数据会真的被使用?
我们有三个副本 , 当一个或者两个副本死掉了 , 我们会指向搬迁操作 , 把数据在新的地方变成新的三副本 。只有当3个机器都死掉了 , 我们才需要使用恢复的数据 。
3 哪些数据需要恢复?
图一 层的数据分布
如上图 , 我们先分析一下 , 图里面的几个模块都在什么地方 。
共享内存里:黄色的索引块 , 里面的数据
磁盘里:那就是已经下刷到磁盘里面的数据 。
不管是否断电 , 磁盘里的数据都在 , 跑不了 。我们不用管 。
如果只是进程死掉了 , 那么进程重启的时候 , 只要重新把共享内存拉起来就能继续工作了 。
如果是机器之间挂掉了 , 重新启动机器后 , 共享内存没有了 。如果我们此时什么都不做 , 那我们面对的情况就是一个磁盘 , 磁盘里面有一堆数据 , 但是我压根不知道哪个key在哪个位置 。
没有桥 , 老子就过不了河了么?
我tm绕着地球走一圈照样能过去!
就好像你给我一个没有了索引的字典 , 你让我怎么查?
没有索引的字典就不能查了么?
当然可以 。我把字典的正文一页页的看 , 然后看到一个字就把它记录到索引里 。我手动恢复索引不就OK了 。
我们要恢复的其实就是内存里的索引 。
图二 丢失了索引
如上图二 , 我们没有任何数据索引 。可是我们有的索引 , (前面每次下刷数据 , 回收block的时候 , 的数据都会落盘)我们按照block生成的顺序从最早到最近依次遍历所有的block就能把数据索引反向补充回来 。
图三 根据 依次遍历block
图三有两个block里面都有DataB , 该怎么处理呢?还需要说么?
搞定了 , 数据都恢复了 。
恢复个屁!
还有一些数据在里面呢 , 那些数据还没有进磁盘呢!断电就没有了 。
关于WAL
刚才提到在里面的数据还没有下刷 , 都在内存里 , 断电自然就没有了 。那么 , 咱们就把它们也放到磁盘里 。写内存之前 , 就先放到磁盘里 。也就是所谓的WAL(Write Ahead Log) 。具体什么流程呢?如下图四的左半部分 , 就是数据在写入之前 , 就先写入缓存 , 如果缓存里面的数据大于8KB , 就下刷到磁盘里的文件里 。(这个文件在mysql里面叫redo log)
(有人说又要下刷磁盘 , 这恐怕对性能又损失 。没办法 , 我们做的就是一个平衡的事情 , 而且顺序写ssd , 速度也不是慢点不可接受 , 如果不下刷 , 或者说压根就不引人机制 , 速度确实能快点 , 但是一旦断电就麻烦了)
那磁盘里面的得有多大?换句话说 , 得保存多久 。看图四的右半部分 。的长度不会大于的长度 。每次从里面取数据下刷的时候 , 就会更新的起点 。
这样一来 , 任何时候断电 , 我们最多损失8KB的数据 。(当然 , 我们也可以来一个数据 , 就顺序写一次到ssd , 但是前面也说了 , 这就是个平衡 , 你也可以当缓存大于80KB的时候下刷 。)