什么是WAL?

https://www.cnblogs.com/hzmark/p/wal.html

原来数据库与消息中间件 用的是相同的模式 

都是基于 顺序写的性能优于 离散写 

series 强于scatter

在写完上一篇《Pull or Push》之后,原本计划这一片写《存储层设计》,但是临时改变主意了,想先写一篇介绍一下消息中间件最最基础也是最核心的部分:write-ahead logging(WAL)。

什么是WAL

"In computer science, write-ahead logging (WAL) is a family of techniques for providing atomicity and durability (two of the ACID properties) in database systems."——维基百科

在计算机领域,WAL(Write-ahead logging,预写式日志)是数据库系统提供原子性和持久化的一系列技术。

在使用WAL的系统中,所有的修改都先被写入到日志中,然后再被应用到系统状态中。通常包含redo和undo两部分信息。

为什么需要使用WAL,然后包含redo和undo信息呢?举个例子,如果一个系统直接将变更应用到系统状态中,那么在机器掉电重启之后系统需要知道操作是成功了,还是只有部分成功或者是失败了(为了恢复状态)。如果使用了WAL,那么在重启之后系统可以通过比较日志和系统状态来决定是继续完成操作还是撤销操作。

redo log

redo log称为重做日志,每当有操作时,在数据变更之前将操作写入redo log,这样当发生掉电之类的情况时系统可以在重启后继续操作。

undo log

undo log称为撤销日志,当一些变更执行到一半无法完成时,可以根据撤销日志恢复到变更之间的状态。

MySQL中用redo log来在系统Crash重启之类的情况时修复数据(事务的持久性),而undo log来保证事务的原子性。

WAL在消息中间件中的应用

WAL可以说是消息中间件的基础,也是所有存储类系统的基础。

在消息中间件中,WAL没有MySQL中那么复杂,我们只需要记redo log。消息直接存储在redo log中,只要写redo log完成了,那么消息就写入完成了:

  1. 消息写入redo log就表明持久化了

  2. 且不会出现原子性的问题,消息写入即成功,没写入即失败

存储结构

使用WAL存储数据,就需要去组织存储文件,比如MySQL的binlog文件。在消息中间件中也需要类似的形式去组织redo log,即消息的存储文件。

我们采用固定大小的存储文件,这样在索引消息的时候,只要知道偏移量,就能找到对应的存储文件。比如下面是文件大小为1024的存储文件示例:

消息被不断的追加到最新的存储文件中。

消息在文件中的存储格式大致如上:

  • 采用二进制的格式存储消息

  • 消息是不定长的

所以这里会需要一个结构来索引消息。索引到一条完整的消息只需要两个元素:偏移量、大小。只要有这两个元素就可以从存储日志中读取一段完整的数据(一条完整的消息)。

以上的结构是最简单的消息中间件存储的模型,虽然离真正应用到实践中还有一些距离,但是核心思想是一致的。

考虑这几个问题:

  1. 消息具体的存储协议,即存储文件中消息需要包含哪些内容

  2. 如何优化索引结构,支持消息回溯、消息过滤等功能

确定一下这几个问题的解决方案基本就是一个可以使用的消息中间件的WAL了。

Crash Recovery

上文说了redo log用于在系统Crash之后做恢复(在中间件中也直接作为数据存储),那么redo log具体我们可以如何使用它进行系统状态的恢复呢?

在消息写入的过程中,这里的状态只有一个,就是消息索引。只要消息索引构建了,那么消息就可以被消息;如果消息索引没构建,那么这条消息就是不可消费的(等价于消息没有写入)。

那么这里的恢复就是在系统Crash之后如何构建索引。

比如上图的状态是已经构建了消息0-3的索引,需要构建消息4-7的索引信息。

这个实现很简单:

  • 消息一旦构建了索引,就记录checkpoint;checkpoint可以定期刷盘

  • 系统恢复过程中读取checkpoint之后的消息构建索引;如果读取的消息不完整,则丢弃消息(可以采用CRC验证之类的方式来校验消息是否完成)

因为消息没有完整写入redo log的情况(写入时系统Crash了)系统并不会响应Producer消息发送成功(只有成功刷盘了才会响应成功),所以直接丢弃不完整的消息并不会对系统语义产生影响(不完整的消息没有响应Producer,也没有构建索引)。

结语

上文介绍了一下WAL,简要的描述了消息中间件存储模型和Crash Recovery,还有一些遗留的问题:

  1. 如何实现消息回溯和过滤,如何支持多tag过滤?

  2. 消息需要写文件且刷盘,如何保证写入性能?

  3. 消费时需要从文件读取消息,如何保证性能?

  4. 序列化的消息需要包含哪些属性才能完整的恢复出索引?

