日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 架構(gòu)師社區(qū)
[導(dǎo)讀]?騰訊面試官:「數(shù)據(jù)庫事務(wù)機(jī)制了解么?」「內(nèi)心獨白:小意思,不就ACID嘛,轉(zhuǎn)眼一想,我面試的可是技術(shù)專家,不會這么簡單的問題吧」程許遠(yuǎn):「balabala……極其自信且從容淡定的說了一通。」?騰訊面試官:「Redis的事務(wù)了解么?它的事務(wù)機(jī)制能實現(xiàn)ACID屬性么?」程許遠(yuǎn):「撓...


?騰訊面試官:「數(shù)據(jù)庫事務(wù)機(jī)制了解么?」

「內(nèi)心獨白:小意思,不就 ACID 嘛,轉(zhuǎn)眼一想,我面試的可是技術(shù)專家,不會這么簡單的問題吧」

程許遠(yuǎn):「balabala…… 極其自信且從容淡定的說了一通。」

?騰訊面試官:「Redis 的事務(wù)了解么?它的事務(wù)機(jī)制能實現(xiàn) ACID 屬性么?」

程許遠(yuǎn):「撓頭,這個……我知道 lua 腳本能實現(xiàn)事務(wù)…」

騰訊面試官:「好的,回去等通知吧?!?/p>
?碼哥,我跟著你學(xué)習(xí)了 《Redis 系列》斬獲了很多 offer,沒想到最后敗在了 「Redis 如何實現(xiàn)事務(wù)?」這個問題上。

我們來一步步分析:

  1. 什么是事務(wù) ACID?
  2. Redis 如何實現(xiàn)事務(wù)?
  3. Redis 的事務(wù)能實現(xiàn)哪些屬性?
  4. Lua 腳本實現(xiàn)。

什么是事務(wù)的 ACID

鬼吹燈之《云南蟲谷》中的摸金校尉有句話叫「合則生,分則死」,為了尋找雮塵珠他們?nèi)朔止っ鞔_、齊心協(xié)力共進(jìn)退方可成功。

事務(wù)(Transaction)是并發(fā)控制單位,一個操作序列組合而成,這些操作要么都執(zhí)行,要么都不執(zhí)行。

「是一個不可分割的工作單位」。

事務(wù)在執(zhí)行時,會提供專門的屬性保證:

  • 原子性(Atomicity):一個事務(wù)的多個操作必須完成,或者都不完成(ps:MySQL 的原子性靠什么實現(xiàn)呢?歡迎留言區(qū)評論);

  • 一致性(Consistency):事務(wù)執(zhí)行結(jié)束后,數(shù)據(jù)庫的完整性約束沒有被破壞,事務(wù)執(zhí)行的前后順序都是合法數(shù)據(jù)狀態(tài)。

    數(shù)據(jù)庫的完整性約束包括但不限于:

    • 實體完整性(如行的主鍵存在且唯一);
    • 列完整性(如字段的類型、大小、長度要符合要求)
    • 外鍵約束;
    • 用戶自定義完整性(如轉(zhuǎn)賬前后,兩個賬戶余額的和應(yīng)該不變)。
  • 隔離性(Isolation):事務(wù)內(nèi)部的操作與其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個事務(wù)之間不能互相干擾。

    講究的是不同事務(wù)之間的相互影響,嚴(yán)格的隔離性對應(yīng)隔離級別中的可串行化(Serializable)。

  • 持久性(Durability):事務(wù)一旦提交,所有的修改將永久的保存到數(shù)據(jù)庫中,即使系統(tǒng)崩潰重啟后數(shù)據(jù)也不會丟失。

?碼哥,了解了 ACID 的具體要求后,Redis 是如何實現(xiàn)事務(wù)機(jī)制呢?

Redis 如何實現(xiàn)事務(wù)

MULTI、EXEC、DISCARD 和 WATCH 命令是 Redis 實現(xiàn)事務(wù)的的基礎(chǔ)。

Redis 事務(wù)的執(zhí)行過程包含三個步驟:

  1. 開啟事務(wù);
  2. 命令入隊;
  3. 執(zhí)行事務(wù)或丟棄;

顯式開啟一個事務(wù)

