本章的许多术语及概念都容易引发误解,因为它们在IT领域之外还有日常的含义,backup与archive这两个词尤其如此。你只要想一想这些词在日常用语里都有哪些意思,就明白笔者为什么说它们容易引发误解了。
警匪片里总是出现wait for backup(等待支援)这样的台词,这里的backup是支援的意思。另外,我们总说某个东西一定要有一份backup,这里的backup是备用品的意思,也就是跟那个东西一样或者相似的一件物品,例如“我妻子开的那辆车,是我的backup车(备用车)”。
即便在IT领域,backup也有一些跟下面要讲的经典含义不同的用法。例如我们总说给文件做一个backup复制,这里的backup实际上就是该文件的一份copy(副本),这份copy一般就放在原文件的旁边。(本章稍后会说到,这种做法违背了3-2-1原则,因此这只是一个copy,而不是真正的备份。)
另外还有virtual snapshot(虚拟快照),这个词经常用在涉及NAS(网络附加存储)的场合,其实它连copy都不算,因为它只是一种虚拟的copy,必须依赖原文件才能体现出它的意义,而不像刚才那段话里提到的普通copy,可以脱离原文件独立使用,尽管刚才说的那种copy是放在原文件旁边的,因此不是真正的备份,但至少可以单独使用。笔者把virtual snapshot这样的copy称为convenience copy(便捷复制或方便复制),因为这样的快照做起来很方便,虽然其也能够充当真正的备份,但笔者还是想把这两个东西区别开,我不会直接将其称为备份。
备份是对数据所做的一份copy,它与原数据分开存放,并且能够把这份数据恢复到早前的状态,之所以恢复,通常是因为原数据受某种原因影响而遭到删除或破坏。下面我们就依次讲解这个定义里的几个关键要素,让大家理解什么才是真正的备份。
让我再当一下语法学究吧。backup是个复合词,它是由back与up这两个词复合而成的。当动词用时,应该写成两个词。一定要分开写,不然句子就不通了。I back up、You back up、She backs up、He backed up等写法都是正确的(不能写成I backup、You backup……)。当名词用时,则应该写成一个词。例如“When I back up, I make a backup.”(第一个分句里的back up是动词,所以要分开写,第二个分句里的backup是名词,所以要合起来写)。大家明白了吗?
copy是对原数据所做的逐字节重制,它的内容与原数据相同。Linux系统的 cp 命令或Windows系统的 copy 命令,创建出来的就是这样的一份copy。你在操作系统的File Explorer(文件管理器)里通过图形界面复制并粘贴文件,所形成的也是这种copy。如果你用 tar 命令、 dump 命令、 cpio 命令、Windows的backup软件,以及其他一些商用的backup软件把原文件重制了一份,那么这样做出来的依然是copy。严格来说,对文件所做的copy,还应该包含所有的metadata(元数据/后设数据),尤其是与安全及权限有关的配置数据。这样的copy能不能充当备份,还要看它是否满足定义中所说的另外两项要求。
这里必须讲清楚,什么样的东西不算copy。前面说过,对文件系统或存储系统所做的virtual snapshot(虚拟快照)不是copy,因为它们并不包含原数据里的内容。它们只是在许多地方引用了原数据而已。NAS的快照、XFS的快照、Windows的VSS(Volume Shadow Copy Service,卷影复制服务)快照,以及VMware或Hyper-V这样的虚拟机管理程序所做的快照,都属于virtual snapshot,它们本身并不能算作copy。凡是那种必须依赖原数据而存在的“copy”,都不是真正的copy,它们只能算作虚拟的copy(virtual copy)。这样的虚拟copy连备份的第一项要求都无法满足,因此就更不能充当备份了。
当然,这里必须指出,如果你把virtual snapshot复制到了另一个系统,那么它就成了一份真正的copy了,这种copy,跟你把原数据直接复制到另一个系统所形成的copy,其实差不多。而且,这种通过把快照重制到另一个系统上而形成的copy,要比普通的copy更好,因为在这样的copy里面,每个磁盘中的数据都是从同一个时刻抓取的,就算重制这份copy所花的时间很长,也能保证这一点,而不像普通的copy,难以保证这些磁盘中的数据会不会在制作copy的过程中有所变化(关于快照的更多细节请参见本书第9章)。
通过快照来制作备份是相当棒的。你可以先把数据库调整到备份模式,然后对文件系统做一份快照,或者对数据库做一份合适的VSS快照并将其复制到你的备份系统里面。这几种都是相当稳固的备份手法。只是你必须意识到:依赖原数据而存在的快照,不是一份合格的copy,你必须把它重制(也就是复制)到其他地方,才能让它成为一份真正的copy(因为在重制的过程中,这份快照为了不再依赖原数据,必须把那些数据囊括进来)。
虽然刚才提到的那几种virtual snapshot本身并不是真正的copy,但在IT领域,有一些snapshot(快照)确实是copy,你不能把这种snapshot与刚说的那几种virtual snapshot混为一谈。例如AWS Elastic Block Store(EBS)的snapshot,还有你在AWS或其他云平台里制作的snapshot,它们都是真正的copy,而不是virtual snapshot。笔者把这样的snapshot称为image copy(镜像复制),因为它们是在逐字节地复制原数据,相当于对原数据做了一个镜像。某些数据库产品也把这种备份称为snapshot,这其实同样属于image copy。
如果你把copy保存在了跟原数据相同的文件系统、计算机或数据库里面,那么笔者认为你做的仅是便捷复制,而不是真正的备份。如果原数据受某种原因影响而遭到摧毁,那么这种copy也会随之丢失,所以说,它起不到对原数据做备份的作用,它只是出现在原数据旁边,方便你随时取用而已。因此,做备份时一定要把数据保存在远离原数据的地方。笔者在3.2.6节讲解3-2-1原则时,会详细解释这个问题。
这才是真正体现出备份与其他一些copy有所区别的地方,archive(档案)也是一种copy,而且也是跟原数据分开存放的,但archive并不能算作备份,因为它虽然符合定义的前两项要求,但却不符合第三项要求。只有那种能够在原数据受损时用来恢复原数据的copy,才是备份。这个道理并不难懂。(本章后面就会讲到,archive不是用来恢复数据的,它们是用来获取数据的,这跟恢复数据不是一回事。)
比方说,原来的文件、驱动器、服务器甚至数据中心可能遭受了损害,无法修复。你可能不小心删掉了不该删的文件,或不小心修改了不该改的文件并且把修改后的内容保存了下来。你可能从数据库里删掉了一张不该删的数据表。你可能在格式化驱动器时把盘符给弄错了——你本来是想把一个无用的盘格式化,将其腾空,结果却把另一个包含有用数据的盘给格式化了(笔者几周前就弄错过一次)。你的RAID-6阵列可能出现了三盘错误(triple-disk failure)。虽然这种阵列能够同时经受最多两块磁盘出现故障的情况,但要是有三块盘同时出现故障,那么数据就会丢失。这种情况真的有可能出现,笔者就遇到过一晚上坏掉6块磁盘的服务器(嗯,我还做了备份呢)。数据中心可能会遭遇火灾、水灾,或勒索攻击。在出现这些状况时,你需要通过备份来恢复数据。如果你的copy是为了应对这些状况而制作的,那么这样的copy就是真正的备份。
前面在定义备份时,其实已经顺带给恢复(restore)一词下了定义,这指的是一种通过备份让数据回到早前状态的操作。下面我们就来深入探讨这种操作,看看它跟另一种操作,也就是获取(retrieve)相比,有何区别,那种操作针对的是档案。
首先,恢复通常是为了让服务器或文件系统的状态回到距离当前较近的某个点。我们一般会利用备份把数据恢复到昨天的模样,如果备份得更为及时,那么你还能够恢复到距离现在更近的点。恢复数据时,我们通常总是会使用最近制作的那个备份。后面会提到几种例外情况,在那几种情况下,我们可能要把文件系统恢复到6个月前的样子。除了那几种例外,我们肯定不会把生产数据库恢复到两周之前的状态,因为那样做会导致这两周的数据操作信息以及与之相关的业务信息丢失。无论恢复的是文件、服务器还是数据库,我们在恢复时使用的一般都是距离当前最近的那个备份。
你可能觉得奇怪,这么简单的道理还用得着说吗?别急,接下来你会看到几种例外的情况。
有这样几种例外情况,让我们并不想用最接近现在的那个备份来恢复数据。比方说,你发现某个文件是在6个月之前删掉的,而你想把这份文件恢复出来,在这种情况下,你所要使用的就应该是6个月前制作的备份,而不是距离现在最近的备份。又比方说,你发现某个勒索病毒在正式开始扰乱数据之前,已经在系统里面待了很久,这种情况下,你必须使用在病毒入侵系统之前所做的备份来恢复该系统。有时你可能想用以前某个时间点所制作的备份来恢复生产数据库,把它恢复到一个专门用来做测试或开发的环境里,并将当时的那个旧版数据库与现在的新版数据库对比。为什么要做这样的对比呢?可能是因为数据库的schema(纲要/模式/结构)发生了大幅变化,你怀疑最近出现的性能问题跟这个变化有关。为此,你要把数据库恢复到修改schema之前的样子,看看那个数据库的性能跟现在的数据相比究竟如何。
像刚才那样使用制作时间稍早的备份来恢复数据是比较少见的。还有一些更为少见的情况,要求我们把数据恢复到更早之前(例如9个月甚至一年多之前)的样子。明白这些例外之后,接下来就要看看到底怎样通过备份恢复数据。
恢复数据时需要知道许多信息,以确定应该从哪个备份里恢复。你需要知道服务器或VM的名字(除非你用的是容器)、应用程序的名字,以及登录服务器或VM所需的账号与密码,另外可能还得提供该层级之下某些更为详细的名称。比方说,要恢复的文件系统名是什么(例如 H:\ 或 /data ),要恢复的目录名是什么(例如 /data/data1 ),要恢复数据库里的哪一张数据表(例如恢复 users 数据表),或者要恢复对象存储系统里的哪个bucket等。这些都是位于VM/服务器/应用程序这一级别之下的细节信息。你通常还得知道你要恢复的这个东西(例如某个文件、某条数据库记录或某个对象)具体叫什么。(当然,如果你恢复的是整个VM/服务器/应用程序,那么只需要知道VM、服务器或应用程序的名字就行,而不用提供更为详细的名称。)
最后,也是最为重要的一点,在于你必须知道自己想把这个有问题的东西恢复到它在哪一时刻的样子。比方说,这份文件是你今天早上不小心弄坏的,那你就应该寻找在今天早晨之前所制作的最新备份,又比方说,这张数据表是你5min之前删掉的,那你就应该寻找制作时间距现在超过5min且最近的一个数据库备份。
你需要找到你在数据受损之前的某个时刻所制作的备份,并通过该备份来恢复某一服务器、VM或应用程序里某一区域(例如某个数据库、某个文件系统、某个目录、某个bucket)中的一条或多条数据。
喜欢较真的人可能会说:“但有时我是要把所有服务器全都恢复了。”没错,确实有这种情况。但根据笔者的看法,这其实还是在针对单独的服务器做恢复,只不过是你把这个恢复操作多次套用在了不同的服务器上。用同一个备份来恢复多台服务器是可以的,但不能在同一个服务器、数据库、文件系统或文件上同时拿多个版本的备份来恢复数据。
就算你是在某个东西上用多个版本的备份来做恢复,严格地说,你每次恢复时所用的也仅是其中的一个版本,你是在做完一次恢复之后再用另一个版本的备份来恢复的,而不是同时采用多个版本的备份做恢复。之所以这样做,很可能是为了试探,也就是说,你并没有足够的信息确定自己到底应该采用什么时间所制作的那个备份,所以只好多次尝试。你可能忘记了文件或数据库最后一次处于正常状态是在什么时候,其实这还算比较好的情况,更糟糕的是你不知道丢失的这份文件在哪个目录里,甚至你根本不知道这份文件叫什么名字。
某一次恢复操作能够把某件事物恢复到它在某个时间点上的样子。仅此而已。
这跟从档案中获取数据是有很大区别的,甚至根本就不太相干。笔者在本章稍后就会讲到,从档案中执行获取操作,所得到的是某个比较大的时间段内的许多数据。这里我们暂停一下,先讲3-2-1原则,然后再来谈档案与备份有何区别。
笔者在本书中提到本节的次数要比提到其他章节的次数都多。书中的每一章或许都会说到3-2-1原则,而且在笔者制作的 Restore It All 播客 [1] 里,几乎每期都会提起该原则。奇怪的是,笔者在这么多年的工作之中其实一直都遵循着这条原则,但却迟迟没有意识到这一点,因此,我现在要反复强调它,让大家都意识到该原则。
3-2-1原则是所有备份工作的基本原则。它在备份工作中的意义就跟E=mc 2 这个质能方程在物理学中的意义一样大。如果你怀疑自己设计的备份方案不太合适,那你就应该赶紧验证一下,看它是不是违背了3-2-1原则。
简单地说,3-2-1原则意味着你应该至少对数据做3个版本的备份,把它们放在2个不同的介质上,并将其中1份放在远处。下面我们就来谈谈这条原则里的三个部分。
按照笔者的理解,这里所说的3个版本,是指除原数据之外还有3个版本。我在运用3-2-1原则时,从来都没有把受保护的数据本身给算进去。为什么要保留3个版本呢?因为有时我们会接连发生失误,例如在没有意识到某份文件已经遭到破坏的情况下,继续操作这份文件。最近的那个备份可能是在该文件已经破坏的时候制作的,如果用这个版本的备份恢复数据,那么恢复出来的文件依然是坏的。因此,笔者主张至少保留3个版本。
备份与恢复数据的具体方案有很多种,这些方案通常都会保留至少3个备份版本,因此笔者建议你在设计自己的备份方案时也这样做。3是下限,而不是上限。现在有许多办公软件会频繁地备份,让你能够多次撤销(undo)自己对文档所做的操作。数据库的事务日志(transaction log)实际上也相当于是在每天给数据库做上千次备份,让你能够多次撤销(undo)与重做(redo)。有些笔记本计算机同样在不停地备份,甚至每分钟都会备份一次,这样可以确保你所操作的每份文件都留有好多个版本,就算是在误操作发生半小时之后才意识到的,你也可以找到距离当时较近的版本,从而将文件恢复到正常状态。
不要把所有的备份都保存到同一介质中,例如放在同一块硬盘、同一张光盘、同一个优盘里面。原数据与你给该数据所做的备份肯定不能保存到同一介质上。笔者特别爱用Mac OS的Time Machine(时间机器/时光机)来举例,这也是我很喜欢的一款软件。你可以在Mac OS的磁盘管理器中把总盘分成两个区,让它们成为操作系统里的两个小盘,然后你就可以配置Time Machine,把第一个盘里的数据备份到第二个盘了。然而一看到这种做法,你就应该立刻意识到,它很不妥。这样确实可以给第一个盘中的数据做多个版本的备份,并在必要时从第二个盘里拿出你想要的那个版本予以恢复,可要实现这种效果,必须保证一个前提,就是整块物理磁盘没有损坏。
如果整个盘都坏了,那么保存备份的这个分区自然无法访问,于是这意味着你根本就没有做任何备份。因此,你必须把备份放在跟原数据不同的磁盘上,或者存放到与你要保护的这台计算机不同的另一台计算机上。笔者建议你不要把备份存放在距离受保护的计算机很近的地方。跟本书里的其他经验一样,这条经验我也是很早就体会到了。
许多年前,笔者在MBNA找到了第一个与备份有关的工作,我们当时有磁带库。这里说的磁带库其实是磁带柜(tape library),指的是一种专门用来存放磁带的设备。里面有一些涉及备份软件的磁带,还有一些用来备份大型机里面的银行数据的九轨磁带(nine-track tape),我们有15个带机械功能的磁带柜,里面存放着DDS与AIT格式的磁带,以及能够处理这些磁带的磁带机。
这样做有许多原因,其中一项就是为了遵循3-2-1原则。还有一项原因则是便于我们对磁带柜所在的这间屋子运用与其他房间不同的安全策略,以限制能够接触到这些磁带的人数。IT部门的所有员工均能访问数据中心,但并非每个人都有权进入这间存放磁带柜的屋子。
这些磁带柜所要守护的服务器跟这个屋子之间隔了几个房间,从距离上看,大概刚超过100ft(30.48m)。当时的那些服务器只支持SCSI-2格式的线材。笔者已经记不清SCSI-2格式的具体规范了,但我知道,这种线材连不到100ft之外的地方。
要想连那么远,必须使用Ultra-wide SCSI线才行,我们当时把这种线叫作又快又长的SCSI线,但服务器与磁带机都不支持这种线材。这两端都只能使用那种又慢又短的SCSI线。那该怎么办呢?有一家叫作Paralan的公司,当时在卖一种能够将SCSI-2与Ultra-wide SCSI桥接起来的东西,于是我就买了两个这样的桥接器,把其中一端的SCSI-2线材通过一个桥接器与Ultra-wide SCSI线材相连,再把这条线通过另一个桥接器与另外一端的SCSI-2线材对接。我记得生产磁带柜的厂家跟我说,这种做法是不受支持的,但我还记得,我当时告诉对方,如果这样做会有通信问题,那我就把磁带柜从那个屋子移到放服务器的这个屋子,看看行不行。其实这样做最后并没有出现问题。
3-2-1原则里面的2,要求我们把备份存放到2个不同的介质中,因此,那种将备份存放到SaaS(Software-as-a-Service,软件即服务)式产品里的设计方案,我觉得并不符合该原则。比方说Microsoft 365的Retention Policy(保留策略)以及Google的Archive机制就属于这样的情况。这些手段只不过是把电子邮件或文件的副本,存放在了与有待保护的数据相同的系统里,而不是存放到不同的介质上。因此,这样做出来的备份不符合3-2-1原则,不是真正的备份。当然,假如以后它们的配置方式发生变化,那另当别论。
此部分意为“让其中一份数据离场”,在那个年代,我们用的就是on-site(在场/在线/上线)与off-side(离场/离线/下线)这样的二分法。现在的情况复杂多了,但总之,意思就是让你把其中一份副本放到距离受保护数据相当远的某个安全地点。要是以前,我会说,你应该把这些备份磁带交给“开着货车的人”(man in a van
),让他带给Iron Mountain(铁山)之类的服务公司去保管。这样可以让备份远离原数据,以便在数据遭遇灾难时,拿这些备份磁带来恢复。这里的关键是想强调:用来做灾难恢复的这份副本,一定要放在远离各种灾难的地方。
遗憾的是,有些公司由于当初没有遵循3-2-1原则中的第三个部分,在9·11事件之后便无法继续运作。它们确实有相当成熟的冗余系统,能够频繁地将主站中的内容同步重制到一个有全套设备的副站上(这种副站也叫作hot site,即热站),然而问题在于,副站就放在双塔之中的另一个“塔”里。虽然当时没人能想到两个“塔”会同时遭到攻击,但总应该有人意识到,副站的位置离它所要保护的主站太近了,尽管这么说很不好,但笔者还是要指出这一点。另外,这一组大楼所在的曼哈顿(Manhattan)是个岛,旁边的哈德逊河(Hudson River)可能会发水灾。就算没有发生双塔倒塌的悲剧,有些情况也可能会让这两个大楼里的设备全都无法运作。因此,你必须考虑到主站可能遭遇哪些类型的灾难,并把用来做灾难恢复的那份副本(尤其是热站)放在不受这些灾难侵扰的地方。
鉴于9·11事件造成的影响,有人想要制定法规,要求金融贸易公司必须将文件同步复制到300mile以外的地方。这虽然听起来很有道理,但由于网速受限,很难做到。最后实际上是分开执行的,也就是一方面确保文件能够同步地得到复制,另一方面,在适当的时候,再将这些同步复制出来的文件转移到远处,而不是立刻将文件同步地复制到远处。这种异步的复制方案虽然不完美,但好处在于,它不会影响有待保护的那个应用程序的性能。
对于云端平台来说,你要注意的并不是让备份远离主站所在的大楼,而是要把这些备份放在一个跟你要保护的应用程序不同的地方。你要确定自己使用的这个云平台所在的实际地理位置,并把备份数据保存到另一个地理位置上的云平台之中。
如果你使用的是IaaS/PaaS式的产品,那你肯定知道自己的应用程序运行在哪个区,而且在默认情况下,你通过自己的账号所创建的备份,也全都以该账号的身份保存在跟应用程序相同的这个区里。这时你必须意识到你的云端账号有可能出现哪些问题,并设法让备份数据不受这些问题干扰。虽说这种产品里面的大多数服务都是高度可用的(highly available,或者说,具备高可用性),能够经受各种常见的故障,但如果有人侵入你的账号,并获得了相关权限,那么他可能会删掉你的整个应用程序,这甚至会把整个组织都搞垮。
2014年,有一家叫作codespaces.com的公司,该公司宣称你可以把代码安全地存放到这里。它对所有的数据都提供三度冗余(triple redundancy),而且做了大量备份。这听上去蛮好,但问题在于,它的备份系统没有遵循3-2-1原则,它的所有备份都是用云平台中的同一个账号制作的,而且都放在了同一个区里。
有人侵入这家公司的网络,拿到了一个权限较高的账号,之所以能拿到这种账号,可能是由于该公司没有对账号启用多重认证机制。入侵者要求公司给钱,否则就删掉账号。公司并没有给钱,而是想通过云平台把这个受到入侵的账号锁住。入侵者意识到了该公司想要做什么,于是就把所有东西都删掉了,包括虚拟机、对象存储系统以及数据库。另外,入侵者还把所有的备份也都删掉了,由于这些备份都是用同一个账号制作的,因此入侵者只要获取了这一个账号,就能将这些备份全都删掉。
这是个相当讽刺的例子,本来想打造一个能够安全存放代码的地方,结果存放在这里的代码却并不安全。你可以去互联网档案馆(例如archive.org里)看看这个网站以前的样子,总之,在2014年之后这家公司就不再运作了。这个例子告诉我们,3-2-1原则确实很重要。
笔者会在8.1.5节再详细说说这一类的事情。
对于云端资源来说,笔者的建议是,你最好能在另一个区里单独创建一个账号,让这个账号专门用来保存备份数据,并把其他区里的那些账号所制作的备份全都汇给这个账号。然后,你需要小心地保管这个账号的登录凭据。具体怎么做呢?笔者在编写本书时还没有见到哪个主流的云平台开始支持多人认证(multiperson authentication)机制,如果以后有这样的功能,那你就应该在这个专用账号上开启该功能。这样的话,如果想删除备份,或是执行一些有可能破坏数据的操作,那么必须有两个人登录该账号才能执行。这就好比导弹发射井的认证措施,两个人需要各自拿着手中的钥匙,同时开锁,而且开锁的地方离得足够远,这意味着必须由两个人来开,而不能由一个人拿着两把钥匙开。电子账号的多人认证在原理上跟这个类似。另外,有些云平台支持不可变的存储机制,本章稍后会谈到这个话题,这种机制也具有保护备份的效果。
对于认证问题,如果没有多人认证机制可以启用,那么最接近该机制的办法是启用多步骤认证(multifactor authentication,也叫多重因素认证),并把其中的每个步骤交给不同的人去做。例如其中一个人拿着电子邮箱地址与密码去登录,另一个人拿着认证设备来确认这次登录。这样的话,除非掌握账号凭据的人同时拿到了认证设备,否则就无法登录云平台;而掌握认证设备的这个人,由于并不知道账号的密码,因此也无法登录账号并重置保护措施,账号的密码只有前一个人知道。这虽然不完美,但在目前的条件下,是最接近多人认证的方案。
这里还是要啰嗦一句:某些SaaS产品(例如Microsoft 365、Google Workspace与Salesforce)会把副本跟原数据放在同一个地方,因此并不符合3-2-1原则的最后一项要求。这就是笔者的观点,笔者依然坚持自己的看法。
我们已经知道什么是备份了,接下来需要看看什么是档案,并了解它与备份之间的区别。两者在许多方面都很相似,但由于目标各异,因此它们是完全不同的两个东西。