成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試竟被問到Redis事務(wù),觸及知識(shí)盲區(qū),臉都綠了

運(yùn)維 數(shù)據(jù)庫運(yùn)維 Redis
在這里寫一篇文章對Redis的事務(wù)進(jìn)行詳細(xì)的講解,估計(jì)對Redis事務(wù)從理解到原理深入這一篇就夠了。

前言

前幾天有讀者說自己面試被問到Redis的事務(wù),雖然不常用,但是面試竟然被問到,平時(shí)自己沒有注意Redis的事務(wù)這一塊,面試的時(shí)候被問到非常不好受。

雖然,這位讀者面試最后算是過了,但是薪資方面沒有拿到自己理想的薪資。

其實(shí)這個(gè)也是正常的,一般面試被問到爛大街的,誰還問你啊,專門挑一些不常見的來問你,就是為了壓你的薪資。

所以在這里寫一篇文章對Redis的事務(wù)進(jìn)行詳細(xì)的講解,估計(jì)對Redis事務(wù)從理解到原理深入這一篇就夠了。

以后面試都不用擔(dān)心了再被問道Redis的事務(wù)了,這一篇主要講解Redis事務(wù)原理和實(shí)操的演練,理解理論的同時(shí)也通過實(shí)操來證實(shí)理論。

事務(wù)介紹

Redis事務(wù)是一組命令的集合,將多個(gè)命令進(jìn)行打包,然后這些命令會(huì)被順序的添加到隊(duì)列中,并且按順序的執(zhí)行這些命令。

「Redis事務(wù)中沒有像Mysql關(guān)系型數(shù)據(jù)庫事務(wù)隔離級(jí)別的概念,不能保證原子性操作,也沒有像Mysql那樣執(zhí)行事務(wù)失敗會(huì)進(jìn)行回滾操作」。

這個(gè)與Redis的特點(diǎn):「快速、高效」有著密切的關(guān)聯(lián),「因?yàn)橐恍┝谢貪L操作、像事務(wù)隔離級(jí)別那這樣加鎖、解鎖,是非常消耗性能的」。所以,Redis中執(zhí)行事務(wù)的流程只需要簡單的下面三個(gè)步驟:

  1.  開始事務(wù)(MULTI)
  2.  命令入隊(duì)
  3.  執(zhí)行事務(wù)(EXEC)、撤銷事務(wù)(DISCARD )

在Redis中事務(wù)的實(shí)現(xiàn)主要是通過如下的命令實(shí)現(xiàn)的:

命令 功能描述
MULTI 「事務(wù)開始的命令」,執(zhí)行該命令后,后面執(zhí)行的對Redis數(shù)據(jù)類型的「操作命令都會(huì)順序的放進(jìn)隊(duì)列中」,等待執(zhí)行EXEC命令后隊(duì)列中的命令才會(huì)被執(zhí)行
DISCARD 「放棄執(zhí)行隊(duì)列中的命令」,你可以理解為Mysql的回滾操作,「并且將當(dāng)前的狀態(tài)從事務(wù)狀態(tài)改為非事務(wù)狀態(tài)」
EXEC 執(zhí)行該命令后「表示順序執(zhí)行隊(duì)列中的命令」,執(zhí)行完后并將結(jié)果顯示在客戶端,「將當(dāng)前狀態(tài)從事務(wù)狀態(tài)改為非事務(wù)狀態(tài)」。若是執(zhí)行該命令之前有key被執(zhí)行WATCH命令并且又被其它客戶端修改,那么就會(huì)放棄執(zhí)行隊(duì)列中的所有命令,在客戶端顯示報(bào)錯(cuò)信息,若是沒有修改就會(huì)執(zhí)行隊(duì)列中的所有命令。
WATCH key 表示指定監(jiān)視某個(gè)key,「該命令只能在MULTI命令之前執(zhí)行」,如果監(jiān)視的key被其他客戶端修改,「EXEC將會(huì)放棄執(zhí)行隊(duì)列中的所有命令」
UNWATCH 「取消監(jiān)視之前通過WATCH 命令監(jiān)視的key」,通過執(zhí)行EXEC 、DISCARD 兩個(gè)命令之前監(jiān)視的key也會(huì)被取消監(jiān)視

以上就是一個(gè)Redis事務(wù)的執(zhí)行過程包含的命令,下面就來詳細(xì)的圍繞著這幾個(gè)命令進(jìn)行講解。

開始事務(wù)

MULTI 命令表示事務(wù)的開始,當(dāng)看到OK表示已經(jīng)進(jìn)入事務(wù)的狀態(tài):

