事務的定義

事務是一組具備原子性操作的命令集合。在這一組命令中,要么全部執(zhí)行成功,要么全部執(zhí)行失敗。

事務的特點

  1. 原子性。原子性指的是事務操作具備原子操作,一個事務里面的 SQL 操作要么全部成功要么全部失敗,不能存在一些 SQL 成功,一些 SQL 執(zhí)行失敗。
  2. 隔離性。隔離性指的是多個事務之間是相互隔離的,事務之間是互不受影響的。
  3. 持久性。持久性指的是事務一旦提交,就不能進行回滾(撤回),永久的保存在磁盤中。
  4. 一致性。一致性指的是事務操作前后必須滿足業(yè)務約束。

有關事務的四大特性的具體講解可以參考該文章
http://mindoc.qqdeveloper.com/docs/mysql/mysql-1cj2eksj770bg

Redis事務執(zhí)行邏輯

Redis在事務中的命令是添加到一個命令隊列里面,等待事務提交之后,則一一執(zhí)行命令隊列里面的命令。

Redis事務命令

  1. multi:開啟事務。
  2. exec:提交當前事務。
  3. discard:取消當前事務。
  4. watch:監(jiān)聽key是否在事務開啟之前被其他命令修改,如果被修改去不處理事務內的操作。
  5. unwatch:取消監(jiān)聽key是否在事務開啟之前被其他的命令修改。

命令演示

  1. 事務執(zhí)行流程。

客戶端一:負責開啟事務并寫入緩存數(shù)據(jù)。

127.0.0.1:6379> multiOK127.0.0.1:6379> set user:id:1 1QUEUED127.0.0.1:6379> exec1) OK

事務執(zhí)行exec命令返回的是,事務中執(zhí)行的命令數(shù)量以及對應的結果。

客戶端二:負責讀取緩存中的數(shù)據(jù)。

# 客戶端一執(zhí)行set之后,執(zhí)行exec之前。127.0.0.1:6379> get user:id:1(nil)# 客戶端執(zhí)行exec之后。127.0.0.1:6379> get user:id:1"1"
  1. watch對key監(jiān)聽。

客戶端一:負責開啟事務,并使用watch監(jiān)聽key。

# 監(jiān)聽key之前查看值127.0.0.1:6379> get age"1"# 開啟監(jiān)聽127.0.0.1:6379> watch ageOK# 開啟事務127.0.0.1:6379> multiOK# 修改被監(jiān)聽的key值127.0.0.1:6379> set age 2QUEUED# 提交事務(發(fā)現(xiàn)返回的是nil,表示未執(zhí)行成功。)127.0.0.1:6379> exec(nil)# 重新獲取監(jiān)聽的key值127.0.0.1:6379> get age"3"

客戶端二:負責修改客戶端一中監(jiān)聽的key。

# 在客戶端一執(zhí)行watch命令,開啟事務之后,提交事務之前執(zhí)行。127.0.0.1:6379> set age 3OK# 在客戶端一執(zhí)行exec命令之后執(zhí)行。127.0.0.1:6379> get age"3"

通過2中的演示,你會發(fā)現(xiàn)在事務開啟之前對key做了監(jiān)聽。事務正常提交之后,被監(jiān)聽的key在事務中執(zhí)行的命令是不會被執(zhí)行的。unwatch對監(jiān)聽的key,取消監(jiān)聽事件。此時的取消監(jiān)聽不能放在事務中,只能在事務開啟之前對key的監(jiān)聽事件做取消。 事務命令異常處理

事務原子性演示

  1. 命令錯誤的原子性。
127.0.0.1:6379> multiOK127.0.0.1:6379> set user:name zhangsanQUEUED127.0.0.1:6379> set user:age 1QUEUED127.0.0.1:6379> set user:sex maxQUEUED# 執(zhí)行一條命令錯誤的操作127.0.0.1:6379> set a(error) ERR wrong number of arguments for set command# 提交事務127.0.0.1:6379> exec(error) EXECABORT Transaction discarded because of previous errors.127.0.0.1:6379> keys *1) "user:id:1"2) "name"3) "age"

通過上面的演示,在事務中執(zhí)行一條錯誤的語法命令,整個事務都將不會被執(zhí)行。

  1. 內部語法使用錯誤。
127.0.0.1:6379> get name"zhangsan"127.0.0.1:6379> multiOK127.0.0.1:6379> set mu:id 1QUEUED# 執(zhí)行一個語法不當?shù)牟僮?27.0.0.1:6379> incr nameQUEUED127.0.0.1:6379> set mu:age 2QUEUED127.0.0.1:6379> exec1) OK2) (error) ERR value is not an integer or out of range3) OK

通過上面的演示,在事務中執(zhí)行了一條語法不當?shù)牡牟僮?,最終提交事務后。事務中的正確命令依舊不被執(zhí)行了。這不符合事務原子性的特點。

  1. 事務原子性總結。

    a. 當事務中存在語法使用不當?shù)那闆r時,事務會跳過當前的命令。其他的正確命令依舊被執(zhí)行。

    b. Redis中的事務并非一定滿足原子性的特點。

    c. 在事務中,執(zhí)行的命令,Redis只會檢測是否是一個合法的命令。如果合法則添加到命令隊列,如果不合法則直接阻止整個事務的執(zhí)行。

常見問題總結

MySQL中的事務與Redis事務的區(qū)別

  1. Redis事務與Mysql事務我們知道關系性數(shù)據(jù)庫Mysql中具有事務的四大特性:「原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)」。

  2. 但是Redis的事務為了保證Redis除了客戶端的請求高效,去除了傳統(tǒng)關系型數(shù)據(jù)庫的「事務回滾、加鎖、解鎖」這些消耗性能的操作,Redis的事務實現(xiàn)簡單。

  3. 原子性中Redis的事務只能保證單個命令的原子性,多個命令就無法保證,如上面索道的運行時錯誤,即使中間有運行時錯誤出現(xiàn)也會正確的執(zhí)行后面正確的命令,不具有回滾操作。

  4. 既然沒有了原子性,數(shù)據(jù)的一致性也就無法保證,這些都需要程序員自己手動去實現(xiàn)。Reids在進行事務的時候,不會被中斷知道事務的運行結束,也具有一定的隔離性,并且Redis也能持久化數(shù)據(jù)。