最新消息:

大话Sheepdog 2 – 对象缓存

未分类 admin 4015浏览 0评论

分布式存储系统的性能一直都是众矢之的,主要是因为数据甚至元数据的存取都添加了网络层的开销。对于多拷贝的对象存储来说,甚至还有复杂的逻辑来保持各个拷贝的一致性。对于拷贝的读写,读写的优化通常是不可兼得。比如通过最终一致性(eventual consistency)优化了写,但是读的时候需要读取大于一份的拷贝,来判断是否是最新的。这些问题都导致了性能的低下。

很多POSIX文件的操作都是元数据操作的重度用户,通常一个文件系统的系统调用会含有多个元数据操作。比如在EXT4上,一个简单的读4K大小的数据操作,最坏的情况会读3次(对于大文件来说,可能大于3次)磁盘,但是只有一次磁盘操作用于读这个4K数据,而其它操作都是元数据操作。这也是为什么Linux内核需要引入复杂的dentry和inode两个cache来加速元数据操作。所以对于很多支持POSIX文件操作的分布式文件系统来说,额外的元数据操作加重了性能的恶化,往往一次系统调用会产生好几次的网络数据操作。而块设备的操作模式简单很多:顺序的读、写和冲刷(FLUSH),没有了元数据的读写负担,所以Sheepdog可以相对简单高效的存取数据,强一致性写,读任意一份拷贝即可。Sheepdog的读操作是1比1的比例,不会有任何额外的操作。这也算得上Sheepdog 相对于分布式文件系统如GlusterFS用文件来提供卷服务的优势,避免了不必要的POSIX软件层的开销。QEMU、虚拟机与Sheepdog集群的关系如下图所示:
sd-node

虽然Sheepdog用哈希算法来寻址数据,免去元数据的操作,实际上也有自己的元数据。这个元数据同普通的数据对象一样,也是一个固定大小的对象,专门用来描述虚拟卷(一个卷对应着一个元数据对象)。Sheepdog通过这个元数据来实现以下的功能:数据的稀疏存储和写时复制(Copy-On-Write)。对于这个特殊的对象,由于很小,虚拟机在启动的时候QEMU就会整个读取加载到内存里面,当写到卷的“空洞”的时候,也就是需要创建一个数据对象来装载用户数据时,才会去更新这个元数据对象。

同其它软件一样,Sheepdog也通过客户端的缓存,对象缓存(Object Cache)来加速对象的存取。但是这个对象缓存除了加速IO操作,还有另外一个重要的功能:减少网络的流量。这对于大规模的集群至关重要,因为相对于处理器和硬盘来说,带宽更加紧张也更容易成为集群扩展的瓶颈。

体验对象缓存

 # 启动3个节点,并且开启200M大小的对象缓存。因为shm不支持directio,所以默认没有开启directio模式
 $ for i in 0 1 2; do sheep /tmp/store$i -c local -w object:size=200:dir=/dev/shm/$i -z $i -p 700$i;done
 $ collie cluster format -b plain
 $ collie vdi create data 1G
 # 然后您可以启动虚拟机,像往常一样挂载data卷,或者直接把操作系统安装到卷上,体验加速的卷!

对象缓存实现原理

对象缓存的实现非常的简单和直观,这里我用本地文件作为块设备的存储后端来做类别,描述其工作机制。当用本地文件作为存储后端时,比如(QCOW2格式),我们主要通过主机的内存页来缓存模拟的块设备的块来加速IO性能(writeback模式)。首先QEMU将这些模拟的设备块对应到文件的逻辑块上,然后内核在内部把文件的逻辑块对应到页缓存(Page Cache)的内存页上,并且依赖内存子系统来预读数据/回写脏数据。所以虚拟机的块设备操作通过一系列的转换变成了内存页的读写。一般情况下,只有虚拟机发送冲刷(比如虚拟机里面执行了fsync(2))请求的时候,内核才会将这些脏数据回写到硬盘。当然,现实更加复杂,因为内存是有限的,所以当内存不够时,内核还要通过LRU(Least Recently Used)算法进行页面回收。如下图所示:

QEMU 《----》 VM
  ^
  |                           writeback/readahead pages
  V                                                |
POSIX file 《 --- 》 page cache 《 --- 》 disk
                                     |
             Kernel does page wb/ra and reclaim

对象缓存跟这个结构非常的类似,如下图所示:

QEMU 《----》VM
  ^
  |                                                 push/pull objects
  V                                                             |
Sheepdog device 《--- 》 object cache 《 --- 》 Sheepdog replicated object storage.
                                                  |
                  Sheep daemon does object push/pull and reclaim

这里sheep进程扮演了内核的角色,内存页变成了对象。同本地文件一样,虚拟机的读写请求在操作完缓存里面的对象后就返回了,只有当收到冲刷的请求时,才会把脏数据回写到集群中去。值得注意的是,同本地文件一样,对象缓存只是充当虚拟卷(块设备)的磁盘缓存,并没有牺牲任何虚拟机里面文件系统的数据一致性,因为目前的操作系统(包括Linux和Windows)几乎都是磁盘缓存感知的,当认为数据必须写到持久化介质时,都会显示的发送冲刷命令,同时应用程序也可以通过fsync(2)或者open(2)参数设置SYNC标记发送冲刷请求。同本地文件缓存还有一个大的区别,就是对象缓存可以选择把数据放在磁盘上而不是内存里,这样不会占用相对紧张的内存资源。对象缓存也是通过LRU算法来进行对象回收的。

对象缓存、快照与热迁移

当虚拟机释放(如关机等)的时候,sheep进程负责冲刷脏数据(如果还有的话)和回收对象,释放缓存,所以不管是关机冷迁移,还是运行时热迁移,对象缓存都会自动的随着虚拟机迁移到指定的节点,不需要用户任何手动的介入。

对象缓存也考虑到了克隆的数据去冗余。当多个克隆来自于同一个快照的时候,这个时候这些克隆将共享大多数的数据(如操作系统和大多数系统配置文件),而所有共享的数据在缓存中只有一份拷贝。这些共享对象也是写时复制的,所以不会出现任何安全问题。

转载请注明:爱开源 » 大话Sheepdog 2 – 对象缓存

您必须 登录 才能发表评论!