該命令執(zhí)行后客戶端會(huì)將「當(dāng)前的狀態(tài)從非事務(wù)狀態(tài)修改為事務(wù)狀態(tài)」,這一狀態(tài)的切換是將客戶端的flags屬性中打開REDIS_MULTI來完成的,該命令可以理解關(guān)系型數(shù)據(jù)庫Mysql的BEGIN TRANCATION語句:

命令入隊(duì)

執(zhí)行完MULTI命令后,后面執(zhí)行的操作Redis五種類型的命令都會(huì)按順序的進(jìn)入命令隊(duì)列中,該部分也是真正的業(yè)務(wù)邏輯的部分。

Redis客戶端的命令執(zhí)行后若是當(dāng)前狀態(tài)處于事務(wù)狀態(tài)命令就會(huì)進(jìn)入隊(duì)列中,并且返回QUEUED字符串,表示該命令已經(jīng)進(jìn)入了命令隊(duì)列中,并且「事務(wù)隊(duì)列是以先進(jìn)先出(FIFO)的方式保存入隊(duì)的命令」的。

若是當(dāng)前狀態(tài)是非事務(wù)狀態(tài)就會(huì)立即執(zhí)行命令,并將結(jié)果返回客戶端。在事務(wù)狀態(tài)「執(zhí)行操作事務(wù)的命令就會(huì)被立即執(zhí)行」,如EXEC、DISCARD、UNWATCH。

結(jié)合上面的分析,Redis執(zhí)行命令的流程如下圖所示:

事務(wù)的命令隊(duì)列中有三個(gè)參數(shù)分別是:「要執(zhí)行的命令」、「命令的參數(shù)」、「參數(shù)的個(gè)數(shù)」。例如:通過執(zhí)行如下的命令: 

  1. redis> MULTI  
  2. OK  
  3. redis> SET name "黎杜"  
  4. QUEUED  
  5. redis> GET name  
  6. QUEUED 

那么對應(yīng)上面的隊(duì)列中三個(gè)參數(shù)如下表格所示:

執(zhí)行的命令 命令的參數(shù) 參數(shù)的個(gè)數(shù)
SET ["name", "黎杜"] 2
GET ["name"] 1

執(zhí)行事務(wù)

當(dāng)客戶端執(zhí)行EXEC命令的時(shí)候,上面的命令隊(duì)列就會(huì)被按照先進(jìn)先出的順序被執(zhí)行,當(dāng)然執(zhí)行的結(jié)果有成功有失敗,這個(gè)后面分析。

上面說到當(dāng)客戶端處于非事務(wù)的狀態(tài)命令發(fā)送到服務(wù)端會(huì)被立即執(zhí)行,若是客戶端處于事務(wù)狀態(tài)命令就會(huì)被放進(jìn)命令隊(duì)列。

命令入隊(duì)的時(shí)候,會(huì)按照順序進(jìn)入隊(duì)列,隊(duì)列以先進(jìn)先出的特點(diǎn)來執(zhí)行隊(duì)列中的命令。

若是客戶端處于事務(wù)狀態(tài),執(zhí)行的是EXEC、DISCARD、UNWATCH這些操作事務(wù)的命令,也會(huì)被立即執(zhí)行。

正常執(zhí)行

還是上面的例子,執(zhí)行如下的代碼: 

  1. redis> MULTI  
  2. OK  
  3. redis> SET name "黎杜"  
  4. QUEUED  
  5. redis> GET name  
  6. QUEUED 

所有的命令進(jìn)入了隊(duì)列,當(dāng)最后執(zhí)行EXEC,首先會(huì)執(zhí)行SET命令,然后執(zhí)行GET命令,并且執(zhí)行后的結(jié)果也會(huì)進(jìn)入一個(gè)隊(duì)列中保存,最后返回給客戶端:

回復(fù)的類型 回復(fù)的內(nèi)容
status code reply OK
bulk reply "黎杜"

所以最后你會(huì)在客戶端看到「OK、黎杜」,這樣的結(jié)果顯示,這個(gè)也就是一個(gè)事務(wù)成功執(zhí)行的過程。

至此一個(gè)事務(wù)就完整的執(zhí)行完成,并且此時(shí)客戶端也從事務(wù)狀態(tài)更改為非事務(wù)狀態(tài)。

放棄事務(wù)

當(dāng)然你也可以放棄執(zhí)行該事務(wù),只要你再次執(zhí)行DISCARD操作就會(huì)放棄執(zhí)行此次的事務(wù)。具體代碼如下所示: 

  1. redis> MULTI  
  2. OK  
  3. redis> SET name "黎杜"  
  4. QUEUED  
  5. redis> GET name  
  6. QUEUED  
  7. redis> DISCARD    // 放棄執(zhí)行事務(wù)  
  8. OK 