客戶端通過 MULTI 命令顯式地表示開啟一個事務(wù),隨后的命令將排隊緩存,并不會實際執(zhí)行。

命令入隊

客戶端把事務(wù)中的要執(zhí)行的一系列指令發(fā)送到服務(wù)端。

需要注意的是,雖然指令發(fā)送到服務(wù)端,但是 Redis 實例只是把這一系列指令暫存在一個命令隊列中,并不會立刻執(zhí)行。

執(zhí)行事務(wù)或丟棄

客戶端向服務(wù)端發(fā)送提交或者丟棄事務(wù)的命令,讓 Redis 執(zhí)行第二步中發(fā)送的具體指令或者清空隊列命令,放棄執(zhí)行。

Redis 只需在調(diào)用 EXEC 時,即可安排隊列命令執(zhí)行。

也可通過 DISCARD 丟棄第二步中保存在隊列中的命令。

Redis 事務(wù)案例

通過在線調(diào)試網(wǎng)站執(zhí)行我們的樣例代碼:https://try.redis.io

正常執(zhí)行

通過 MULTIEXEC 執(zhí)行一個事務(wù)過程:

#?開啟事務(wù)
>?MULTI
OK
#?開始定義一些列指令
>?SET?“公眾號:碼哥字節(jié)”?"粉絲?100?萬"
QUEUED
>?SET?"order"?"30"
QUEUED
>?SET?"文章數(shù)"?666
QUEUED
>?GET?"文章數(shù)"
QUEUED
#?實際執(zhí)行事務(wù)
>?EXEC
1)?OK
2)?OK
3)?OK
4)?"666"
我們看到每個讀寫指令執(zhí)行后的返回結(jié)果都是 QUEUED,表示謝謝操作都被暫存到了命令隊列,還沒有實際執(zhí)行。

當(dāng)執(zhí)行了 EXEC 命令,就可以看到具體每個指令的響應(yīng)數(shù)據(jù)。

放棄事務(wù)

通過 MULTIDISCARD丟棄隊列命令:

#?初始化訂單數(shù)
>?SET?"order:mobile"?100
OK
#?開啟事務(wù)
>?MULTI
OK
#?訂單?-?1
>?DECR?"order:mobile"
QUEUED
#?丟棄丟列命令
>?DISCARD
OK
#?數(shù)據(jù)沒有被修改
>?GET?"order:mobile"
"100"
?碼哥,Redis 的事務(wù)能保證 ACID 特性么?

這個問題問得好,我們一起來分析下。

Redis 事務(wù)滿足 ACID?

Redis 事務(wù)可以一次執(zhí)行多個命令, 并且?guī)в幸韵氯齻€重要的保證:

  1. 批量指令在執(zhí)行 EXEC 命令之前會放入隊列暫存;
  2. 收到 EXEC 命令后進(jìn)入事務(wù)執(zhí)行,事務(wù)中任意命令執(zhí)行失敗,其余的命令依然被執(zhí)行;
  3. 事務(wù)執(zhí)行過程中,其他客戶端提交的命令不會插入到當(dāng)前命令執(zhí)行的序列中。

原子性

?碼哥,如果事務(wù)執(zhí)行過程中發(fā)生錯誤了,原子性能保證么?

在事務(wù)期間,可能遇到兩種命令錯誤:

  • 在執(zhí)行 EXEC 命令前,發(fā)送的指令本身就錯誤。如下:
    • 參數(shù)數(shù)量錯誤;
    • 命令名稱錯誤,使用了不存在的命令;
    • 內(nèi)存不足(Redis 實例使用 maxmemory指令配置內(nèi)存限制)。
  • 在執(zhí)行 EXEC 命令后,命令可能會失敗。例如,命令和操作的數(shù)據(jù)類型不匹配(對 String 類型 的 value 執(zhí)行了 List 列表操作);
  • 在執(zhí)行事務(wù)的 EXEC 命令時。Redis 實例發(fā)生了故障導(dǎo)致事務(wù)執(zhí)行失敗。

EXEC 執(zhí)行前報錯

在命令入隊時,Redis 就會報錯并且記錄下這個錯誤。

此時,我們還能繼續(xù)提交命令操作。

