2.1 日志技术

2021/06/20 分布式 共 3982 字,约 12 分钟

在今天的互联网技术中心,日志技术用于方方面面。比如数据库、消息队列、分布式系统等等。只要涉及持久化、多副本就离不开日志技术。更好的理解日志技术,有助于我们更好的理解持久化和分布式系统;

1、关于Log

日志是totally-ordered,append-only的数据结构,我们经常用到,但可能我们还并没有意识到,因为他太简单了。关于Log,最容易想到的就是log4j、syslog这类文本日志,主要是为了方便人去阅读的调试信息。我们称之为应用日志。应用日志实际上是Log的一种退化,也不是本文今天讨论的重点。

日志技术是主要的宕机恢复技术之一,日志技术最早使用与数据库系统中,我们先从Mysql中的日志说起:

  • general log:记录所有的操作日志,会耗费数据库5-10%的性能,一般不打开。常用语sql审计和排错;
  • Redo log:重做日志,用于InnoDB实现持久性,Redo log、Check point可实现宕机恢复;
  • Undo log:回滚日志,用于实现InnoDB的原子性;
  • Binglog:Mysql的逻辑日志,用户Mysql的主从复制;

从分类上来看,general log更偏向应用日志,Redo log、Undo log、Binlog属于数据日志,称为data log或者journal log。

而数据日志又可分为逻辑日志和物理日志:

  • 逻辑日志physical logging):记录每一行的改变的内容,描述具体某一个Page的修改操作;Mysql InnoDB的redo log、undo log属于物理日志(准确来说应该属于physiological logging:物理日志和逻辑日志的混合);
  • 逻辑日志logical logging):记录的不是改变的行,而是引起行改变的SQL语句,相比于逻辑日志,又被成为high-level logging,不关心具体作用于哪一个page,得益于更高层次的抽象,一条逻辑日志,可以对应多条物理日志。Mysql binlog属于逻辑日志;

除物理日志和逻辑日志以外,还有一种日志被称为physiological logging,试图同时获得物理日志和逻辑日志的优势。

1.1、日志的抽象

日志是一种简单的的存储抽象,只能追加(append only)、不可变、按照时间完全有序(total-orcered)的记录序列:

log

在日志的末尾添加记录,读取日志记录则从左到右。每一条记录都制定一个唯一的顺序日志记录编号。

日志的次序(ordering)定义时间』概念,因为位于左边的日志记录表示比右边的早。日志记录编号可以看作是这条日志记录的『时间戳』。把次序直接看成是时间的概念,刚开始觉得有点怪异,但是这样的做法有个便利的性质:解耦了时间和任意特定的物理时钟(physical clock)。引入分布式系统后,这回成为一个必不可少的性质。

1.2、日志技术:数据持久性保证

要保证数据的持久性,我们需要将数据落盘持久化。现在数据库基本都是使用WAL(Write Ahead Logging)预写日志来实现的。

在单机系统中,宕机恢复主要依赖WAL+Checkpoint技术,但是在分布式系统中,要保证数据的持久性,需要引入多副本技术,要实现多副本,就离不开日志复制技术(Log Replication)。

2、WAL(Write-Ahead Logging)

WAL是一种实现事务日志的标准方法。WAL的标准思想是先写日志,再写数据,数据文件的修改必须发生在这些修改已经记录日志文件之后。

如果每次发生数据变化,就将变更的数据页刷到磁盘,那么这个开销是非常大的。如果数据集中到几个热点数据页,那么性能会非常差。同时如果在从缓冲池将页数据刷到磁盘前发生了宕机,那么数据库就不能恢复了,为了避免发生数据丢失问题,当前事务数据系统普遍采用了Write Ahead Log策略,即当事务提交时,先写重做日志,再修改页。当由于宕机而导致数据丢失时,通过重做日志来完成数据恢复。这也是事务ACID中的D(Durability)的要求。

WAL机制可以从两个方面提高性能:

  • 多个client写日志文件可以通过一次fsync来完成
  • 日志文件是顺序写的,同步日志的开销远比同步数据页的开销要小

image-20210702221502271

采用单个日志,可能变得很难管理:

  1. 清理老日志困难
  2. 重启时读取文件过大

为了解决这个问题,通常采用分段日志(Segmented Log)或者最低水位线(Low-Water Mark)来减少程序启动时读取文件大小以及清理老日志。

2.1、Segmented Log