DISCARD命令取消一個(gè)事務(wù)的時(shí)候,就會(huì)將命令隊(duì)列清空,并且將客戶端的狀態(tài)從事務(wù)狀態(tài)修改為非事務(wù)的狀態(tài)。

「Redis的事務(wù)是不可重復(fù)的」,當(dāng)客戶端處于事務(wù)狀態(tài)的時(shí)候,再次向服務(wù)端發(fā)送MULTI命令時(shí),直接就會(huì)向客戶端返回錯(cuò)誤。

WATCH 命令

WATCH命令是在MULTI命令之前執(zhí)行的,表示監(jiān)視任意數(shù)量的key,與它對應(yīng)的命令就是UNWATCH命令,取消監(jiān)視的key。

WATCH命令有點(diǎn)「類似于樂觀鎖機(jī)制」,在事務(wù)執(zhí)行的時(shí)候,若是被監(jiān)視的任意一個(gè)key被更改,則隊(duì)列中的命令不會(huì)被執(zhí)行,直接向客戶端返回(nil)表示事務(wù)執(zhí)行失敗。

下面我們來演示一下WATCH命令的操作流程,具體實(shí)現(xiàn)代碼如下: 

  1. redis> WATCH num  
  2. OK  
  3. redis> MULTI  
  4. OK  
  5. redis> incrby num 10  
  6. QUEUED  
  7. redis> decrby num 1  
  8. QUEUED  
  9. redis> EXEC   // 執(zhí)行成功 

這個(gè)是WATCH命令的正常的操作流程,若是在其它的客戶端,修改了被監(jiān)視的任意key,就會(huì)放棄執(zhí)行該事務(wù),如下圖所示:

客戶端一 客戶端二
WATCH num  
MULTI  
incrby num 10 get num
  decrby num 1
EXEC  
執(zhí)行失敗,返回(nil)  

WATCH命令的底層實(shí)現(xiàn)中保存了watched_keys 字典,「字典的鍵保存的是監(jiān)視的key,值是一個(gè)鏈表,鏈表中的每個(gè)節(jié)點(diǎn)值保存的是監(jiān)視該key的客戶端」。

若是某個(gè)客戶端不再監(jiān)視某個(gè)key,該客戶端就會(huì)從鏈表中脫離。如client3,通過執(zhí)行UNWATCH命令,不再監(jiān)視key1:

錯(cuò)誤處理

上面說到Redis是沒有回滾機(jī)制的,那么執(zhí)行的過程,若是不小心敲錯(cuò)命令,Redis的命令發(fā)送到服務(wù)端沒有被立即執(zhí)行,所以是暫時(shí)發(fā)現(xiàn)不到該錯(cuò)誤。

那么在Redis中的錯(cuò)誤處理主要分為兩類:「語法錯(cuò)誤」、「運(yùn)行錯(cuò)誤」。下面主要來講解一下這兩類錯(cuò)誤的區(qū)別。

語法錯(cuò)誤

比如執(zhí)行命令的時(shí)候,命令的不存在或者錯(cuò)誤的敲錯(cuò)命令、參數(shù)的個(gè)數(shù)不對等都會(huì)導(dǎo)致語法錯(cuò)誤。

下面來演示一下,執(zhí)行下面的四個(gè)命令,前后的兩個(gè)命令是正確的,中間的兩個(gè)命令是錯(cuò)誤的,如下所示: 

  1. 127.0.0.1:6379> multi  
  2. OK  
  3. 127.0.0.1:6379> set num 1  
  4. QUEUED  
  5. 127.0.0.1:6379> set num  
  6. (error) ERR wrong number of arguments for 'set' command  
  7. 127.0.0.1:6379> ssset num 3  
  8. (error) ERR unknown command 'ssset'  
  9. 127.0.0.1:6379> set num 2  
  10. QUEUED  
  11. 127.0.0.1:6379> exec  
  12. (error) EXECABORT Transaction discarded because of previous errors. 

語法錯(cuò)誤是在Redis語法檢測的時(shí)候就能發(fā)現(xiàn)的,所以當(dāng)你執(zhí)行錯(cuò)誤命令的時(shí)候,也會(huì)即使的返回錯(cuò)誤的提示。

最后,即使命令進(jìn)入隊(duì)列,只要存在語法錯(cuò)誤,該隊(duì)列中的命令都不會(huì)被執(zhí)行,會(huì)直接向客戶端返回事務(wù)執(zhí)行失敗的提示。