等到執(zhí)行了 EXEC命令之后,Redis 就會拒絕執(zhí)行所有提交的命令操作,返回事務(wù)失敗的結(jié)果。

這樣一來,事務(wù)中的所有命令都不會再被執(zhí)行了,保證了原子性。

如下是指令入隊發(fā)生錯誤,導(dǎo)致事務(wù)失敗的例子:

#開啟事務(wù)
>?MULTI
OK
#發(fā)送事務(wù)中的第一個操作,但是Redis不支持該命令,返回報錯信息
127.0.0.1:6379>?PUT?order?6
(error)?ERR?unknown?command?`PUT`,?with?args?beginning?with:?`order`,?`6`,
#發(fā)送事務(wù)中的第二個操作,這個操作是正確的命令,Redis把該命令入隊
>?DECR?b:stock
QUEUED
#實際執(zhí)行事務(wù),但是之前命令有錯誤,所以Redis拒絕執(zhí)行
>?EXEC
(error)?EXECABORT?Transaction?discarded?because?of?previous?errors.

EXEC 執(zhí)行后報錯

事務(wù)操作入隊時,命令和操作的數(shù)據(jù)類型不匹配,但 Redis 實例沒有檢查出錯誤。

但是,在執(zhí)行完 EXEC 命令以后,Redis 實際執(zhí)行這些指令,就會報錯。

敲黑板了:Redis 雖然會對錯誤指令報錯,但是事務(wù)依然會把正確的命令執(zhí)行完,這時候事務(wù)的原子性就無法保證了!

?碼哥,為什么 Redis 不支持回滾?

其實,Redis 中并沒有提供回滾機(jī)制。雖然 Redis 提供了 DISCARD 命令。

但是,這個命令只能用來主動放棄事務(wù)執(zhí)行,把暫存的命令隊列清空,起不到回滾的效果。

EXEC 執(zhí)行時,發(fā)生故障

如果 Redis 開啟了 AOF 日志,那么,只會有部分的事務(wù)操作被記錄到 AOF 日志中。

我們需要使用 redis-check-aof 工具檢查 AOF 日志文件,這個工具可以把未完成的事務(wù)操作從 AOF 文件中去除。

這樣一來,我們使用 AOF 恢復(fù)實例后,事務(wù)操作不會再被執(zhí)行,從而保證了原子性。

簡單總結(jié):

  • 命令入隊時就報錯,會放棄事務(wù)執(zhí)行,保證原子性;
  • 命令入隊時沒報錯,實際執(zhí)行時報錯,不保證原子性;
  • EXEC 命令執(zhí)行時實例故障,如果開啟了 AOF 日志,可以保證原子性。

一致性

一致性會受到錯誤命令、實例故障發(fā)生時機(jī)的影響,按照命令出錯實例故障兩個維度的發(fā)生時機(jī),可以分三種情況分析。

EXEC 執(zhí)行前,入隊報錯

事務(wù)會被放棄執(zhí)行,所以可以保證一致性。

EXEC 執(zhí)行后,實際執(zhí)行時報錯

有錯誤的執(zhí)行不會執(zhí)行,正確的指令可以正常執(zhí)行,一致性可以保證。

EXEC 執(zhí)行時,實例故障

實例故障后會進(jìn)行重啟,這就和數(shù)據(jù)恢復(fù)的方式有關(guān)了,我們要根據(jù)實例是否開啟了 RDB 或 AOF 來分情況討論下。

如果我們沒有開啟 RDB 或 AOF,那么,實例故障重啟后,數(shù)據(jù)都沒有了,數(shù)據(jù)庫是一致的。

如果我們使用了 RDB 快照,因為 RDB 快照不會在事務(wù)執(zhí)行時執(zhí)行。

所以,事務(wù)命令操作的結(jié)果不會被保存到 RDB 快照中,使用 RDB 快照進(jìn)行恢復(fù)時,數(shù)據(jù)庫里的數(shù)據(jù)也是一致的。

如果我們使用了 AOF 日志,而事務(wù)操作還沒有被記錄到 AOF 日志時,實例就發(fā)生了故障,那么,使用 AOF 日志恢復(fù)的數(shù)據(jù)庫數(shù)據(jù)是一致的。

