為什麼在 Redis 實現 Lua 指令碼事務?
在剛過去的幾個月中,我一直在構思並嘗試在 redis 中實現 lua 指令碼的事務功能。沒有多少人理解我的想法,所以我將通過一些歷史為大家做下解釋。
MySQL 與 Postgres
在 1998-2003 年間,如果你想執行一個正規的資料庫驅動的網站/服務,但又沒有足夠的資金購買微軟或 Oracle 的資料庫,你可以選擇 MySQL 或 Postgres 。很多人都選擇了 MySQL,因為它速度較快——主要是因為 MyISAM 儲存引擎沒有提供事務功能以此來換取效能,但速度確實很快。另一些人轉向 Postgres,因為雖然在相同硬體上其效能明顯低於 MySQL,但 Postgres 不會丟失資料(說實話,MySQL 資料丟失的情況非常少見,但丟了可不是鬧著玩的)。
就這樣湊合著過了很久;MySQL 將其預設的儲存引擎從 MyISAM 過渡到了 InnoDB (其實很早就有了),這樣它的儲存引擎也得到了完整的事務支援和其他功能。與此同時,Postgres 也變快了,並新增了一個持續擴充套件的功能列表來使自己與眾不同。現在對於 MySQL 與 Postgres 的選擇只看個人的體驗與偏好,除了有時業務需要或領導決定使用其他選擇。
資料完整性
從很多方面來看,Redis 很像當初採用 InnoDB 前的 MySQL。而 Redis 採用了一種很合理的方式來保證資料完整性(複製,AOF 等),並且從 Redis2.6 開始引入的 Lua 指令碼在功能與易用性方面為 Redis 的成長提供了很大助力。
相對來說,Lua 指令碼與其他資料庫中的儲存過程很相似,但指令碼的執行有些許不同。在本文中最重要的一點就是一旦將指令碼寫入資料庫,它會一直執行直到以下任一種情況出現:
1. 完成所有工作,所有寫操作處理完成後指令碼會自動退出。
2. 指令碼執行時出錯並中途退出,所有以前執行的寫操作都已發生,但不會再有其他寫操作。
3. Redis 通過 SHUTDOWN NOSAVE 關閉時(不儲存)。
4. 你附加了偵錯程式來“使”指令碼完成 #1 與 #2 (或其他手段來保證不會丟失資料)。
對於使用資料庫開發軟體的人,我想你也認同只有情景 #1 是最理想的。情景 #2,#3,#4 都會導致資料異常(#2 與 #4)和/或資料丟失(#3 和 #4)。如果你很重視資料,你應該儘可能地阻止資料異常與丟失。這不是哲學,而是工作(This is not philosophy, this is doing your job)。但很遺憾目前的 Redis 也幫不了你多少。所以我決定改變這種情況。
實現 Lua 指令碼事務
我嘗試解決上面列表中的 #2,#3,#4 問題,最終像下面這樣:
- 指令碼完成所有的工作,處理完寫操作後正常退出
- 指令碼執行過程中遇到錯誤退出,不更改任何資料(所有寫操作都回滾)
無論有沒有寫入資料,都不會有資料丟失。這應該是所有的資料庫都希望做到的,我打算把這個加到 Redis 中,因為我們都希望 Redis有 這個功能。
目前的 pull request 只是一個概念性的證明。也就是說,為了避免資料丟失,你要麼 a) 顯式使用事務的變體執行指令碼,要麼 b) 強制所有 Lua 指令碼呼叫帶配置選項的事務語義。
還有很多的辦法使現在這個 patch 變得更好,我希望能得到 Salvatore (Redisw 作者)和其他社群的幫助。
相關文章
- Lua 指令碼在 Redis 事務中的應用實踐指令碼Redis
- Lua指令碼在Redis事務中的應用實踐指令碼Redis
- Redis篇:事務和lua指令碼的使用Redis指令碼
- 一文講透 Redis 事務 (事務模式 VS Lua 指令碼)Redis模式指令碼
- redis+lua指令碼實現介面限流Redis指令碼
- 詳解事務模式和Lua指令碼,帶你吃透Redis 事務模式指令碼Redis
- Redis - Lua 指令碼Redis指令碼
- Redis使用lua指令碼實現庫存扣減Redis指令碼
- redis+lua實現指令碼一鍵查詢Redis指令碼
- Redis使用Lua指令碼Redis指令碼
- redis執行lua指令碼的實現方法括饃Redis指令碼
- 新姿勢!Redis中呼叫Lua指令碼以實現原子性操作Redis指令碼
- Redis Lua指令碼完全入門Redis指令碼
- redis初級之Lua指令碼Redis指令碼
- Redis 實戰 —— 14. Redis 的 Lua 指令碼程式設計Redis指令碼程式設計
- Redis學習筆記(三)使用Lua指令碼實現分散式鎖Redis筆記指令碼分散式
- 【redis】-使用Lua指令碼解決多執行緒下的超賣問題以及為什麼?Redis指令碼執行緒
- redis中lua指令碼的簡單使用Redis指令碼
- redis學習(九) redis事務和redis指令碼的比較Redis指令碼
- 深入分析 Redis Lua 指令碼執行原理Redis指令碼
- openresty+redis配合 lua指令碼封停 IPRESTRedis指令碼
- 如何在Redis中實現事務Redis
- Lua 指令碼在 Redis 中能夠保證操作不會被其他指令插入或打擾 ??指令碼Redis
- lua~IDEA中除錯lua指令碼Idea除錯指令碼
- Redis 使用 Lua 指令碼替代 SETNX / DECR 保證原子性Redis指令碼
- Redis 設計與實現 (七)--事務Redis
- 使用Spring Boot實現Redis事務 | VinsguruSpring BootRedis
- Redis 設計與實現 (九)--LuaRedis
- Golang 實現 Redis(8): TCC分散式事務GolangRedis分散式
- nginx+lua+redis實現灰度釋出NginxRedis
- Redis中的原子操作(2)-redis中使用Lua指令碼保證命令原子性Redis指令碼
- Redis 事務支援 ACID 麼?Redis
- Redis中Lua指令碼的使用和設定超時坍淑Redis指令碼
- 快速入門Redis呼叫Lua指令碼及使用場景介紹Redis指令碼
- 要想用活Redis,Lua指令碼是繞不過去的坎Redis指令碼
- 什麼是shell指令碼?Linux為什麼學習shell?指令碼Linux
- SpringGateway - Redis限流元件之Luau指令碼&Java實現SpringGatewayRedis元件指令碼Java
- MySQL:begin後事務為什麼不提交MySql
- wrk(2)- Lua 指令碼的使用指令碼