運(yùn)行錯(cuò)誤

執(zhí)行時(shí)使用不同類型的操作命令操作不同數(shù)據(jù)類型就會(huì)出現(xiàn)運(yùn)行時(shí)錯(cuò)誤,這種錯(cuò)誤時(shí)Redis在不執(zhí)行命令的情況下,是無法發(fā)現(xiàn)的。 

  1. 127.0.0.1:6379> multi  
  2. OK  
  3. 127.0.0.1:6379> set num 3  
  4. QUEUED  
  5. 127.0.0.1:6379> sadd num 4  
  6. QUEUED  
  7. 127.0.0.1:6379> set num 6  
  8. QUEUED  
  9. 127.0.0.1:6379> exec  
  10. 1) OK  
  11. 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value  
  12. 3) OK  
  13. 127.0.0.1:6379> get num  
  14. "6" 

這樣就會(huì)導(dǎo)致,正確的命令被執(zhí)行,而錯(cuò)誤的命令不會(huì)不執(zhí)行,這也顯示出Redis的事務(wù)并不能保證數(shù)據(jù)的一致性,因?yàn)橹虚g出現(xiàn)了錯(cuò)誤,有些語句還是被執(zhí)行了。

這樣的結(jié)果只能程序員自己根據(jù)之前執(zhí)行的命令,自己一步一步正確的回退,所謂自己的爛攤子,自己收拾。

Redis事務(wù)與Mysql事務(wù)

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

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

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

既然沒有了原子性,數(shù)據(jù)的一致性也就無法保證,這些都需要程序員自己手動(dòng)去實(shí)現(xiàn)。

Reids在進(jìn)行事務(wù)的時(shí)候,不會(huì)被中斷知道事務(wù)的運(yùn)行結(jié)束,也具有一定的隔離性,并且Redis也能持久化數(shù)據(jù)。 

 

責(zé)任編輯:龐桂玉 來源: 數(shù)據(jù)庫開發(fā)
相關(guān)推薦

2020-03-27 16:27:03

Redis數(shù)據(jù)庫

2020-07-01 17:25:28

Redis數(shù)據(jù)庫內(nèi)存

2024-06-26 11:55:44

2020-09-15 10:25:13

Redis命令Java

2019-05-07 18:17:26

Redis服務(wù)器數(shù)據(jù)

2024-08-12 09:55:42

Redis二進(jìn)制數(shù)據(jù)

2019-04-09 09:22:32

Redis內(nèi)存緩存

2022-03-08 16:10:38

Redis事務(wù)機(jī)制

2021-11-03 11:58:44

分布式事務(wù)面試

2018-06-11 15:20:24

2021-11-29 10:55:11

線程池Java面試

2022-08-12 09:35:36

JavaScript面試

2019-05-15 16:45:13

SpringBoot面試題Java

2013-06-14 17:24:42

棱鏡門安全

2019-07-16 10:10:46

JavaScript數(shù)據(jù)類型

2021-03-04 09:20:20

數(shù)據(jù)Redis 架構(gòu)

2021-09-08 08:06:57

Redis原子性數(shù)據(jù)類型

2019-02-21 10:49:51

Redis持久化恢復(fù)

2017-12-18 17:21:56

AndroidJava內(nèi)存泄漏

2020-05-14 08:13:56

JDK命令Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 奇米超碰在线 | 99视频久 | 久久久久久蜜桃一区二区 | 九九综合九九 | 天天综合干| 精品一区二区久久久久久久网精 | 一级免费黄色 | 精品欧美乱码久久久久久 | 国产精品久久久久久久久免费樱桃 | 亚洲免费网 | 久久精品av麻豆的观看方式 | 最近最新中文字幕 | 天天躁天天操 | 久久综合国产精品 | 99精品网 | 成人国产精品久久 | 久久国产三级 | 久久人| 午夜av免费 | 国产精品精品视频 | 久久综合影院 | 亚洲视频欧美视频 | 国产精品久久久久久久久久久久冷 | 99精品欧美一区二区三区综合在线 | 免费观看成人鲁鲁鲁鲁鲁视频 | 99久久精品国产一区二区三区 | 国产精品久久久久久久久久免费 | 国产精品区二区三区日本 | 日韩高清成人 | 亚洲精品综合一区二区 | 欧美九九 | 97国产一区二区精品久久呦 | 国产久| 日本高清视频网站 | 日韩一区二区三区在线观看视频 | 国产在线播放一区二区三区 | 日韩精品色网 | 欧美一级全黄 | 久久久网| 亚洲天堂二区 | 亚洲黄色片免费观看 |