目录

前文列表

VMware 虚拟化编程(1) — VMDK/VDDK/VixDiskLib/VADP 概念简析

VMware 虚拟化编程(2) — 虚拟磁盘文件类型详解

VMware 虚拟化编程(3) —VMware vSphere Web Service API 解析

VMware 虚拟化编程(4) — VDDK 安装

VMware 虚拟化编程(5) — VixDiskLib 虚拟磁盘库详解之一

VMware 虚拟化编程(6) — VixDiskLib 虚拟磁盘库详解之二

VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三

VMware 虚拟化编程(8) — 多线程中的 VixDiskLib

VMware 虚拟化编程(9) — VMware 虚拟机的快照

数据块修改跟踪技术 CBT

CBT(Changed Block Tracking) 数据块修改跟踪技术,是 VMware 实现「增量备份」的底层支撑技术。CBT 的优势在于节约空间,它允许只备份发生了修改的数据。在 CBT 被引入之前,每次都必须要备份整个虚拟机,而不是增量备份。所谓增量备份,即仅备份两个快照时间点之间所被修改过的数据。开启了 CBT 的虚拟机会在其数据储存目录下新建一个 -ctk.vmdk 文件,用于记录数据块修改的跟踪信息。但开启 CBT 会对虚拟机的虚拟磁盘带来一些性能损失,所以默认会关闭 CBT。

CBT 的工作原理就是让 VMKernel 监控自上次快照时间点以来有那些数据块中的数据被改变了,并记录下这些被改变的数据块的偏移量,依靠这些偏移量就能够获取数据块中的修改数据了。

以下场景都支持 CBT:

  • 存储在 VMFS 上的虚拟磁盘(SAN or Local)
  • NFS 上的虚拟磁盘
  • 虚拟兼容模式的 RDM(裸设备映射)

以下场景不支持 CBT

  • 物理兼容模式的 RDM

为虚拟机开启 CBT

默认情况下 CBT 功能是禁用的,因为它会引起一个很小但是可被测量到的性能损耗。开启 CBT 的前提条件需要虚拟机版本为 7 或更高,我们可以使用 PropertyCollector 从 VirutalMachine ManagedObject 中获取这个 CBT 的属性域,如果其中含有 changeTrackingSupported 属性值,就该虚拟机支持 CBT 功能。

  • 使用程序设置 CBT
VirtualMachineConfigSpec configSpec = new VirtualMachineConfigSpec();
configSpec.changeTrackingEnabled = new Boolean(true);
ManagedObjectReference taskMoRef = serviceConnection.getService().ReconfigVm_Task(targetVM_MoRef, configSpec);
  • 手动设置 CBT

    • 右击虚拟机,选择「Edit Settings」
    • 点击「Options」
    • 点击「Advanced section」下的「General」,点击「Configuration Parameters」,开启「Configuration Parameters」窗口后,查找或添加「ctkEnabled」项,设置为「true」,并设置每个磁盘的「ctkEnabled=true」

在设置了 CBT 之后,需要重启虚拟机生效。

NOTE: vSphere WS API 能调用 configSpec.changeTrackingEnabled = new Boolean(true) 来动态的设置 CBT 状态,而不需关闭虚拟机。

CBT 修改数据块偏移量获取函数 QueryChangedDiskAreas

VMware vSphere WS API 中提供的 QueryChangedDiskAreas Method 能够帮助开发者获得虚拟机 CBT 的功能,该函数需要提供以下参数:

  • _this:目标 VirtualMachine moRef
  • snapshot:虚拟机当前的 Snapshot moRef
  • deviceKey:目标虚拟磁盘的 Id
  • startOffset:指定开始检查 CBT 的 offset,一般可以为 0
  • changeId:虚拟磁盘在某个时间点上的状态标识符,是一个格式为 <UUID>/<nnn> 的数字序列字符串,如果 <UUID> 改变了,跟踪信息就会失效。每次创建虚拟机快照时都会生成一个新的 changeId,你可以从快照的虚拟磁盘对象或 snapshot_moref 中获取新的 changeId。

