十年技术大牛总结:分布式架构之日志技术( 二 )


  1. 将dump到磁盘的数据加载到内存
  2. 从后向前扫描日志文件,寻找最后一个“end check point”日志
  3. 从最后一个“end check point”日志向前找到最近的一个“begin check point”日志,并回放该日志之后的所有更新操作日志
上述的check point的方式依赖redo日志中记录的都是更新后的数据结果这一特征,即使dump的数据已经包含了某些操作的结果,重新回放这些操作的日志也不会造成数据错误 。同一条日志可以重复回放的操作即所谓具有” 幂等性 ”的操作 。工程中,有些时候Redo日志无法具有幂等性,例如 加法操作、append操作 等 。此时,dump的内存数据一定不能包括“begin check point”日志之后的操作 。为此,有两种方法,其一是checkpoint的过程中停更新服务,不能进行新的操作,另一种方法是,设计一种支持快照(snapshot)的内存数据结构,可以快速的将内存生成快照,然后写入check point日志再dump快照数据 。至于如何设计支持快照的内存数据结构,方式也很多,例如假设内存数据结构维护key-value值,那么可以使用哈希表数据结构,当做快照时,新建一个哈希表接收新的更新,原哈希表用于dump数据,此时内存存在两个哈希表,查询数据时查询两个哈希表并合并结果。
No Undo/ No Redo Log
介绍另一种特殊的日志技术“No Undo/ No Redo Log”,这种技术也称之为“0/1目录”(0/1 directory) 假设另一种问题场景:若数据维护在磁盘中,某批更新由若干个更新操作组成,这些更新操作需要 原子生效,即要么同时生效,要么都不生效 。
 
十年技术大牛总结:分布式架构之日志技术

文章插图
 
 
0/1目录技术中有两个目录结构,称为目录0和目录1 。另有一个结构称为主记录(master record)记录当前正在使用的目录称为活动目录 。主记录中要么记录使用目录0,要么记录使用目录1 。目录0或者目录1记录了各个数据在日志文件中的位置 。
图中给出了一个0/1目录的例子 。活动目录为目录1,数据有A、B、C三项 。查目录1可得A、B、C三项的值分别为2、5、2 。0/1目录的数据更新过程始终在非活动目录上进行,只是在数据生效前 。将主记录中的0、1值反转,从而切换主记录 。
0/1目录数据更新流程
  1. 将活动目录完整拷贝到非活动目录
  2. 对于每个更新操纵,新建一个日志项记录操作后的值,并在非活动目录中将相应数据的位置修改为新建的日志项的位置
  3. 原子性修改主记录: 反转主记录中的值,使得非活动目录生效
0/1目录的更新流程很简单,通过0、1目录的主记录切换使得一批修改的生效是原子的 。
0/1目录将批量事务操作的原子性通过目录手段归结到主记录的原子切换 。由于多条记录的原子修改一般较难实现而单条记录的原子修改往往可以实现,从而降低了问题实现的难度 。在工程中0/1目录思想运用非常广泛,其形式也不局限在上面的流程中,可以是内存中两个数据结构的来回切换,也可以是磁盘上的两个文件目录的来回生效切换。
工程投影
日志技术的使用非常广泛,在zookeeper系统中,为了实现高效的塑胶访问,数据完全保存在内存中,但更新操作的日志不断持久化到磁盘,另一方面,为了实现较快速的宕机恢复,zookeeper周期性的将内存数据以checkpoint的方式dump到磁盘 。
MySQL的主从库设计也是基于日志 。从库只需通过回放主库的日志,就可以实现与主库的同步 。由于从库同步的速度与主库更新的速度没有强约束,这种方式只能实现 最终一致性。




推荐阅读