分布式系统原理(6)--日志技术

日志技术是宕机恢复的主要技术之一,最初用在数据库系统中。

(1)数据库系统日志技术简述

l  数据库系统中实现宕机恢复的难点在于数据库操作满足ACID,在支持事务的数据库系统中宕机往往发生在某些事务只执行了部分操作的时候,此时宕机恢复的主要目标是数据库系统恢复到一个稳定可靠状态,消除未完成事务对数据库状态的影响。

l  数据库的日志主要分为Undo Log、Redo Log、Redo/Undo Log和No Redo/NoUndo Log。区别在于更新日志文件和数据文件的时间点要求不同,从而造成性能和效率也不相同。

(2)Redo Log和Check point

a)问题模型

一个高速单机查询系统,数据均在内存中,每次更新一小部分数据,现利用日志技术实现该查询系统的宕机恢复。注:该模型中每次成功的更新操作都会生效,等效于数据库中每个事物只有一个更新操作,且每次更新操作都可以也必须立即提交。

b)Redo Log

l  Redo Log是一种非常简单实用的日志技术,Redo Log更新流程如下:

1. 将更新操作的结果(例如Set K1 = 1,则记录K1 = 1)以追加写(append)的方式写入磁盘的日志文件

2. 按更新操作修改内存中的数据

3. 返回更新成功

注:

   2中未考虑修改内存数据需多线程互斥等问题,但对说明原理无影响。

   Redo Log写入日志的是更新操作完成后的结果(与Undo Log的区别之一)

   是顺序追加写日志文件,在磁盘等对顺序写有利的存储设备上效率较高。

l  Redo Log的宕机恢复

1. 从头读取日志文件中的每次更新操作的结果,用这些结果修改内存中的数据

注:

   只有写入日志文件的更新结果才能在宕机后恢复。若先更新内存再更新日志,可能会导致用户已读取到更新数据,但未来得及更新日志就宕机,此时宕机恢复后,会存在不一致的问题。

l  Redo Log的缺点:宕机恢复时需要回放所有redo日志,效率较低,若需恢复的操作非常多,则该过程将非常漫长。

c)Check point

为解决Redo Log的缺点,引入check point技术。在简化模型下,checkpoint技术的过程即将内存中的数据以某种易于重新加载的数据组织方式完整的dump到磁盘,从而减少宕机恢复时需要回放的日志数据

check point过程

1. 向日志文件中记录“Begin Check Point”

2. 将内存中的数据以某种易于重新加载的数据组织方式dump到磁盘上

3. 向日志文件中记录“End Check Point”

注:在check point流程中,数据可以继续更新,更新的数据可以dump,也可以不dump到磁盘上,具体取决于实现。

基于check point的宕机恢复流程

1. 将dump到磁盘的数据加载到内存

2. 从后向前扫描日志文件,寻找最后一个“End Check Point”日志

3. 从最后一个“End Check Point”日志向前找到最近的一个“BeginCheck Point”日志,并回放该日志之后的所有更新操作日志

注:

l  上述check point的方式依赖redo日志中记录的都是更新后的数据结果这一特征,故即使dump的数据已经包含了某些操作的结果,重放这些操作的日志也不会造成数据错误。同一日志可以重复回放的操作即所谓具有“幂等性”的操作。

l  工程中有些时候Redo日志无法具有幂等性,如加法操作、append等。此时,dump的内存数据一定不能包括“begin check point”日志之后的操作。有两种方法

1.check point过程中停更新服务,不再进行新的操作

2.设计一种支持快照(snapshot)的内存数据结构,可以快速的将内存生产快照,然后写入check point日志,再dump快照数据。

设计支持快照的内存数据结构的方式有很多,如假设内存数据结构维护key-value值,那么可以使用哈希表的数据结构,当做快照时,新建一个哈希表接收新的更新,原哈希表用于dump数据,此时内存中存在两个哈希表,查询数据时查询两个哈希表并合并结果

(3)No Undo/No Redo Log

l  也称“0/1目录”(0/1 directory)。使用场景:若数据维护在磁盘中,某批更新由若干个更新操作组成,这些更新操作需要原子生效,要么同时生效,要么都不生效。

l  0/1目录技术有两个目录结构,称为目录0(Directory 0)和目录1(Directory 1)。另有一个结构称为主记录(Masterrecord)记录当前正在使用的目录称为活动目录。主记录中要么记录使用目录0,要么记录使用目录1。目录0和目录1中记录了各个数据在日志文件中的位置。

l  如图,活动目录为目录1,数据有A/B/C三项,查目录1可得A、B、C三项的值分别为2/5/2

l  0/1目录的数据更新过程始终在非活动目录上进行,只是在数据生效前,将主记录中的0、1值反转,从而切换主记录。

0/1目录示例

l  0/1目录数据更新流程

1. 将活动目录哼拷贝到非活动目录

2. 对于每个更新操作,新建一个日志项记录操作后的值,并在非活动目录中将相应数据的位置修改为新建的日志项的位置

3. 原子性修改主记录,反转主记录中的值,使得非活动目录生效

优点:

l  0/1目录的更新流程非常简单,通过0、1目录的主记录切换使得一批修改的生效是原子的

l  0/1目录将批量事务操作的原子性通过目录手段归结到主记录的原子切换。由于多跳记录的原子修改一般较难实现但单条记录的原子修改往往可以实现,从而降低了问题实现的难度

l  工程中0/1目录的思想运用非常广泛,其形式也不局限于上述流程,可以是内存中的两个数据结构来回切换,也可以是磁盘上的两个文件目录来回生效切换。

(4)工程投影

a)Zookeeper

在zookeeper系统中,为实现高效的数据访问,数据完全保存在内存中,但更新操作的日志不断持久化到磁盘,另一方面,为实现较快速度的宕机恢复,zookeeper周期性的将内存数据以checkpoint的方式dump到磁盘。

b)MySQL的主从库设计

从库只需通过回放主库的日志,就可以实现与主库的同步,由于从库同步的速度与主库更新的速度没有强约束,这种方式只能实现最终一致性

c)Mola*与Armor*

l  支持多种不同的存储引擎,对于接收到的更新操作,两系统将操作日志(redo log)保存到磁盘,引擎可通过回访日志实现副本数据的同步

l  在Mola*中,由于不需要强一致性,日志与数据分离,且日志也保存多个副本,当日志副本更新满足quorum要求后就返回用户更新成功。引擎通过回访日志的方式实现数据更新,由于回放速度不一致,mola提供最终一致性保证。

l  由于返回用户更新成功时只保证日志更新成功,此时读取引擎数据未必可以读到最新更新的数据。Armor*中更新了这一设计,日志与数据不分离,更新日志的同时也更新引擎数据,从而可以立刻读取到成功更新的数据。


猜你喜欢

转载自blog.csdn.net/summer00072/article/details/80744751
今日推荐