首页 > 其他分享 >深入理解 Write-Ahead Logging (WAL) 及其应用

深入理解 Write-Ahead Logging (WAL) 及其应用

时间:2024-09-15 15:52:56浏览次数:10  
标签:WAL Logging log Ahead 写入 file 日志 data

在讨论数据库原理的时候,我们经常会听到一种技术-Write-Ahead Logging (WAL),它保证了数据的持久性和一致性。WAL 的基本思想非常简单,但它的应用范围非常广泛,从数据库到分布式系统,再到各种现代应用的开发中,都能看到它的影子。本文将深入剖析 WAL 的基本机制,并探讨其在不同应用场景中的创新性使用。

图片

什么是 Write-Ahead Logging (WAL)?

Write-Ahead Logging (WAL)是一种日志机制,其核心思想是:在对数据库进行任何持久性更改之前,先将更改记录到一个日志文件中。这种做法的优势在于,即使系统在实际更改数据之前崩溃或发生故障,数据库依然可以通过日志来恢复一致性状态。

WAL的工作原理

WAL的实现通常遵循以下几个步骤:

  1. 记录日志:当事务开始时,对所有要进行的更改操作进行日志记录。

  2. 写入日志:将这些日志顺序地写入一个独立的日志文件中,这样可以保证写入的效率。

  3. 应用变更:在日志写入成功后,将变更应用到数据库的主数据文件中。

  4. 检查点(Checkpoint):周期性地将日志中的信息刷新到数据库文件中,减少日志文件的大小,并缩短恢复时间。

这种设计能有效减少数据丢失的风险,并且显著提高数据库的性能和恢复速度。

WAL的好处是因为,日志文件是顺序写入的,相比于随机写入操作,顺序写入的速度更快。此外日志文件记录格式更简单,从而可靠性更高,通过日志文件可以快速执行重做(REDO)操作,恢复因故障未完成的事务。

尤其是在一些写入密集的场景下,WAL利用预写日志的原理,能够带来很大的优势,例如Kafka通过顺序写入日志分区文件,减少了随机写带来的磁盘寻址开销,从而提高了吞吐量和延迟性能。类似地,LSM 树通过将变更操作先写入WAL,再批量合并到持久存储,实现了高效的写入性能和快速恢复能力。

WAL的优点是写性能提升和可靠性,操作简单,缺点是并不适合大量数据的读取,因此,在数据库中,WAL记录的是操作,只用于顺序读取之后重做,需要从大量数据中读取特定记录,应该采用单独的,更适合的索引存储结构,当然这个主题就是各种数据存储引擎百花齐放的领域。

WAL 在数据库中的典型应用

WAL机制最常见的应用场景就是数据库系统。

RocksDB中,每次写操作(如PutDelete)先写入WAL,再将数据写入MemTable。即使在系统崩溃时,RocksDB也能通过重放WAL恢复到最近一次一致的状态。这种机制使得 WAL 成为确保数据可靠性和一致性的关键。

MySQL中,WAL机制通过InnoDB存储引擎redo log实现,保障了数据库的 ACID特性(原子性、一致性、隔离性、持久性),尤其是在崩溃恢复和数据一致性方面起到关键作用。

数据的修改先写入redo log,随后在后台异步将数据写入实际的数据文件。即使发生崩溃,系统也可以通过 redo log 重做所有已提交但尚未持久化的事务。

MySQL事务的两阶段提交是跟WAL协同工作完成的。当一个事务准备提交时,存储引擎首先将变更写入redo log并标记为“准备状态”;随后更新实际数据页,并将redo log标记为“已提交状态”。这种流程确保了在崩溃时,事务要么完全提交,要么不影响任何数据。

在数据库之外应用WAL的思想

WAL修改数据之前,先写日志的思想,不仅仅在数据库中可以用到,在我们日常的应用开发中,也可以用这样的思想,设计对应的方案,解决数据存储和一致性相关的问题。

1. 前端应用中数据保存和恢复

在复杂的前端表单应用中,用户填写数据的时候,浏览器可能会意外刷新或关闭,导致数据丢失。我们可以将用户每次输入的内容保存到浏览器的本地存储localStorage中。如果页面刷新,可以从日志中恢复数据,确保用户体验的一致性。

2. API 请求的可靠重试机制

在微服务架构中,API请求可能因网络抖动而失败。如果在每次请求发起之前,将请求数据先写入日志文件,就可以在请求失败的时候,根据日志进行重试,保证API调用的幂等性和可靠性。

3. 移动应用的离线数据同步

在网络不稳定或离线场景下,移动应用需要保存用户操作并在网络恢复时进行同步。利用WAL的思路,我们可以将用户的操作先记录到本地日志文件中,并在网络恢复时重放这些日志,以确保数据的一致性和正确性。

4. 文件系统的安全写入

在需要自己管理本地文件,进行读写操作的场景,为了保证文件写入操作的安全性,可以在将变更操作写入到一个临时文件之后,再修改或者替换原文件。这种方法可以有效防止在写入过程中发生崩溃而导致的数据损坏。

以下是一段简单的Python代码,展示如何使用临时文件进行文件更新:

import json
import os
import shutil
import threading

DATA_FILE = "data.json"
LOG_FILE = "data.log"
lock = threading.Lock()  # 创建一个全局锁对象

def write_ahead_log(log_entry):
    """Write an entry to the WAL log file."""
    with open(LOG_FILE, "a") as log_file:
        log_file.write(log_entry + "\n")

def load_data():
    """Load JSON data from the data file."""
    if not os.path.exists(DATA_FILE):
        return {}

    with open(DATA_FILE, "r") as file:
        try:
            data = json.load(file)
        except json.JSONDecodeError:
            data = {}  # Return empty data if file is corrupted
    return data

