標籤:redis 事務 資料庫 應用 nosql
redis進階應用程式-事務
一、redis的事務
二、redis實現事務
三、redis事務問題
一、redis的事務
事務提供了一種“將多個命令打包,然後一次性、按順序地執行”的機制, 並且事務在執行的期間不會主動中斷 —— 伺服器在執行完事務中的所有命令之後, 才會繼續處理其他用戶端的其他命令。
二、redis實現事務
redis 通過 multi 、disacrd、exec 和 watch四個命令來實現事務功能
1、redis事務簡單例子
127.0.0.1:6379> multi
OK
127.0.0.1:6379>set name xiaobei
QUEUED
127.0.0.1:6379>get name
QUEUED
127.0.0.1:6379>exec
1)OK
2)"xiaobei"
2、詳解redis事務過程
2.1、一個事務從開始到執行會經曆以下三個階段:a、開始事務。b、命令入隊。c、執行事務。
2.1.1、開始事務
127.0.0.1:6379>multi
(備忘: 這個命令的作用就是讓用戶端從非事務狀態切換到事務狀態)
2.1.2、命令入隊
127.0.0.1:6379> set name xiaobei
QUEUED
(備忘: 如果用戶端處於非事務狀態下,所有發送給服務端的命令都會立即執行。相反,伺服器在收到來自用戶端的命令時,不會立即執行命令, 而是將這些命令全部放進一個事務隊列裡, 然後返回 QUEUED , 表示命令已入隊)
命令入隊的流程圖:
2.1.3、執行事務
127.0.0.1:6379>exec
1)OK
2)"xiaobei"
(備忘: 當 exec 命令執行時, 伺服器根據用戶端所儲存的事務隊列,以先進先出(FIFO)的方式執行事務隊列中的命令: 最先入隊的命令最先執行, 而最後入隊的命令最後執行。當事務隊列裡的所有命令被執行完之後, exec命令會將回複隊列作為自己的執行結果返回給用戶端, 用戶端從事務狀態返回到非事務狀態, 至此, 事務執行完畢)
執行事務的流程圖:
3、撤銷事務
127.0.0.1:6379> multi
OK
127.0.0.1:6379>set name xiaobei
QUEUED
127.0.0.1:6379>discard
OK
127.0.0.1:6379>exec
(error) ERREXEC without MULTI
(備忘: discard 命令用於取消一個事務, 它清空用戶端的整個事務隊列, 然後將用戶端從事務狀態調整回非事務狀態,最後返回字串 OK 給用戶端, 說明事務已被取消)
4、帶watch的事務
watch 命令用於在事務開始之前監視任意數量的鍵: 當調用 exec命令執行事務時, 如果任意一個被監視的鍵已經被其他用戶端修改了,那麼整個事務不再執行, 直接返回失敗
4.1、例子
4.2、以下表格展示了用戶端A是如何失效
|
時間 |
用戶端A |
用戶端B |
|
t1 |
watch name |
|
|
t2 |
multi |
|
|
t3 |
set name xiaobei |
|
|
t4 |
|
set name hello |
|
t5 |
exec |
|
(備忘: 在時間 t4 ,用戶端 B 修改了 name 鍵的值, 當用戶端 A 在 t5 執行 exec 時,Redis 會發現 name 這個被監視的鍵已經被修改,因此用戶端 A 的事務不會被執行,而是直接返回失敗)
三、redis事務問題
1、為什麼redis不支援復原
a、redis 命令只會因為錯誤的文法而失敗(並且這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面:這也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生產環境中
b、因為不需要對復原進行支援,所以 Redis 的內部可以保持簡單且快速
2、事務狀態下的 discard、multi和watch命令
除了 exec之外, 伺服器在用戶端處於事務狀態時,不加入到事務隊列而直接執行的另外三個命令是 discard、multi和watch。
discard命令用於取消一個事務, 它清空用戶端的整個事務隊列,然後將用戶端從事務狀態調整回非事務狀態, 最後返回字串 OK 給用戶端, 說明事務已被取消。
redis的事務是不可嵌套的, 當用戶端已經處於事務狀態,而用戶端又再向伺服器發送 multi時, 伺服器只是簡單地向用戶端發送一個錯誤, 然後繼續等待其他命令的入隊。 multi命令的發送不會造成整個事務失敗, 也不會修改事務隊列中已有的資料。
watch只能在用戶端進入事務狀態之前執行, 在事務狀態下發送watch命令會引發一個錯誤, 但它不會造成整個事務失敗, 也不會修改事務隊列中已有的資料(和前面處理 multi的情況一樣)
3、在事務和非事務狀態下執行命令
a、非事務狀態下的命令以單個命令為單位執行,前一個命令和後一個命令的用戶端不一定是同一個;而事務狀態則是以一個事務為單位,執行事務隊列中的所有命令:除非當前事務執行完畢,否則伺服器不會中斷事務,也不會執行其他用戶端的其他命令。
b、在非事務狀態下,執行命令所得的結果會立即被返回給用戶端;而事務則是將所有命令的結果集合到回複隊列,再作為 EXEC 命令的結果返回給用戶端
4、事務中的錯誤
1、使用事務時可能會遇上以下兩種錯誤:
a、事務在執行EXEC 之前,入隊的命令可能會出錯。比如說,命令可能會產生語法錯誤(參數數量錯誤,參數名錯誤,等等),或者其他更嚴重的錯誤,比如記憶體不足(如果伺服器使用 maxmemory 設定了最大記憶體限制的話)。
b、命令可能在EXEC 調用之後失敗。舉個例子,事務中的命令可能處理了錯誤類型的鍵,比如將列表命令用在了字串鍵上面等。
2、執行個體
(備忘: 最重要的是記住這樣一條, 即使事務中有某條/某些命令執行失敗了, 事務隊列中的其他命令仍然會繼續執行—— redis 不會停止執行事務中的命令)
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
小貝_redis 進階應用程式-事務