往期文章:

Push or Pull?

消息中间件核心实体(1)

消息中间件核心实体(0)

消息的写入和读取流程

NameServer模块划分

Client模块划分

Broker模块划分

消息中间件架构讨论

业务方对消息中间件的需求

消息中间件中的一些概念

什么是分布式消息中间件?

[转帖]什么是WAL?的更多相关文章

  1. [转帖]PostgreSQL与MySQL比较 From 2010年

    PostgreSQL与MySQL比较 [复制链接]  http://bbs.chinaunix.net/thread-1688208-1-1.html osdba 稍有积蓄 好友 博客 消息 论坛徽章 ...

  2. nginx负载均衡基于ip_hash的session粘帖

    nginx负载均衡基于ip_hash的session粘帖 nginx可以根据客户端IP进行负载均衡,在upstream里设置ip_hash,就可以针对同一个C类地址段中的客户端选择同一个后端服务器,除 ...

  3. HBase的Write Ahead Log (WAL) —— 整体架构、线程模型

    解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发.持久化的日志保存与回放机制.每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中. 如果出 ...

  4. HBase的Write Ahead Log (WAL) —— API与基本概念

    HBase的数据写入操作,会先记录到HLog中,再真正写入到MemStore中.前者是对写入友好的格式,后者是对查询友好的格式.所以前者吞吐量更高,写入成功率大,提高了系统的可靠性,“基本”可以实现宕 ...

  5. [转帖]网络协议封封封之Panabit配置文档

    原帖地址:http://myhat.blog.51cto.com/391263/322378

  6. [转帖]零投入用panabit享受万元流控设备——搭建篇

    原帖地址:http://net.it168.com/a2009/0505/274/000000274918.shtml 你想合理高效的管理内网流量吗?你想针对各个非法网络应用与服务进行合理限制吗?你是 ...

  7. 3d数学总结帖

    3d数学总结帖,以下是对3d学习过程中数学知识的简单总结 角度值和弧度制的互转 Deg2Rad 角度A1转弧度A2 => A2=A1*PI/180 Rad2Deg 弧度A2转换角度A1 => ...

  8. [转帖]The Lambda Calculus for Absolute Dummies (like myself)

    Monday, May 7, 2012 The Lambda Calculus for Absolute Dummies (like myself)   If there is one highly ...

  9. [转帖]FPGA开发工具汇总

    原帖:http://blog.chinaaet.com/yocan/p/5100017074 ----------------------------------------------------- ...

随机推荐

  1. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  2. sync、fsync和fdatasync

    转自 http://blog.csdn.net/todd911/article/details/11701847 传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘 I/O都通过缓 ...

  3. nodejs基础(回调函数、模块、事件、文件读写、目录的创建与删除)

    node官网:http://nodejs.cn/ 今天想看看node的视频,对node进一步了解, 1.我们可以从官网下载node到自己的电脑上,今天了解到node的真正概念,node时javascr ...

  4. python 多线程_thread

    import _thread import time def print_time(threadName, delay, iterations): start = int(time.time()) , ...

  5. java生成zip包兼容Linux

    /* 这个方法只用在windows中用服务器为Linux就不行 */ package common.util; import java.io.File;import java.io.FileInput ...

  6. Flutter安装

    下载右边的安装包以获取最新版本 stable 的 Flutter SDK 将压缩包解压,然后把其中的 flutter 目录整个放在你预想的 Flutter SDK 安装目录中(比如 C:\src\fl ...

  7. DLL:操作数据库和表

    1. 操作数据库 C(Create 创建) R(Retrieve 查询) U(Update 更新) D(Delete 删除) (1) 查询数据库 1) 查询所有数据库名称 SHOW DATABASES ...

  8. NMS(非极大值抑制)实现

    1.IOU计算 设两个边界框分别为A,B.A的坐标为Ax1,Ax2,Ay1,Ay2,且Ax1 < Ax2,Ay1 < Ay2.B和A类似. 则IOU为A∩B除以A∪B. 当两个边界框有重叠 ...

  9. php mvc 模式的开发注意事项

    1.控制器中: 如果不涉及到数据库的就在控制器中. empty($res['code']) ? $this->error($res['msg']) : $this->success($re ...

  10. 错误Uncaught Error: Bootstrap's JavaScript requires jQuery at bootstrap.min.js:6 错误详解

    引入Bootstrap的顺序进行修改 <% //获取以/开始,不以/结尾的部分 pageContext.setAttribute("APP_PATH", request.ge ...