如果只有部分操作被記錄到了 AOF 日志,我們可以使用 redis-check-aof 清除事務(wù)中已經(jīng)完成的操作,數(shù)據(jù)庫恢復(fù)后也是一致的。

隔離性

事務(wù)執(zhí)行又可以分成命令入隊(EXEC 命令執(zhí)行前)和命令實際執(zhí)行(EXEC 命令執(zhí)行后)兩個階段。

所以在并發(fā)執(zhí)行的時候我們針對這兩個階段分兩種情況分析:

  1. 并發(fā)操作在 EXEC 命令前執(zhí)行,隔離性需要通過 WATCH 機(jī)制保證;
  2. 并發(fā)操作在 EXEC 命令之后,隔離性可以保證。
?碼哥,什么是 WATCH 機(jī)制?

我們重點來看第一種情況:一個事務(wù)的 EXEC 命令還沒有執(zhí)行時,事務(wù)的命令操作是暫存在命令隊列中的。

此時,如果有其它的并發(fā)操作,同樣的 key 被修改,需要看事務(wù)是否使用了 WATCH 機(jī)制。

WATCH 機(jī)制的作用是:在事務(wù)執(zhí)行前,監(jiān)控一個或多個鍵的值變化情況,當(dāng)事務(wù)調(diào)用 EXEC 命令執(zhí)行時,WATCH 機(jī)制會先檢查監(jiān)控的鍵是否被其它客戶端修改了。

如果修改了,就放棄事務(wù)執(zhí)行,避免事務(wù)的隔離性被破壞。

同時,客戶端可以再次執(zhí)行事務(wù),此時,如果沒有并發(fā)修改事務(wù)數(shù)據(jù)的操作了,事務(wù)就能正常執(zhí)行,隔離性也得到了保證。

騰訊二面:Redis?事務(wù)支持?ACID?么?
沒有 WATCH

如果沒有 WATCH 機(jī)制, 在 EXEC 命令執(zhí)行前的并發(fā)操作對數(shù)據(jù)讀寫。

當(dāng)執(zhí)行 EXEC 的時候,事務(wù)內(nèi)部要操作的數(shù)據(jù)已經(jīng)改變,Redis 并沒有做到事務(wù)之間的隔離。

騰訊二面:Redis?事務(wù)支持?ACID?么?
并發(fā)操作在 EXEC 之后接收執(zhí)行

至于第二種情況,因為 Redis 是用單線程執(zhí)行命令,而且,EXEC 命令執(zhí)行后,Redis 會保證先把命令隊列中的所有命令執(zhí)行完再執(zhí)行之后的指令。

所以,在這種情況下,并發(fā)操作不會破壞事務(wù)的隔離性。

騰訊二面:Redis?事務(wù)支持?ACID?么?

持久性

如果 Redis 沒有使用 RDB 或 AOF,那么事務(wù)的持久化屬性肯定得不到保證。

如果 Redis 使用了 RDB 模式,那么,在一個事務(wù)執(zhí)行后,而下一次的 RDB 快照還未執(zhí)行前,如果發(fā)生了實例宕機(jī),數(shù)據(jù)丟失,這種情況下,事務(wù)修改的數(shù)據(jù)也是不能保證持久化的。

如果 Redis 采用了 AOF 模式,因為 AOF 模式的三種配置選項 no、everysec 和 always 都會存在數(shù)據(jù)丟失的情況。

所以,事務(wù)的持久性屬性也還是得不到保證。

不管 Redis 采用什么持久化模式,事務(wù)的持久性屬性是得不到保證的。

總結(jié)

  • Redis 具備了一定的原子性,但不支持回滾。
  • Redis 具備 ACID 中一致性的概念。點)
  • Redis 具備隔離性。
  • Redis 無法保證持久性。
Redis 的事務(wù)機(jī)制可以保證一致性和隔離性,但是無法保證持久性。

不過,因為 Redis 本身是內(nèi)存數(shù)據(jù)庫,持久性并不是一個必須的屬性,我們更加關(guān)注的還是原子性、一致性和隔離性這三個屬性。

原子性的情況比較復(fù)雜,當(dāng)事務(wù)中使用的命令語法有誤時,原子性得不到保證,在其它情況下,事務(wù)都可以原子性執(zhí)行。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機(jī)驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機(jī)驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