[TOC]
# 簡介
Redis和傳統的關系型數據庫一樣,因為具有持久化的功能,所以也有事務的功能!
有關事務相關的概念和介紹,這里就不做介紹。
在學習Redis的事務之前,首先拋出一個面試的問題。
面試官:請問Redis支持事務嗎?如果支持和傳統的關系型數據的事務有什么區別?
應試者:支持,但是是部分支持。Redis的事務和傳統的關系型數據庫事務有點不一樣,傳統的數據庫事務一組操作單元,要么全部成功,要么全都失敗。而Redis在執行一個命令集合的時候,可能會出現集合的一些命令成功,一些命令失敗。
# 參考文檔
Redis 事務-中文官網:http://www.redis.cn/topics/transactions.html
Redis 事務| 菜鳥教程 :http://www.runoob.com/redis/redis-transactions.html
# 總結:
1. 是什么?
可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,按順序地串行化執行而不會被其它命令插入,不許加塞。
2. 能做什么?
一個隊列中,一次性、順序性、排他性的執行一系列命令
3. 常用命令
~~~
1 DISCARD
取消事務,放棄執行事務塊內的所有命令。
2 EXEC
執行所有事務塊內的命令。
3 MULTI
標記一個事務塊的開始。
4 UNWATCH
取消 WATCH 命令對所有 key 的監視。
5 WATCH key [key ...]
監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷。
~~~
4. 怎么玩?
案例1:正常執行
~~~
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379> MULTI #開始事務
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> EXEC #執行,全部執行成功
1) OK
2) OK
3) OK
127.0.0.1:6379> MGET k1 k2 k3 #查看執行結果
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379>
~~~
案例2:放棄事務
~~~
127.0.0.1:6379> MULTI #開始事務
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> set k1 v11 #這里發現出錯了,第一次設置k1 了
QUEUED
127.0.0.1:6379> DISCARD #放棄事務
OK
127.0.0.1:6379> MGET k1 k2 k3 k4 k5 #k4 k5 的值沒有設置成功
1) "v1"
2) "v2"
3) "v3"
4) (nil)
5) (nil)
127.0.0.1:6379>
~~~
案例3:全體連坐(一個出錯,全部執行失敗)
~~~
127.0.0.1:6379> KEYS * #查看當前的keys
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> MULTI #開始事務
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> getandset k1 #這里有個操作出錯 ,下面報錯,
(error) ERR unknown command 'getandset'
127.0.0.1:6379> set k6 v6 # 這個命令依舊執行成功,放到Queued隊列
QUEUED
127.0.0.1:6379> EXEC #執行,出錯
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> MGET k1 k2 k3 k4 k5 k6 #k4 k5 k6 的值都沒有設置成功,操作全部失敗
1) "v1"
2) "v2"
3) "v3"
4) (nil)
5) (nil)
6) (nil)
127.0.0.1:6379>
~~~
案例4:冤頭債主(一個出錯,出錯的不執行,其他的執行成功!)
~~~
127.0.0.1:6379> set k1 1 #將k1 修改為 1
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> MULTI #開啟事務
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set v5 v5
QUEUED
127.0.0.1:6379> INCR k1 #k1 加1
QUEUED
127.0.0.1:6379> INCR k2 #k2 加1 ,因為k2的值為v2 ,這里最后執行會報錯
QUEUED
127.0.0.1:6379> INCR k3 #k3 加1
QUEUED
127.0.0.1:6379> set k6 v6
QUEUED
127.0.0.1:6379> EXEC #執行,除了 k2 k3 執行失敗,其他的都執行成功。
1) OK
2) OK
3) (integer) 2
4) (error) ERR value is not an integer or out of range #INCR k2 執行出錯
5) (error) ERR value is not an integer or out of range #INCR k3 執行出錯
6) OK
127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6 #看到k4 v5 k6 設置成功
1) "2"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
6) "v6"
127.0.0.1:6379>
~~~
案例5:watch監控(watch可以監控多個key,使用watch進行key的監控,相當于給key上鎖,如果在事務中,監控的key的value發生變化,則整個事務的全部命令都執行失敗)
~~~
127.0.0.1:6379> KEYS *
1) "k3"
2) "k4"
3) "k2"
4) "v5"
5) "k1"
6) "k6"
127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6
1) "2"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
6) "v6"
127.0.0.1:6379> WATCH k1 #監控k1 第一步
OK
127.0.0.1:6379> MULTI #開始事務 第二步
OK
127.0.0.1:6379> set k7 v7 #第三步
QUEUED
127.0.0.1:6379> set k2 v2222 #第四步
QUEUED
127.0.0.1:6379> set k3 v3333 #第五步
QUEUED
127.0.0.1:6379> set k8 v8 #第六步
QUEUED
127.0.0.1:6379> EXEC #第七步 #執行結果為nil ,說明執行失敗
(nil)
127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6 k7 k8
1) "110" #k1 的值被改了 ,其他的事務中的值都沒有成功
2) "v2"
3) "v3"
4) "v4"
5) "v5"
6) "v6"
7) (nil)
8) (nil)
127.0.0.1:6379>
--
在執行第三 —— 第六步之間,使用另一個客戶端修改k1 的值為 成110
另一個客服端執行:
127.0.0.1:6379> set k1 110
OK
~~~
案例5解釋:因為另一個客服端修改 了k1的值,但是k1的值是被監控的,事務在執行的時候發現k1的值被修改了,則事務中的其他操作命令也不執行,即執行失敗。
5. 執行階段
開啟:以MULTI開始一個事務
入隊:將多個命令入隊到事務中,接到這些命令并不會立即執行,而是放到等待執行的事務隊列里面
執行/撤銷:由EXEC/Discard 命令觸發/撤銷事務
6. 總結
* 單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷
* 沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務里的更新,在事務外查詢不能看到”這個讓人萬分頭痛的問題
* 不保證原子性:redis同一個事務中如果有一條命令執行失敗,其后的命令仍然會被執行,沒有回滾
# 備注知識 :
## 悲觀鎖:
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block
直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖.
## 樂觀鎖:
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,
樂觀鎖策略:提交版本必須大于記錄當前版本才能執行更新
## CAS(check and set)
悲觀鎖和樂觀鎖相關的參考博文:
Java 中的悲觀鎖和樂觀鎖的實現:https://toutiao.io/posts/400085/app_preview
樂觀鎖的一種實現方式:CAS:http://blog.csdn.net/qq32933432/article/details/51036361
- SQL
- 名詞
- mysql
- 初識mysql
- 備份和恢復
- 存儲引擎
- 數據表損壞和修復
- mysql工具
- 數據庫操作
- 增
- 刪
- 改
- 查
- 數據類型
- 整數類型
- 小數類型
- 日期時間類型
- 字符和文本型
- enum類型
- set類型
- 時間類型
- null與not null和null與空值''的區別
- 數據表操作
- 創建
- 索引
- 約束
- 表選項列表
- 表的其他語句
- 視圖
- sql增刪改查
- sql增
- sql刪
- sql改
- sql查
- sql語句練習
- 連接查詢和更新
- 常用sql語句集錦
- 函數
- 字符函數
- 數值運算符
- 比較運算符與函數
- 日期時間函數
- 信息函數
- 聚合函數
- 加密函數
- null函數
- 用戶權限管理
- 用戶管理
- 權限管理
- pdo
- 與pdo相關的幾個類
- 連接數據庫
- 使用
- pdo的錯誤處理
- pdo結果集對象
- pdo結果集對象常用方法
- pdo預處理
- 常用屬性
- mysql編程
- 事務
- 語句塊
- mysql中的變量
- 存儲函數
- 存儲過程
- 觸發器
- mysql優化
- 存儲引擎
- 字段類型
- 三范式和逆范式
- 索引
- 查詢緩存
- limit分頁優化
- 分區
- 介紹
- 分區算法
- list分區
- range范圍
- Hash哈希
- key鍵值
- 分區管理
- 特別注意
- 分表
- 數據碎片與維護
- innodb表壓縮
- 慢查詢
- explain執行計劃
- count和max,groupby優化
- 子查詢優化
- mysql鎖機制
- 介紹
- 演示
- 總結
- 樂觀鎖和悲觀鎖
- 扛得住的mysql
- 實例和故事
- 系統參數優化
- mysql體系結構
- mysql基準測試
- 索引
- mysql的復制
- win配置MySQL主從
- mysql5.7新特性
- 常見問題
- general log
- 忘記密碼
- uodo log與redo log
- 事務隔離級別
- mysql8密碼登錄
- explain
- 高效的Tree表
- on delete cascade 總結
- mongod
- 簡介
- 集合文檔操作語句
- 增刪改查
- 索引
- 數據導入和導出
- 主從復制
- php7操作mongod
- 權限管理
- redis
- redis簡介
- 3.2版本配置文件
- 3.0版本配置文件
- 2.8版本配置文件
- 配置文件總結
- 外網連接
- 持久化
- RDB備份方式保存數據
- AOF備份方式保存數據
- 總結
- win安裝redis和sentinel部署
- 事務
- Sentinel模式配置
- 分布式鎖
- 管道
- php中redis代碼
- 發布訂閱
- slowlog
- Redis4.0
- scan和keys
- elasticsearch
- 配置說明
- 啟動
- kibana
- kibana下載
- kibana配置文件
- kibana常用功能
- 常用術語
- Beats
- Beats簡介
- Filebeat
- Packetbeat
- Logstash
- 配置
- elasticsearch架構
- es1.7
- head和bigdesk插件
- 插件大全
- 倒排索引
- 單模式下API增刪改查
- mget獲取多個文檔
- 批量操作bulk
- 版本控制
- Mapping映射
- 基本查詢
- Filter過濾
- 組合查詢
- es配置文件
- es集群優化和管理
- logstash
- kibana
- es5.2
- 安裝
- 沖突處理
- 數據備份
- 缺陷不足
- 集群管理api
- 分布式事務
- CAP理論
- BASE模型
- 兩階段提交(2PC)
- TCC (Try-Confirm-Cancle)
- 異步確保型
- 最大努力通知型
- 總結