赵二狗刚刚毕业,应聘进入了锤钮匹科技有限公司,成为了这里的新员工。入司的第一天是分配宿舍(背景音:天哪,还有宿舍!羡慕嫉妒恨!)。跟他在同一个宿舍的是公司的老员工王大拿,王大拿是该公司的架构师,对公司的情况基本上无所不知。请注意,这里说的是公司的八卦新闻,哈哈!
赵二狗进了宿舍,王大拿正在那里噼里啪啦的敲键盘... ...
赵二狗: 前辈,我是新报道的同事。
没有任何反应。
“前辈”,赵二狗提高了嗓门。
还是没有任何反应。
“前辈!”,赵二狗大喝一声。
王大拿忽的从椅子上站了起来,“干毛,吓死老子了”,王大拿略带怒气的说。
“前辈,我是新入职的同事,跟您一个宿舍,认识您很高兴!”,赵二狗面带笑容的说。
一听这样,王大拿笑了,“好说,好说,你随便坐吧,我这忙着调程序呢”。
“周末还不休息!?”赵二狗小声嘀咕着。
王大拿很愤愤,“是啊,娘的,遇到个Bug,阻塞好几天了。”
“什么问题?”赵二狗问。
“说了你也不懂,小鲜肉”,王大拿不屑的说。
王大拿继续说, “你知道什么是快照吗?”
“切,不就是快照,那有什么不懂的,我也是堂堂985的硕士研究生,之前专门搞存储的”,赵二狗很不爽。
“好小子,那你讲讲”,王大拿突然提起了兴趣。
于是赵二狗同学开始娓娓道来... ...
什么是快照
快照是存储系统中的一种数据保护技术,主要是实现数据的逻辑保护。所谓逻辑保护,就是当数据出现误删除或者病毒等原因导致数据破坏的情况。通过快照技术,可以将数据恢复到某一个时间点的数据。
“不错,接着说”,王大拿觉得赵同学还有两下子。
从名字上可以猜出来,快照就好像给数据拍了一个照片,就好像我们日常生活中给人拍照片类似。以生活中拍照片为例,比如给你家娃娃拍了他2岁的照片,等他到5岁的时候,样子变化很大。这个时候你想看看他2岁的时候长什么样,那你就可以拿出他2岁的照片看看。
对于存储中的快照技术也是类似,在某个时间点,你给某个磁盘(或者存储中的LUN)打一个快照,相当于让存储系统给这个磁盘拍了一个照片。当之后的使用过程中发生了意外,比如病毒把数据搞坏了等等。这个时候你就可以通过快照知道原来的数据是什么样的,这样数据就可以找回来了。
快照的实现原理
”不错,不错,那快照的实现原理是什么呢?“,王大拿觉得有点小看小赵同学了,于是接着问。
快照可以在文件系统或者块设备层面实现,我们以块存储为例。块存储从普通用户的角度来看就是磁盘。从用户的角度磁盘其实就是一个线性空间,可以理解为一个很大的数组,比如512G或者4TB等。但磁盘的读写最小单位是一个扇区,也就是512字节。这样可以不用关心,这个跟我们后面讲的快照的原理也没有太大关系。
有了磁盘的这个概念,那么快照就比计较容易理解了。对于存储系统而言,磁盘实际上是从存储池划分的一块空间而已(这一点与我们普通PC的事物磁盘有所不同),如图2所示,假设原始磁盘在存储池中有如图的一块空间,而磁盘在存储系统中其实就是一个数据结构而已,只不过这个数据结构描述了磁盘在存储池中的空间范围。
磁盘是一个数据结构,快照实际上也是一个数据结构。对磁盘做快照,其实就是在存储系统中创建一个数据结构,让其描述的数据范围指向原始磁盘指向的存储池的范围即可。这样快照的数据就和磁盘的数据一模一样,具体可以参考图2 A进行理解。
但是原始磁盘的数据是会变化的,也就是会被重新写新数据的。这个时候怎么保证快照的数据还是打快照那个时间点的数据呢?问题的关键就在磁盘对数据的描述和管理。在存储系统中,将磁盘划分为固定大小的块(比如4KB),然后通过某种机制(比如位图)对这些磁盘块进行管理和标记。当有应用对磁盘写新的数据的时候,磁盘管理软件就会将原始数据拷贝到新的地方,然后让快照的指向改为这个新地址,而磁盘原来的地方就可以将数据写入。这样对于磁盘而言,数据发生了变化;而对于快照而言,快照的数据还是打快照那个时间点的数据。
“嗯,懂得很多嘛,小赵”,王大拿似乎很满意赵二狗同学的答案。“问题是这种方式需要在底层复制数据,会影响原始磁盘的性能”。
快照的2种实现
是的,目前快照有2中实现方式,一种是我上面介绍的方式,称为COW,全称为Copy-On-Write。也就是在原始磁盘写数据的时候会将原始数据拷贝到新的地方。当然,并不是每次写数据都会拷贝,而是第一次写数据的时候才会拷贝。这里有一个位图记录着已经拷贝过的数据,如果已经拷贝过,则下次再写数据的时候将不会再拷贝了。
另外一种实现方式成为ROW,全称为Redirect-On-Write,也就是写时重定向。这种实现方式的基本原理是当原始磁盘写数据的时候并不在原始位置写入数据,而是分配一个新的位置。这种情况下就需要维护磁盘逻辑地址与实际数据位置的对应关系。如图3是ROW的原理示意图。
快照的用途与局限
“你刚才说的快照可以防止数据被病毒破坏,还有其它应用场景吗?”,王大拿问。
“很多啊”, 赵二狗接着说。
“比如在数据库应用领域,使用关系型数据库的业务通常是关键业务。因此,需要保证数据库在出现数据损坏或者丢失的情况下能够恢复到某个时间点。这样,通过快照,比如每个小时打一个快照,这样即使出现问题,最多丢失1个小时的数据,从而保证数据的安全。”
“数据库为了提升性能可能会同时使用好几个磁盘,比如Oracle数据库会用不同的磁盘存放不同的数据。比如数据文件会单独放在一个磁盘,Redo日志又会放在另外一个磁盘。并且,Oracle数据库会校验两者的一致性,任何差异可能会导致整个数据库的不一致,这个怎么解决?”,王大拿问。
赵二狗回答:“这种情况下就需要一种称为“一致性组”的技术了,“一致性组”相当于将磁盘打包成为一组磁盘,做快照的时候可以保证这一组磁盘的数据是在同一个时间点的。”
王大拿若有所思:“嗯嗯,但是还有一点,如果我们做了快照,在恢复的时候数据库是否可以直接恢复?”
赵二狗:“应该可以的啊,因为数据我们都保护了,数据恢复到该时间点后,数据库可以直接启动。”
“不一定”,王大拿继续说“我们举个例子,数据库通常是要保证事务性的,为了保证数据的事务性,数据库对于一个写数据通常不是简单的写,而是要写一大堆各种日志,因此对于一个写数据操作,到我们存储系统就会变成很多个IO。”
“在我们存储层面我们是不知道那些IO是某一个事务的,而我们做快照是以IO为粒度进行的。换而言之,也就是我们做了一个快照,可能对于数据库而言正在处于中间过程。这样的话,当我们恢复到这个时间点的时候,数据库并不能直接启动,而是处于一种数据不一致的状态,需要手动做恢复处理。”
赵二狗露出了惊讶的表情: “大拿就是大拿, 那怎么办?”
“凉拌,这个没招啊,臣妾做不到”,王大拿说。
“应用层面上的问题只能在应用层面上解决了,存储系统本身处于下层,无法感知应用的差异。Oracle层面本身也有数据保护的机制,比如数据备份,或者RAC等。好了,时间不早了,吃饭去吧。”
“好的,大拿,今天我请客,学到不少新东西。”