QueryChangedDiskAreas 返回的是 DiskChangeInfo 数据对象,它包含一组 DiskChangeInfo.DiskChangeExtent 元素,分别表示已修改数据块磁盘区域的开始位移和长度,DiskChangeInfo 覆盖了整个磁盘区域的开始位移和长度。

EXAMPLE:(offset,length) 表示一个发生了修改的数据块的偏移量

(117768192, 65536)
(132120576, 65536)
(145096704, 43122688)
(265289728, 65536)
(958398464, 65536)

使用 QueryChangedDiskAreas 得到已修改数据块偏移量信息的前提条件是需要在创建快照前启用 CBT 功能,如果在启用 CBT 前调用该 Method 就会触发 FileFault 错误。

changeId

changeId 实际上就是虚拟磁盘在某个时间点的标识符。当我们调用 QueryChangedDiskAreas Method 时,除了可能会为形参 changeId 传入一串数字序列字符串之外,还可能会传入一个「*」号。

在使用 changeId 时,应该注意以下几点

  • 当虚拟机还没有快照时,虚拟磁盘的 changeId 初始值应该为 none 表示未设置的。

  • 当虚拟机创建第一个快照时,应该将传入「*」号,表示虚拟磁盘上所有的实际已分配的区域,同时忽略稀疏类型磁盘的未分配区域。需要注意的是,只有当虚拟磁盘的 changeId 初始值为 none 时,changeId=* 才会生效。换句话说,只有当虚拟机仅拥有一个快照时调用 QueryChangedDiskAreas,才能够将 changeId 设置为「*」,并且能够以此获得虚拟机的全量数据偏移量。

  • 在此之后的每次创建快照都会生成一个新的 changeId。如果 changeId 不再为 none,则表示虚拟机已经进行过至少一次快照,此后调用 QueryChangedDiskAreas 就能够得到自 changeId 标识的快照时间点以来所发生了修改的数据块偏移量,也就是增量数据偏移量。

总结一下,使用「*」时,存在下面两点限制

  • 虚拟磁盘必须存放在 VMFS 上。
  • 启动 CBT 时,虚拟机必须没有快照存在。

获取虚拟磁盘当前的 changeId

我们能够用过 VirutalMachine ManagedObject 的 vim.vm.device.VirtualDevice.VirtualDisk 配置项中找到虚拟机每一块虚拟磁盘的 backing 信息。如果 backing 的类型是下列中的一个,你就可以使用 BackingInfo 数据对象的 changeId 属性来获得其 changeId:

  • vim.vm.device.VirtualDevice.VirtualDiskFlatVer2BackingInfo
  • vim.vm.device.VirtualDevice.VirtualDiskSparseVer2BackingInfo
  • vim.vm.device.VirtualDevice.VirtualDiskRawDiskMappingVer1BackingInfo
  • vim.vm.device.VirtualDevice.VirtualDiskRawDiskVer2BackingInfo

最后总结一下,QueryChangedDiskAreas(..., "*") 实际上会返回虚拟磁盘被实际使用的(Thin)或者整个被分配的(Thick)的数据空间偏移量。CBT 的实现依赖于「虚拟磁盘的未分配区域」以及「 VMFS 的数据块延迟清零」两者的定义和特性。因此,CBT 只有在 VMFS 数据存储上才会返回有意义的结果。在其他存储类型上,要么就失败,要么就返回包含整个磁盘的单个内容。

在开启的 CBT 的前提下,第一次调用 QueryChangedDiskAreas(..., "*") 时,它会返回虚拟磁盘上所有 已经使用的 数据块区域,后续的调用则会返回 已修改的 数据块区域,而不是 已分配的 区域。

在没有开启 CBT 的前提下,在快照后调用 QueryChangedDiskAreas,则会返回 已分配的 区域,对于精简置备虚拟磁盘和延迟清零的厚置备磁盘而言,那些 已分配但未使用的 区域则会使用零值填充。也就是说这种情况下,即便是精简置备虚拟磁盘,其全量备份所得到的数据量等于为其所分配的数据量,而非实际所使用了的数据量。

一个 QueryChangedDiskAreas 的 DEMO

