[TOC]
## 基礎
MULTI、EXEC、DISCARD 和 WATCH 命令是 Redis 實現事務的的基礎。
Redis 事務的執行過程包含三個步驟:
1. 開啟事務;
2. 命令入隊;
3. 執行事務或丟棄;
## 三個重要的保證
**Redis 事務可以一次執行多個命令, 并且帶有以下三個重要的保證:**
1. 批量指令在執行 EXEC 命令之前會放入隊列暫存;
2. 收到 EXEC 命令后進入事務執行,事務中任意命令執行失敗,其余的命令依然被執行;
3. 事務執行過程中,其他客戶端提交的命令不會插入到當前命令執行的序列中。
## 原子性
>1、EXEC執行前
**事務中的所有命令都不會再被執行了,保證了原子性**
2、EXEC執行后
**Redis 雖然會對錯誤指令報錯,但是事務依然會把正確的命令執行完,這時候事務的原子性就無法保證了!**
3、EXEC執行時
如果 Redis 開啟了 AOF 日志,那么,只會有部分的事務操作被記錄到 AOF 日志中。
我們需要使用 redis-check-aof 工具檢查 AOF 日志文件,這個工具可以把未完成的事務操作從 AOF 文件中去除。
這樣一來,我們使用 AOF 恢復實例后,事務操作不會再被執行,從而保證了原子性。
**簡單總結**:
* 命令入隊時就報錯,會放棄事務執行,保證原子性;
* 命令入隊時沒報錯,實際執行時報錯,不保證原子性;
* EXEC 命令執行時實例故障,如果開啟了 AOF 日志,可以保證原子性。
## 一致性
>一致性會受到錯誤命令、實例故障發生時機的影響
1、EXEC執行前
事務會被放棄執行,所以可以保證一致性。
2、EXEC執行后
有錯誤的命令不會執行,正確的指令可以正常執行,一致性可以保證。
3、EXEC執行時,實列故障
實例故障后會進行重啟,這就和數據恢復的方式有關了,我們要根據實例是否開啟了 RDB 或 AOF 來分情況討論下。
(1)如果我們沒有開啟 RDB 或 AOF,那么,實例故障重啟后,數據都沒有了,數據庫是一致的。
(2)如果我們使用了 RDB 快照,**因為 RDB 快照不會在事務執行時執行。**
所以,**事務命令操作的結果不會被保存到 RDB 快照中**,使用 RDB 快照進行恢復時,數據庫里的數據也是一致的。
(3)如果我們使用了 AOF 日志,而事務操作還沒有被記錄到 AOF 日志時,實例就發生了故障,那么,使用 AOF 日志恢復的數據庫數據是一致的。
如果只有部分操作被記錄到了 AOF 日志,我們可以使用 redis-check-aof 清除事務中已經完成的操作,數據庫恢復后也是一致的。
## 隔離性
>1. 并發操作在`EXEC`命令前執行,隔離性需要通過`WATCH`機制保證。
WATCH 機制的作用是:在事務執行前,監控一個或多個鍵的值變化情況,當事務調用 EXEC 命令執行時,WATCH 機制會先檢查監控的鍵是否被其它客戶端修改了。**如果修改了,就放棄事務執行,避免事務的隔離性被破壞。**
沒有watch時,不能保證
> 2. 并發操作在`EXEC`命令之后,隔離性可以保證。
雖然在沒有watch時不能保證,但是Redis 是用單線程執行命令,而且,EXEC 命令執行后,Redis 會保證先把命令隊列中的所有命令執行完再執行之后的指令。所以,在這種情況下,并發操作不會破壞事務的隔離性。
## 持久性
>如果 Redis 沒有使用 RDB 或 AOF,那么事務的持久化屬性肯定得不到保證。
如果 Redis 使用了 RDB 模式,那么,在一個事務執行后,而下一次的 RDB 快照還未執行前,如果發生了實例宕機,數據丟失,這種情況下,事務修改的數據也是不能保證持久化的。
如果 Redis 采用了 AOF 模式,因為 AOF 模式的三種配置選項 no、everysec 和 always 都會存在數據丟失的情況。
所以,事務的持久性屬性也還是得不到保證。
**不管 Redis 采用什么持久化模式,事務的持久性屬性是得不到保證的。**
## 總結
* Redis 具備了一定的原子性,但不支持回滾。
* Redis 具備 ACID 中一致性的概念。
* Redis 具備隔離性。
* Redis 無法保證持久性。
**Redis 的事務機制可以保證一致性和隔離性,但是無法保證持久性。**
不過,因為 Redis 本身是內存數據庫,持久性并不是一個必須的屬性,我們更加關注的還是原子性、一致性和隔離性這三個屬性。
原子性的情況比較復雜,**當事務中使用的命令語法有誤時,原子性得不到保證**,在其它情況下,事務都可以原子性執行。
數據來源:https://mp.weixin.qq.com/s/UZTMuf2UOJu7N4lYQ_AjKQ
- 消息隊列
- 為什么要用消息隊列
- 各種消息隊列產品的對比
- 消息隊列的優缺點
- 如何保證消息隊列的高可用
- 如何保證消息不丟失
- 如何保證消息不會重復消費?如何保證消息的冪等性?
- 如何保證消息消費的順序性?
- 基于MQ的分布式事務實現
- Beanstalk
- PHP
- 函數
- 基礎
- 基礎函數題
- OOP思想及原則
- MVC生命周期
- PHP7.X新特性
- PHP8新特性
- PHP垃圾回收機制
- php-fpm相關
- 高級
- 設計模式
- 排序算法
- 正則
- OOP代碼基礎
- PHP運行原理
- zavl
- 網絡協議new
- 一面
- TCP和UDP
- 常見狀態碼和代表的意義以及解決方式
- 網絡分層和各層有啥協議
- TCP
- http
- 二面
- TCP2
- DNS
- Mysql
- 鎖
- 索引
- 事務
- 高可用?高并發?集群?
- 其他
- 主從復制
- 主從復制數據延遲
- SQL的語?分類
- mysqlQuestions
- Redis
- redis-question
- redis為什么那么快
- redis的優缺點
- redis的數據類型和使用場景
- redis的數據持久化
- 過期策略和淘汰機制
- 緩存穿透、緩存擊穿、緩存雪崩
- redis的事務
- redis的主從復制
- redis集群架構的理解
- redis的事件模型
- redis的數據類型、編碼、數據結構
- Redis連接時的connect與pconnect的區別是什么?
- redis的分布式鎖
- 緩存一致性問題
- redis變慢的原因
- 集群情況下,節點較少時數據分布不均勻怎么辦?
- redis 和 memcached 的區別?
- 基本算法
- MysqlNew
- 索引new
- 事務new
- 鎖new
- 日志new
- 主從復制new
- 樹結構
- mysql其他問題
- 刪除
- 主從配置
- 五種IO模型
- Kafka
- Nginx
- trait
- genergtor 生成器
- 如何實現手機掃碼登錄功能
- laravel框架的生命周期