
和本地DMA的概念类似,remote direct memory access 技术可以使同一网络中的主机绕过其他主机的CPU、cache、操作系统等模块直接读写其他主机的数据。其有如下优势:
SPDK是Intel提供的一个操作RDMA的库。
新型非易失存储器在持久化、随机读写能力、存储密度、扩展能力、漏电功耗等多个方面与传统的存储介质相比具有明显优势。主要考虑是的两个方面:
NVMe和NVM不是一个东西;NVMe是和AHCI是同一类同,其是一个存储接口协议,AHCI是早期将HDD接到PCIe上的存储接口协议;NVMe是适配SSD接到PCIe上的存储接口协议。
将传统的本地文件系统抽象为一个分布式文件系统;提供类似的文件api;db基于日志即数据的概念,将redo日志放在分布式文件系统中冗余存储;这样读写节点共享同一份数据。
我了解的PolarDB的结构如下:

角度AuroraPolarDB分布式文件存储存储的数据包括RedoLog和Page,以10GB为单位划分的6副本,基于gossip协议实现数据一致性。存储的数据包括RedoLog和Page,以10GB为单位划分的3副本,基于Parallel-Raft实现的数据一致性。向存储层写入的内容只有redolog,存储层不断重建page;写入redolog和page。但是通过RDMA与OptaneSSD等新硬件优化。读写一致性基于Quorum协议,读写按照多数派满足的方式获取最新数据。数据读写只在主副本上进行。代码增加物理复制的增加InnoDB的物理复制;通过修改调用文件的api将数据写入到分布式文件存储中。异常恢复主挂,因为底层不断的进行recovery,从秒升主。不走经典的redo/undo逻辑。类似单机MySQL的恢复方式社区融合与社区版本代码相差较大,比较慢跟进新功能。相对容易跟进新功能。
PolarFS是一个用户空间的分布式文件系统。MySQL代码可以容易的从Linux FS迁移到PolarFS;提供了O_DIRECT的读写操作;支持数据页的原子写;

PolarFS的存储组织
与大多数存储系统一样,PolarFS对存储资源也进行了多层封装和管理,PolarFS的存储层次包括:Volume、Chunk和Block,分别对应存储领域中的数据卷,数据区和数据块,在有些系统中Chunk又被成为Extent,均表示一段连续的块组成的更大的区域,作为分配的基本单位。一张图可以大致表现各层的关系:

Volume
当用户申请创建PolarDB数据库实例时,系统就会为该实例创建一个Volume(卷,本文后续将这两种表达混用),每个卷都有多个Chunk组成,其大小就是用户指定的数据库实例大小,PolarDB支持用户创建的实例大小范围是10GB至100TB,满足绝大部分云数据库实例的容量要求。
跟其他传统的块设备一样,卷上的读写IO以512B大小对齐,对卷上同个Chunk的修改操作是原子的。当然,卷还是块设备层面的概念,在提供给数据库实例使用前,需在卷上格式化一个PolarFS文件系统(PFS)实例,跟ext4、btrfs一样,PFS上也会在卷上存放文件系统元数据。这些元数据包括inode、directory entry和空闲块等对象。同时,PFS也是一个日志文件系统,为了实现文件系统的元数据一致性,元数据的更新会首先记录在卷上的Journal(日志)文件中,然后才更新指定的元数据。
跟传统文件系统不一样的是PolarFS是个共享文件系统即一个卷会被挂载到多个计算节点上,也就是说可能存在有多个客户端(挂载点)对文件系统进行读写和更新操作,所以PolarFS在卷上额外维护了一个Paxos文件。每个客户端在更新Journal文件前,都需要使用Paxos文件执行Disk Paxos算法实现对Journal文件的互斥访问。更详细的PolarFS元数据更新实现,后续单独作为一个小节。
Chunk
前面提到,每个卷内部会被划分为多个Chunk(区),区是数据分布的最小粒度,每个区都位于单块SSD盘上,其目的是利于数据高可靠和高可用的管理,详见后续章节。每个Chunk大小设置为10GB,远大于其他类似的存储系统,例如GFS为64MB,Linux LVM的物理区(PE)为4MB。这样做的目的是减少卷到区映射的元数据量大小(例如,100TB的卷只包含10K个映射项)。一方面,全局元数据的存放和管理会更容易;另一方面,元数据可以全都缓存在内存中,避免关键IO路径上的额外元数据访问开销。
当然,Chunk设置为10GB也有不足。当上层数据库应用出现区域级热点访问时,Chunk内热点无法进一步打散,但是由于每个存储节点提供的Chunk数量往往远大于节点数量(节点:Chunk在1:1000量级),PolarFS支持Chunk的在线迁移,其上服务着大量数据库实例,因此可以将热点Chunk分布到不同节点上以获得整体的负载均衡。
在PolarFS上,卷上的每个Chunk都有3个副本,分布在不同的ChunkServer上,3个副本基于ParallelRaft分布式一致性协议来保证数据高可靠和高可用。
Block
在ChunkServer内,Chunk会被进一步划分为163,840个Block(块),每个块大小为64KB。Chunk至Block的映射信息由ChunkServer自行管理和保存。每个Chunk除了用于存放数据库数据的Block外,还包含一些额外Block用来实现预写日志(Write Ahead Log,WAL)。
需要注意的是,虽然Chunk被进一步划分为块,但Chunk内的各个Block在SSD盘是物理连续的。PolarFS的VLDB文章里提到“Blocks are allocated and mapped to a chunk on demand to achieve thin provisioning”。thin provisioning就是精简配置,是存储上常用的技术,就是用户创建一个100GB大小的卷,但其实在卷创建时并没有实际分配100GB存储空间给它,仅仅是逻辑上为其创建10个Chunk,随着用户数据不断写入,PolarFS不断分配物理存储空间供其使用,这样能够实现存储系统按需扩容,大大节省存储成本。
那么为何PolarFS要引入Block这个概念呢,其中一个是跟卷上的具体文件相关,我们知道一个文件系统会有多个文件,比如InnoDB数据文件*.ibd。每个文件大小会动态增长,文件系统采用预分配(fallocate())为文件提前分配更多的空间,这样在真正写数据的时无需进行文件系统元数据操作,进而优化了性能。显然,每次给文件分配一个Chunk,即10GB空间是不合理的,64KB或其倍数才是合适的值。上面提到了精简配置和预分配,看起来是冲突的方法,但其实是统一的,精简配置的粒度比预分配的粒度大,比如精简配置了10GB,预分配了64KB。这样对用户使用没有任何影响,同时还节省了存储成本。