String changeId; //Already initialized: changeId, snapshotMoRef, the VM
ManagedObjectReferencesnapshotMoRef;
ManagedObjectReferencetheVM;
int diskDeviceKey; //Identifies the virtual disk.
VirutalMachine.DiskChangeInfochanges;
long startPostion = 0;
do {
changes =theVM.QueryChangedDiskAreas(snapshotMoRef, diskDeviceKey, startPostion,changeId);
for (int i = 0; i < changes.changedAread.length;i++) {
long length =changes.changedArea[i].length;
long offset =changes.chagedArea[i].startOffset;
//
// Go get and save disk data here
}
startPosition = changes.startOffset +changes.length;
} while (startPosition< diskCapacity);

在这个 DEMO 里,QueryChangedDiskAreas 被反复调用,同时开始检查位置 startPosition 在虚拟磁盘中不断往后移动。这是因为对于大型虚拟磁盘而言,ChangedDiskArea 数组很可能会占用大量的内存。

NOTE:需要注意的是,QueryChangedDiskAreas 获得的是已修改数据块的偏移量,而非实际的已修改数据。

应用 QueryChangedDiskAreas 设计的增量/差异备份算法

假设在 T1 时间点创建了一个初始的全量备份,之后在 T2、T3 时间点分别创建了增量备份。当然,你也可以使用差异备份,只是它会消耗更多的备份时间和带宽,但是拥有更少的还原时间。

  • T1 时间的全量备份

    1. 记录虚拟机的配置信息 VirtualMachineConfigInfo。
    2. 创建虚拟机快照,命名为 snapshot_T1。
    3. 获得并保存快照中各个虚拟磁盘的 changeId,changeId_T1。
    4. 备份调用 queryChangedDiskAreas(…, “*”) 所返回的已修改数据块扇区对应的数据。
    5. 删除快照 snapshot_T1。
  • T2 时间的增量备份

    1. 创建虚拟机快照,命名为 snapshot_T2。
    2. 获得并保存快照中各个虚拟磁盘的 changeId,changeId_T2。
    3. 备份调用 queryChangedDiskAreas(snapshot_T2, …, changedId_T1)返回的已修改数据块扇区对应的数据。
    4. 删除快照snapshot_T2。
  • T3 时间的增量备份

    1. 创建虚拟机快照,命名为 snapshot_T3 (此时你无法再获得 T1 到 T2 两个时间点之间的以修改数据块列表)
    2. 获得并保存快照中各个虚拟磁盘的 changeId,changeId_T3。
    3. 备份调用 queryChangedDiskAreas(snapshot_T3, …, changedId_T2)返回的已修改数据块扇区对应的数据。如果你希望执行差异备份,则调用 queryChangedDiskAreas(snapshot_T3, …, changedId_T1)。

      4删除快照snapshot_T3。
  • T4 时间的灾难恢复

    1. 使用之前保存的 VirtualMachineConfigInfo 中的配置参数,创建一个没有 GuestOS,没有虚拟磁盘的新虚拟机。
    2. 从 T3 的增量备份中还原数据,并记录还原了哪些扇区。
    3. 从 T2 中还原增量备份的数据,跳过 2 中已记录(已还原)的扇区,并记录还原了哪些扇区。如果 T3 是差异备份,则跳过此步骤。
    4. 从 T1 完全备份中还原数据,并跳过 2、3 中已记录(已还原)的扇区。
    5. 打开恢复过后的虚拟机。

NOTE:从后往前还原的目的就是获取同一数据块上最新的数据,从而避免不需要的数据拷贝。

