深入理解 Write-Ahead Logging (WAL) 及其應(yīng)用

在討論數(shù)據(jù)庫(kù)原理的時(shí)候让蕾,我們經(jīng)常會(huì)聽(tīng)到一種技術(shù)-Write-Ahead Logging (WAL)醉锅,它保證了數(shù)據(jù)的持久性和一致性勤庐。WAL 的基本思想非常簡(jiǎn)單二鳄,但它的應(yīng)用范圍非常廣泛曙搬,從數(shù)據(jù)庫(kù)到分布式系統(tǒng)摔吏,再到各種現(xiàn)代應(yīng)用的開(kāi)發(fā)中,都能看到它的影子纵装。本文將深入剖析 WAL 的基本機(jī)制舔腾,并探討其在不同應(yīng)用場(chǎng)景中的創(chuàng)新性使用。

什么是 Write-Ahead Logging (WAL)?

Write-Ahead Logging (WAL)是一種日志機(jī)制搂擦,其核心思想是:在對(duì)數(shù)據(jù)庫(kù)進(jìn)行任何持久性更改之前稳诚,先將更改記錄到一個(gè)日志文件中。這種做法的優(yōu)勢(shì)在于瀑踢,即使系統(tǒng)在實(shí)際更改數(shù)據(jù)之前崩潰或發(fā)生故障扳还,數(shù)據(jù)庫(kù)依然可以通過(guò)日志來(lái)恢復(fù)一致性狀態(tài)。

WAL的工作原理

WAL的實(shí)現(xiàn)通常遵循以下幾個(gè)步驟:

  1. 記錄日志:當(dāng)事務(wù)開(kāi)始時(shí)橱夭,對(duì)所有要進(jìn)行的更改操作進(jìn)行日志記錄氨距。

  2. 寫(xiě)入日志:將這些日志順序地寫(xiě)入一個(gè)獨(dú)立的日志文件中,這樣可以保證寫(xiě)入的效率棘劣。

  3. 應(yīng)用變更:在日志寫(xiě)入成功后俏让,將變更應(yīng)用到數(shù)據(jù)庫(kù)的主數(shù)據(jù)文件中。

  4. 檢查點(diǎn)(Checkpoint):周期性地將日志中的信息刷新到數(shù)據(jù)庫(kù)文件中茬暇,減少日志文件的大小首昔,并縮短恢復(fù)時(shí)間。

這種設(shè)計(jì)能有效減少數(shù)據(jù)丟失的風(fēng)險(xiǎn)糙俗,并且顯著提高數(shù)據(jù)庫(kù)的性能和恢復(fù)速度勒奇。

WAL的好處是因?yàn)椋罩疚募琼樞驅(qū)懭氲那缮В啾扔陔S機(jī)寫(xiě)入操作赊颠,順序?qū)懭氲乃俣雀旄穸4送馊罩疚募涗浉袷礁?jiǎn)單,從而可靠性更高竣蹦,通過(guò)日志文件可以快速執(zhí)行重做(REDO)操作顶猜,恢復(fù)因故障未完成的事務(wù)。

尤其是在一些寫(xiě)入密集的場(chǎng)景下痘括,WAL利用預(yù)寫(xiě)日志的原理驶兜,能夠帶來(lái)很大的優(yōu)勢(shì),例如Kafka通過(guò)順序?qū)懭肴罩痉謪^(qū)文件远寸,減少了隨機(jī)寫(xiě)帶來(lái)的磁盤尋址開(kāi)銷抄淑,從而提高了吞吐量和延遲性能。類似地驰后,LSM 樹(shù)通過(guò)將變更操作先寫(xiě)入WAL肆资,再批量合并到持久存儲(chǔ),實(shí)現(xiàn)了高效的寫(xiě)入性能和快速恢復(fù)能力灶芝。

WAL的優(yōu)點(diǎn)是寫(xiě)性能提升和可靠性郑原,操作簡(jiǎn)單,缺點(diǎn)是并不適合大量數(shù)據(jù)的讀取夜涕,因此辐真,在數(shù)據(jù)庫(kù)中徐裸,WAL記錄的是操作愉适,只用于順序讀取之后重做浸遗,需要從大量數(shù)據(jù)中讀取特定記錄,應(yīng)該采用單獨(dú)的驾胆,更適合的索引存儲(chǔ)結(jié)構(gòu)涣澡,當(dāng)然這個(gè)主題就是各種數(shù)據(jù)存儲(chǔ)引擎百花齊放的領(lǐng)域。

WAL 在數(shù)據(jù)庫(kù)中的典型應(yīng)用

WAL機(jī)制最常見(jiàn)的應(yīng)用場(chǎng)景就是數(shù)據(jù)庫(kù)系統(tǒng)丧诺。