上图右侧的表描述了目录树中的某个文件的前3个块分别对应的是卷的第348,1500和201这几个块。假如数据库操作需要回刷一个脏页,该页在该表所属文件的偏移位置128KB处,也就是说要写该文件偏移128KB开始的16KB数据,通过文件映射表知道该写操作其实写的是卷的第201个块。这就是lipfs发送给PolarSwitch的请求包含的内容:volumeid,offset和len。其中offset就是201*64KB,len就是16KB。
PolarSwitch
PolarSwitch是部署在计算节点的Daemon,即上图的Data Router&Cache模块,它负责接收libpfs发送而来的文件IO请求,PolarSwitch将其划分为对应的一到多个Chunk,并将请求发往Chunk所属的ChunkServer完成访问。具体来说PolarSwitch根据自己缓存的volumeid到Chunk的映射表,知道该文件请求属于那个Chunk。请求如果跨Chunk的话,会将其进一步拆分为多个块IO请求。PolarSwitch还缓存了该Chunk的三个副本分别属于那几个ChunkServer以及哪个ChunkServer是当前的Leader节点。PolarSwitch只将请求发送给Leader节点。
ChunkServer
ChunkServer部署在存储节点上,即上图的Data Chunk Server,用于处理块IO(Block IO)请求和节点内的存储资源分布。一个存储节点可以有多个ChunkServer,每个ChunkServer绑定到一个CPU核,并管理一块独立的NVMe SSD盘,因此ChunkServer之间没有资源竞争。
ChunkServer负责存储Chunk和提供Chunk上的IO随机访问。每个Chunk都包括一个WAL,对Chunk的修改会先写Log再执行修改操作,保证数据的原子性和持久性。ChunkServer使用了3D XPoint SSD和普通NVMe SSD混合型WAL buffer,Log会优先存放到更快的3DXPoint SSD中。
前面提到Chunk有3副本,这三个副本基于ParallelRaft协议,作为该Chunk Leader的ChunkServer会将块IO请求发送给Follow节点其他ChunkServer)上,通过ParallelRaft一致性协议来保证已提交的Chunk数据不丢失。
PolarCtrl
PolarCtrl是系统的控制平面,相应地Agent代理被部署到所有的计算和存储节点上,PolarCtrl与各个节点的交互通过Agent进行。PolarCtrl是PolarFS集群的控制核心,后端使用一个关系数据库云服务来管理PolarDB的元数据。其主要职责包括:
监控ChunkServer的健康状况,包括剔除出现故障的ChunkServer,维护Chunk多个副本的关系,迁移负载过高的ChunkServer上的部分Chunk等;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3139944/ ,如需转载,请注明出处,否则将追究法律责任。