VMware 虚拟化编程(10) — VMware 数据块修改跟踪技术 CBT的更多相关文章

  1. VMware 虚拟化编程(15) — VMware 虚拟机的恢复方案设计

    目录 目录 前文列表 将已存在的虚拟机恢复到指定时间点 恢复为新建虚拟机 灾难恢复 恢复细节 恢复增量备份数据 以 RDM 的方式创建虚拟磁盘 创建虚拟机 Sample of VirtualMachi ...

  2. VMware 虚拟化编程(13) — VMware 虚拟机的备份方案设计

    目录 目录 前文列表 备份思路 备份算法 备份细节 连接到 vCenter 还是 ESXi 如何选择快照类型 是否开启 CBT 如何获取备份数据 如何提高备份数据的传输率 备份厚置备磁盘和精简置备磁盘 ...

  3. VMware 虚拟化编程(11) — VMware 虚拟机的全量备份与增量备份方案

    目录 目录 前文列表 全量备份数据的获取方式 增量备份数据的获取过程 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/VADP 概念简析 VMware 虚拟化编 ...

  4. VMware 虚拟化编程(9) — VMware 虚拟机的快照

    目录 目录 前文列表 VMware 虚拟机的快照 快照的执行过程 删除快照 快照类型 Quiseced Snapshot 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDis ...

  5. VMware 虚拟化编程(3) —VMware vSphere Web Service API 解析

    目录 目录 前文列表 VMware vSphere Web Services API VMware vSphere Web Services SDK vSphere WS API 中的托管对象 Man ...

  6. VMware 虚拟化编程(14) — VDDK 的高级传输模式详解

    目录 目录 前文列表 虚拟磁盘数据的传输方式 Transport Methods Local File Access NBD and NBDSSL Transport SAN Transport Ho ...

  7. VMware 虚拟化编程(12) — VixDiskLib Sample 程序使用

    目录 目录 前文列表 vixDiskLibSample 安装 Sample 程序 Sample 程序使用方法 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/V ...

  8. VMware 虚拟化编程(5) — VixDiskLib 虚拟磁盘库详解之一

    目录 目录 前文列表 VixDiskLib 虚拟磁盘库 虚拟磁盘数据的传输方式 Transport Methods VixDiskLib_ListTransportModes 枚举支持的传输模式 Vi ...

  9. VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三

    目录 目录 前文列表 VixDiskLib 虚拟磁盘库 VixDiskLib_GetMetadataKeys VixDiskLib_ReadMetadata 获取虚拟磁盘元数据 VixDiskLib_ ...

随机推荐

  1. vue项目1-pizza点餐系统6-路由精讲之复用router-view

    1.在主组件展示二级路由的组件内容,在App.vue中添加 <br> <div class="container"> <!-- row 行排列 --& ...

  2. 关于代码手写UI,xib和StoryBoard

    代码手写UI 这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用.Geek们喜欢用代码构建UI,是因为代码是键盘敲出来的,这样可以做到不开IB,手不离开键盘就完成工作,可以专注于编码环境, ...

  3. 深度复数网络 Deep Complex Networks

    转自:https://www.jiqizhixin.com/articles/7b1646c4-f9ae-4d5f-aa38-a6e5b42ec475  (如有版权问题,请联系本人) 目前绝大多数深度 ...

  4. Azure IoT 技术研究系列2

    上篇博文中,我们主要介绍了Azure IoT Hub的基本概念.架构.特性: Azure IoT 技术研究系列1-入门篇 本文中,我们继续深入研究,做一个起步示例程序:模拟设备注册到Azure IoT ...

  5. Azure IoT 技术研究系列4

    上两篇博文中,我们介绍了将设备注册到Azure IoT Hub,设备到云.云到设备之间的通信: Azure IoT 技术研究系列2-设备注册到Azure IoT Hub Azure IoT 技术研究系 ...

  6. LeetCode--015--三数之和(python)

    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 先对nums进行排序,再用双指针,L ...

  7. 安卓手机通过有线连接PC上网

    因手机wifi坏了,速度上限为2.5m/s.无法发挥出100m带宽的威力. 这里探索各大神的指导,记录下其中一种方式. :链接       主题:使用openvpn和手机的USB共享网络 通过mico ...

  8. vue父组件更新,子组件也更新的方法

    1.父组件 使用 Math.ramdom() 2.子组件获取 然后监听这个ramdom变化,处理子组件的更新

  9. 关了浏览器再开,怎么session还在?

    关了浏览器session当然仍然存在,因为session是储存在服务器端的,而服务器是不可能知道你有没有关掉浏览器. 服务器只是简单的保持session接受用户请求,只有当session一段时间没有被 ...

  10. Acitiviti的查询及删除(六)

    流程定义查询 查询部署的流程定义. /** * 查询流程定义信息 //act_re_procdef */ public class QueryProcessDefinition { public st ...