def write_data(data):
    """Safely write JSON data to the data file with locking mechanism."""
    # Step 1: Write to WAL log file
    write_ahead_log(json.dumps(data))

    # Step 2: Lock and write to the data file
    lock.acquire()  # 获取锁
    try:
        # Write new data to a temporary file first
        temp_file = DATA_FILE + ".tmp"
        with open(temp_file, "w") as temp:
            json.dump(data, temp, indent=4)

        # Replace the original file with the temporary file
        shutil.move(temp_file, DATA_FILE)
    finally:
        lock.release()  # 释放锁

def add_entry(new_entry):
    """Add a new entry to the JSON data file."""
    # Load current data
    data = load_data()

    # Update data with new entry (for example, append to a list)
    if 'entries' not in data:
        data['entries'] = []
    data['entries'].append(new_entry)

    # Write updated data back to the file
    write_data(data)

if __name__ == "__main__":
    # Example usage: Add a new entry to the JSON file
    add_entry({"name": "will", "value": 12})
    print("Data added successfully!")

总结和思考

Write-Ahead Logging (WAL)是一种强大而灵活的技术,其核心思想非常简单:在更改数据之前,先写日志。虽然主要应用在数据库系统中,但 WAL的思想具有普适性。

从数据库事务到前端数据保存,从离线数据同步到分布式系统的可靠操作管理。它不仅能帮助我们构建更加可靠和健壮的系统,还能在面对复杂的技术挑战时,提供一种解决问题的思考方式。

理解WAL的机制,不管对于我们理解数据库的原理,还是平时开发中,设计优雅的解决方案,都是有价值的。

深入理解 Write-Ahead Logging (WAL) 及其应用icon-default.png?t=O83Ahttps://mp.weixin.qq.com/s/7qf3-qLFZjyqDdraMe6qtg

标签:WAL,Logging,log,Ahead,写入,file,日志,data
From: https://blog.csdn.net/liuwill/article/details/142139574

相关文章

  • Java 21的Logging的笔记
    JavaCoreLibrariesJavaLoggingJDK自带的日志记录框架,提供了基本功能,但在项目中没有实际使用过。通常会使用SLF4J和Log4j2或者Logback搭配。以maven管理的项目为例,修改pom.xml,增加如下配置:<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</art......
  • python logging 限制文件大小
    环境window10,pycharm23.0.2logging的配置使用logging模块时,你可以通过logging.handlers.RotatingFileHandler类来限制日志文件的大小。当日志文件达到指定大小时,RotatingFileHandler会自动创建一个新的日志文件,并将后续的日志记录到新的文件中。代码importloggingfro......
  • A Walkthrough Using Acquire and Release Fences
    We’lltaketheexamplefrommypreviouspostandmodifyittouseC++11’sstandaloneacquireandreleasefences.Here’stheSendTestMessagefunction.Theatomicwriteisnowrelaxed,andareleasefencehasbeenplacedimmediatelybeforeit.voidSen......
  • Why system logging "kernel: tcp_parse_options: Illegal window scaling value 15 >
    环境Linux问题在var/log/messages文件中发现以下日志。Oct621:01:05mplttaxsx101kernel:tcp_parse_options:Illegalwindowscalingvalue15>14received.Oct621:01:05mplttaxsx101kernel:tcp_parse_options:Illegalwindowscalingvalue15>14......
  • 分布式链路追踪-SkyWalking
    分布式链路追踪-SkyWalking为什么需要链路追踪在这个微服务系统中,用户通过浏览器的H5页面访问系统,这个用户请求会先抵达微服务网关组件,然后网关再把请求分发给各个微服务。所以你会发现,用户请求从发起到结束要经历很多个微服务的处理,这里面还涉及到消息组件的集成。......
  • logging模块用于记录日志的标准库
    日志级别是监控和调试软件系统的关键组成部分,它们帮助开发者和运维人员区分不同严重程度的信息,从而更有效地响应和解决问题。以下是日志级别的详细说明及如何在Python中使用它们的示例。日志级别分类日志级别按严重程度从低到高排序如下:DEBUG:用于记录详细的调试信息,通常在开......
  • 解决python封装Logging模块后,log位置显示错误的问题
    引入今天由于项目需要,要将logging库二次封装成一个类,以实现一些自定义的功能。我将二次封装了一个logService类,然后在其中同样也实现info,warn,error等日志函数。额外加了一个将日志存入数据库的功能。大概是像下面这样子:但是在封装的过程中,出现了一个问题:log中,不能正确显......
  • 【shell脚本】使用firewall-cmd批量增加IP访问规则
    原创wsdhla想惑1025增加单个IP,并指定端口:firewall-cmd--permanent--zone=public--add-rich-rule="rulefamily="ipv4"sourceaddress="xxx.xx.xx.xxx"portprotocol="tcp"port="54321"accept"批量增加IP访问规则,使用脚本:batch-ad......
  • snmpwalk工具使用
    snmpwalk工具使用简介snmpwalksnmpwalk是SNMP的一个工具,它使用SNMP的GETNEXT请求查询指定OID(SNMP协议中的对象标识)入口的所有OID树信息,并显示给用户。在linux下使用snmpwalk工具,我们必须要安装net-snmp-utils这个软件包。注意:如果linux只安装net-snmp的话,则不包含snmpwalk工具,如下......
  • docker安装skywalking
     创建网络dockernetworkcreate-dbridgeelastic 一、安装oapdockerrun--nameoap-d\-eTZ=Asia/Shanghai\-p12800:12800\-p11800:11800\--netelastic\--linkelasticsearch:elasticsearch\-eSW_STORAGE=elasticsearch7\-eSW_STORAGE_ES_CLUS......