单一的日志文件可能会增长到很大,并且程序启动时读取从而成为性能瓶颈。老的日志需要清理,对于一个大的文件清理操作很费劲。将一个日志切分为多个,日志在达到一定大小时,会切换到新文件继续写。

2.2、Low-Water Mark

WAL预写日志维护了对存储的每次更新,随着时间的不断增长,这个日志文件会变得无限大。Segmented Log分割日志可以让我们每次只处理一个小文件,但是如果不清理,会无休止增长以至于硬盘被沾满。

最低水位线标记哪一步日志可以被删除了,即在最低水位线之前的所有日志都可以清理掉。一般的实现方式是程序内有一个定时运行的线程,来清理水位线以下的日志文件。

2.3、Checkpoint技术

如果WAL日志可以无限增大,同时缓冲池也足够大,能够缓冲所有的变更数据,那么就不需要讲缓冲池的数据刷到磁盘。因为发生宕机的时候,完全可以通过WAL日志来恢复整个数据系统。但是这需要满足两个前提条件:

  • 缓冲池足够大
  • WAL日志足够大

当然,还需要考虑另外一个问题,宕机恢复时间问题。因此Checkpoint技术的目的是解决以下几个问题:

  • 缩短数据库的恢复时间
  • 缓冲池不够用的时候,触发fsync
  • WAL日志不够用,触发fsync

LSN(Log Sequence Number)

LSN通常用来标记版本,单调递增且唯一,通常WAL也LSN,Checkpoint也有LSN。

2.4、幂等

WAL是顺序Append的,当网络或者其他问题触发重试时,WAL实现幂等的代价是很大的,可能会生成重复的日志,需要WAL刷盘的时候通来保证幂等;

2.5、工程投影:Twitter DistributedLog

bdfa5faca04009f15042750efde4c073

每条日志记录都是一个字节序列。日志记录会按照序列写入到日志流中,并且会分配一个名为 DLSN(分布式序列号,DistributedLog Sequence Number)的唯一序列号。除了 DLSN 以外,应用程序还可以在构建日志记录的时候设置自己的序列号,应用程序所定义的序列号称为 TransactionID(txid)。

[注]InnoDB的Redo Log的RingBuffer结构

3、Log Replication

WAL+checkpoint在单机系统下可以很好的应对故障恢复。但是在分布式系统中,我们需要通过多副本技术来应对单节点故障,多副本最常用的技术就是日志复制技术。

日志解决了两个问题:更改动作的排序和数据的分发,这两个问题在分布式系统中尤为重要。协商达成一致的更改动作顺序是分布式系统设计的核心问题一致。

分布式系统以日志为中的方案来自于一个简单的观察,我们称之为状态复制机原理(State Machine Replication Principle)

3.1、Log Replication State Machine

raft-图1

复制状态机的结构。一致性算法管理着来自客户端指令的复制日志。状态机从日志中处理相同顺序的相同指令,所以产生的结果也是相同的。

3.2:工程投影:Mysql的主从复制技术

待补充

4、日志与表的二象性

二象性(duality)是个冷门词汇。我唯一在『光的波粒二象性(wave-particle duality』一词中有接触,是指光(电磁波)有时会显示出波动性(这时粒子性较不显著),有时又会显示出粒子性(这时波动性较不显著),在不同条件下分别表现出波动或粒子的性质。 波动性/粒子性是人们对光的认识、理解或描述方式。类似的,数据表现出了表与事件的二象性,表与事件是数据在不同条件/场景下数据的性质,是对人们对数据的认识、理解或描述方式。

如果上面描述你觉得『二象』一词还是很难理解,你可以理解成『对偶』、『互通』、『对称』或『可逆』,即数据表 和 数据事件之间可以互相转化。

数据库、缓存、消息队列:

相同:存储一段时间的数据

不同:访问模式不同,有不同的性能特征和实现手段;

消息队列:日志数据流

4.1、工程投影:Pulsar 消息和流一体的消息队列

bk1

参考文档

http://mysql.taobao.org/monthly/2017/03/02/

https://github.com/oldratlee/translations/blob/master/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part1-what-is-a-log.md

https://spongecaptain.cool/post/database/logicalandphicallog/

https://zhuanlan.zhihu.com/p/350131538

https://martinfowler.com/articles/patterns-of-distributed-systems/log-segmentation.html

https://bravenewgeek.com/building-a-distributed-log-from-scratch-part-1-storage-mechanics/

https://www.infoq.cn/article/2016/05/twitter-github-distributedlog

Table of Contents