RocksDB中入桂,每次寫(xiě)操作(如PutDelete)先寫(xiě)入WAL,再將數(shù)據(jù)寫(xiě)入MemTable驳阎。即使在系統(tǒng)崩潰時(shí)抗愁,RocksDB也能通過(guò)重放WAL恢復(fù)到最近一次一致的狀態(tài)。這種機(jī)制使得 WAL 成為確保數(shù)據(jù)可靠性和一致性的關(guān)鍵呵晚。

MySQL中蜘腌,WAL機(jī)制通過(guò)InnoDB存儲(chǔ)引擎redo log實(shí)現(xiàn),保障了數(shù)據(jù)庫(kù)的 ACID特性(原子性劣纲、一致性逢捺、隔離性谁鳍、持久性)癞季,尤其是在崩潰恢復(fù)和數(shù)據(jù)一致性方面起到關(guān)鍵作用劫瞳。

數(shù)據(jù)的修改先寫(xiě)入redo log,隨后在后臺(tái)異步將數(shù)據(jù)寫(xiě)入實(shí)際的數(shù)據(jù)文件绷柒。即使發(fā)生崩潰志于,系統(tǒng)也可以通過(guò) redo log 重做所有已提交但尚未持久化的事務(wù)。

MySQL事務(wù)的兩階段提交是跟WAL協(xié)同工作完成的废睦。當(dāng)一個(gè)事務(wù)準(zhǔn)備提交時(shí)伺绽,存儲(chǔ)引擎首先將變更寫(xiě)入redo log并標(biāo)記為“準(zhǔn)備狀態(tài)”;隨后更新實(shí)際數(shù)據(jù)頁(yè)嗜湃,并將redo log標(biāo)記為“已提交狀態(tài)”奈应。這種流程確保了在崩潰時(shí),事務(wù)要么完全提交购披,要么不影響任何數(shù)據(jù)杖挣。

在數(shù)據(jù)庫(kù)之外應(yīng)用WAL的思想

WAL修改數(shù)據(jù)之前,先寫(xiě)日志的思想刚陡,不僅僅在數(shù)據(jù)庫(kù)中可以用到惩妇,在我們?nèi)粘5膽?yīng)用開(kāi)發(fā)中,也可以用這樣的思想筐乳,設(shè)計(jì)對(duì)應(yīng)的方案歌殃,解決數(shù)據(jù)存儲(chǔ)和一致性相關(guān)的問(wèn)題。

1. 前端應(yīng)用中數(shù)據(jù)保存和恢復(fù)在復(fù)雜的前端表單應(yīng)用中蝙云,用戶填寫(xiě)數(shù)據(jù)的時(shí)候氓皱,瀏覽器可能會(huì)意外刷新或關(guān)閉,導(dǎo)致數(shù)據(jù)丟失勃刨。我們可以將用戶每次輸入的內(nèi)容保存到瀏覽器的本地存儲(chǔ)localStorage中匀泊。如果頁(yè)面刷新,可以從日志中恢復(fù)數(shù)據(jù)朵你,確保用戶體驗(yàn)的一致性各聘。

2. API 請(qǐng)求的可靠重試機(jī)制在微服務(wù)架構(gòu)中,API請(qǐng)求可能因網(wǎng)絡(luò)抖動(dòng)而失敗抡医。如果在每次請(qǐng)求發(fā)起之前躲因,將請(qǐng)求數(shù)據(jù)先寫(xiě)入日志文件,就可以在請(qǐng)求失敗的時(shí)候忌傻,根據(jù)日志進(jìn)行重試大脉,保證API調(diào)用的冪等性和可靠性。

3. 移動(dòng)應(yīng)用的離線數(shù)據(jù)同步在網(wǎng)絡(luò)不穩(wěn)定或離線場(chǎng)景下水孩,移動(dòng)應(yīng)用需要保存用戶操作并在網(wǎng)絡(luò)恢復(fù)時(shí)進(jìn)行同步镰矿。利用WAL的思路,我們可以將用戶的操作先記錄到本地日志文件中俘种,并在網(wǎng)絡(luò)恢復(fù)時(shí)重放這些日志秤标,以確保數(shù)據(jù)的一致性和正確性绝淡。

4. 文件系統(tǒng)的安全寫(xiě)入在需要自己管理本地文件,進(jìn)行讀寫(xiě)操作的場(chǎng)景苍姜,為了保證文件寫(xiě)入操作的安全性牢酵,可以在將變更操作寫(xiě)入到一個(gè)臨時(shí)文件之后,再修改或者替換原文件衙猪。這種方法可以有效防止在寫(xiě)入過(guò)程中發(fā)生崩潰而導(dǎo)致的數(shù)據(jù)損壞馍乙。以下是一段簡(jiǎn)單的Python代碼,展示如何使用臨時(shí)文件進(jìn)行文件更新:

