大家好,我是 31 歲愛講故事的小米,一個喜歡在通勤路上刷源碼、在深夜裏喝咖啡寫技術文章的大哥哥。
前兩天去面一家公司,本來以為是常規“扯扯項目、問問框架、聊聊八股”那種,卻沒想到面試官直接用一句:
“小米,聊聊事務吧。ACID 是什麼?説具體點。”
我當場一個激靈:這不是八股中的八股嗎?但面試嘛,不能只説術語,要講人話,還要講故事。
於是我端起喝了一半的美式,就像講武俠一樣,把“事務”講成一出江湖大戲。
這一講,面試官聽得直點頭,最後還説一句:“有意思,你這個解釋方式我第一次聽。”
所以今天,就把那套講故事的方式寫下來,給你做武功秘籍,不僅讓你理解,還能讓你在下一次面試時吊打法器。
第一章:ACID 是什麼?江湖規矩四大門派
我當時對面試官笑笑説:
“事務嘛?就像江湖中的‘四大門派’,想維護世界和平就必須守住四個規矩。”
這四個規矩就是:
- A - Atomicity 原子性
- C - Consistency 一致性
- I - Isolation 隔離性
- D - Durability 持久性
為了讓他聽懂,我開始講故事:
原子性:一刀到底,不分你我
原子性像是一個江湖殺手的規矩:
要麼成功一刀斃命,要麼收刀走人,不能砍一半卡住。
事務也是一樣:
- 要麼全部執行成功
- 要麼全部不執行
比如銀行轉賬:
- A 扣 100 元
- B 加 100 元
這兩件事必須成對出現。如果只扣不加?社會亂套了。
因此數據庫保證在任何異常情況下都能“自動回滾”,確保事務像一刀到底的武功。
一致性:江湖必須保持平衡
一致性像江湖的天道平衡:
不管發生什麼,一定要保持前後邏輯一致。
比如銀行轉賬前:
- 總金額 = 1 萬
轉賬後:
- 總金額仍舊 = 1 萬
不會憑空多錢,也不會憑空少錢。
數據庫通過約束、觸發器、外鍵、校驗等保證這個平衡。
隔離性:各練各的功,不互相干擾
我當場舉例:
假設你去銀行取錢,同時我也去銀行取錢。你在窗口操作,我在 App 上操作,我們兩個的事務不能互相干擾,否則肯定會出現:
- 你看到的餘額被我修改
- 我看到的餘額被你覆蓋
隔離性就是:
讓每個事務擁有獨立練功房間,不被其他事務干擾。
數據庫有 4 個隔離級別:
- Read Uncommitted
- Read Committed
- Repeatable Read
- Serializable
隔離性越高,越安全,但性能越低。這就是江湖中典型的“安全 vs 性能”兩難。
持久性:功練成了,誰也抹不掉
持久性就像練成了絕世神功,無論外界怎麼風雨飄搖,你的功力不會掉。
數據庫裏,事務只要提交成功:
- 數據必須持久化
- 即使斷電、宕機、服務器崩潰也不能丟
這就是 WAL 日誌、redo log、binlog、checkpoint 等的價值。
到這裏,面試官笑着點點頭:“不錯,有畫面感。”
第二章:Redis 事務?呵呵,它不姓 ACID,它姓 KISS(簡單粗暴)
Redis 為什麼火?就是因為它足夠 簡單 + 暴力 + 快。於是它在事務這件事上,也延續了“簡單到離譜”的路線。
我繼續講故事:
“Redis 的事務不像數據庫那樣是‘江湖大師’,更像街邊擼串小店:
要不要一次性把菜都烤完?行。
要不要幫你回滾?不行。
要不要隔離?嗯……我們這裏沒那玩意。”
面試官:“繼續説。”
於是我説:
第三章:Redis 支持隔離性嗎?不支持!
Redis 用的是單線程模型。
也就是説,一個事務在執行的時候:
Redis 沒法讓其他命令插隊,但也沒法提供真正的隔離級別。
細説:
- Redis 的事務只是把命令收集起來
- 等到 EXEC 時,一次性按順序執行
- 但整個過程中,Redis 不會隔離讀寫,不會快照,不會鎖住數據
所以 Redis 沒有隔離性!
你甚至在事務執行前:
- 看到的數據已經被別人改了
- watch 的鍵被修改後,整個事務直接失敗
典型的“你別動,我做完再説”的模式。
第四章:Redis 事務保證原子性嗎?不保證!
這句我一説完,面試官立刻坐直。
因為很多人以為 Redis 的事務很強,其實不是。Redis 的事務是這樣:
- Redis 只保證 EXEC 中的命令會連續執行,不會被其他客户端插隊
- 但不保證全部成功,要失敗就會局部失敗
比如你執行:
結果:
- SET a 成功
- INCR b 報錯
- SET c 成功
Redis 不會幫你回滾!不會!不會!不會!
這就是 Redis 事務最大的坑:它不具備原子性,只具備“順序性”。
第五章:Redis 支持回滾嗎?不支持!
我給面試官舉例:
“數據庫像是安全顧問,做錯事會幫你撤銷。
Redis 像是你那粗線條的好兄弟:
哥們我幫你做了,但做錯我也沒辦法。”
Redis 的哲學:
- 錯誤命令不會導致整個事務失敗
- 成功的命令不會被撤銷
- Redis 從來不保證回滾
為什麼?因為 Redis 追求速度,回滾會拖慢性能。
第六章:那 Redis 事務有什麼用?
這也是很多面試官愛問的關鍵點。
Redis 事務適合:
- 批量執行命令
- 給多個命令增加“一起執行”的語義
- 配合 WATCH 實現輕量級樂觀鎖
- 保證不會被插隊(單線程)
但絕不適合:
- 強一致
- 強隔離
- 強原子性
- 金融系統、轉賬系統
第七章:Redis 事務的三種核心機制
面試官問:“那 Redis 事務到底有哪些實現方式?”
我直接給他畫三條線:
1、MULTI / EXEC / DISCARD —— Redis 原生事務機制
流程:
- WATCH key(可選)——監聽變化,相當於樂觀鎖
- MULTI —— 開啓事務
- 一堆命令排隊
- EXEC —— 執行
- DISCARD —— 放棄事務
缺點:
- 沒有回滾
- 沒有隔離
- 執行出錯不會撤銷之前命令
2、WATCH —— 樂觀鎖
WATCH 就是:
“我盯着某幾個鍵,你要是敢改,我就直接放棄執行。”
適合解決:
- 搶購
- 庫存扣減
- CAS 更新(Compare And Set)
但 WATCH 失敗後要自己重試。Redis 不會幫你。
3、Lua 腳本 —— 真正的“Redis 原子性之王”
我當時看着面試官説:
“如果你真的想在 Redis 中實現原子性,那你一定要用 Lua。”
因為:
- Lua 腳本在 Redis 裏是原子執行
- 期間不會有其他命令插隊
- 執行要麼全部成功,要麼全部失敗(邏輯自己寫)
- 可以用邏輯手動模擬回滾
Lua 才是 Redis 中真正的“事務神器”。
面試官直接點頭:“對,這點很重要。”
第八章:總結——你在面試中應該這樣説
為了讓你面試不翻車,這裏給你一段 最佳答案:
ACID:
- 原子性:事務要麼全部成功,要麼全部失敗
- 一致性:數據前後符合規則
- 隔離性:多個事務互相隔離
- 持久性:提交後的數據不能丟失
Redis 事務:
- Redis 不支持嚴格意義上的隔離性
- Redis 事務不保證原子性,執行中有命令失敗不會回滾
- Redis 事務不支持回滾
- Redis 事務機制主要包括:
- MULTI / EXEC
- WATCH(樂觀鎖)
- Lua 腳本(唯一能保證原子性)
END
這就是我那天在面試現場講的一套故事型解釋方式。
面試官很滿意,因為:
- 不只是背概念
- 而是真正解釋了背後邏輯
- 還能用故事讓面試官不困
- 最重要——你講得和別人不一樣
希望你在下一次面試時,也能把事務講得像江湖一樣精彩。
我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!