分布式存储 = 单机存储引擎 + 分布式存储架构
news
https://github.com/OpenMPDK/uNVMe
单机存储引擎
首先基于这样的事实:磁盘的读写都是按着512Byte对齐的,针对单个磁盘扇区的操作是原子的,多个扇区就不是了,而且机械磁盘的顺序读写比随机读写要好很多
- 假设我们的存储场景都是针对512Byte对齐内的数据做操作,那我们可以设计服务为每次写流程,先读取对应扇区到内存,修改内存数据,然后回写数据到磁盘,这样能很好满足ACID特性
client(write x=100) => server(get sector/modify sector/write sector) - 但是通常我们的场景会复杂一些,修改的数据量会超过一个扇区,或者需要同时修改多个扇区里的数据,并且我们希望这批操作要么全部成功要么全部失败,此时明显我们不能直接修改磁盘数据(修改完部分扇区时,因为各种原因服务挂掉),由此我们引入WAL(write ahead log),修改磁盘数据前我们先记录数据当前状态至WAL并落盘,然后开始修改磁盘数据并删除这条log,最后返回客户端成功
client(write x=100) => server(write log/get sector/modify sector/write sector/remove log)
(若服务中间挂掉,恢复时读取该WAL, 即可恢复存储至安全状态,对应mysql的undo log) - 上面处理多扇区的写入方法中需要立即修改磁盘数据,我们知道WAL是顺序写可以充分利用磁盘性能,但是修改磁盘数据往往是随机操作,对机械磁盘非常不友好,因此我们引入另一种WAL2,记录数据写入之后的状态,并将要修改的数据先缓存在内存中,异步写入磁盘
(若服务中间挂掉,恢复是先应用所有WAL2,再应用所有WAL, 即可恢复存储至安全状态, WAL2对应mysql的redo log) - 但是对于对象存储的场景还是有问题,因为对象存储的数据量都比较大,每次需要记录WAL写放大严重,因此像bluestore这类存储引擎的解决方式是对于一次写流程,先把非覆盖写、覆盖写中的对齐写(大块)写入磁盘新Block,再把覆盖写中非对齐写部分和相关信息一起写入log