import json
import os
import shutil
import threading

DATA_FILE = "data.json"
LOG_FILE = "data.log"
lock = threading.Lock()  # 創(chuàng)建一個(gè)全局鎖對(duì)象

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!")

總結(jié)和思考

Write-Ahead Logging (WAL)是一種強(qiáng)大而靈活的技術(shù)垫释,其核心思想非常簡(jiǎn)單:在更改數(shù)據(jù)之前丝格,先寫(xiě)日志。雖然主要應(yīng)用在數(shù)據(jù)庫(kù)系統(tǒng)中棵譬,但 WAL的思想具有普適性铁追。

從數(shù)據(jù)庫(kù)事務(wù)到前端數(shù)據(jù)保存,從離線數(shù)據(jù)同步到分布式系統(tǒng)的可靠操作管理茫船。它不僅能幫助我們構(gòu)建更加可靠和健壯的系統(tǒng)琅束,還能在面對(duì)復(fù)雜的技術(shù)挑戰(zhàn)時(shí),提供一種解決問(wèn)題的思考方式算谈。

理解WAL的機(jī)制涩禀,不管對(duì)于我們理解數(shù)據(jù)庫(kù)的原理,還是平時(shí)開(kāi)發(fā)中然眼,設(shè)計(jì)優(yōu)雅的解決方案艾船,都是有價(jià)值的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末高每,一起剝皮案震驚了整個(gè)濱河市屿岂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鲸匿,老刑警劉巖爷怀,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異带欢,居然都是意外死亡运授,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門乔煞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吁朦,“玉大人,你說(shuō)我怎么就攤上這事渡贾《阂耍” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)纺讲。 經(jīng)常有香客問(wèn)我擂仍,道長(zhǎng),這世上最難降的妖魔是什么刻诊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任防楷,我火速辦了婚禮牺丙,結(jié)果婚禮上则涯,老公的妹妹穿的比我還像新娘。我一直安慰自己冲簿,他們只是感情好粟判,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著峦剔,像睡著了一般档礁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吝沫,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天呻澜,我揣著相機(jī)與錄音,去河邊找鬼惨险。 笑死羹幸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辫愉。 我是一名探鬼主播栅受,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼恭朗!你這毒婦竟也來(lái)了屏镊?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤痰腮,失蹤者是張志新(化名)和其女友劉穎而芥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體膀值,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔚出,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虫腋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骄酗。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖悦冀,靈堂內(nèi)的尸體忽然破棺而出趋翻,到底是詐尸還是另有隱情,我是刑警寧澤盒蟆,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布踏烙,位于F島的核電站师骗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讨惩。R本人自食惡果不足惜辟癌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荐捻。 院中可真熱鬧黍少,春花似錦、人聲如沸处面。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)魂角。三九已至昵济,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間野揪,已是汗流浹背访忿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斯稳,地道東北人海铆。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像平挑,于是被迫代替她去往敵國(guó)和親游添。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • MySQL 里經(jīng)常說(shuō)到的 WAL技術(shù)通熄,也就是先寫(xiě)日志唆涝,再寫(xiě)磁盤。 當(dāng)內(nèi)存數(shù)據(jù)頁(yè)跟磁盤數(shù)據(jù)頁(yè)內(nèi)容不一致的時(shí)候唇辨,我們成...
    如夢(mèng)又似幻閱讀 16,608評(píng)論 3 6
  • 事務(wù)的定義 事務(wù)的基本要素(ACID)原子性:Atomicity廊酣,整個(gè)數(shù)據(jù)庫(kù)事務(wù)是不可分割的工作單位一致性:Con...
    binecy閱讀 286評(píng)論 0 0
  • 一、事務(wù)及其特性 首先看看什么是事務(wù)赏枚?事務(wù)具有哪些特性亡驰?關(guān)于事務(wù),上大學(xué)的時(shí)候饿幅,你應(yīng)該有接觸過(guò)相關(guān)的課程凡辱。簡(jiǎn)單來(lái)說(shuō)...
    四街的1024閱讀 942評(píng)論 0 0
  • 事務(wù)的定義 事務(wù)的基本要素(ACID)原子性:Atomicity,整個(gè)數(shù)據(jù)庫(kù)事務(wù)是不可分割的工作單位一致性:Con...
    曉碼君閱讀 351評(píng)論 0 1
  • 事務(wù)及其特性 什么是事務(wù)栗恩?事務(wù)具有哪些特性透乾?事務(wù)是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作,這些操作要么全做,要么全...
    owen_he閱讀 290評(píng)論 0 0