Redis事務(wù)與數(shù)據(jù)持久化方式
一、Redis 事務(wù)
1.1 事務(wù)本質(zhì)
一組命令的集合
1.2 數(shù)據(jù)庫(kù)事務(wù)與redis事務(wù)
1.2.1 數(shù)據(jù)庫(kù)事務(wù)
數(shù)據(jù)庫(kù)事務(wù)通過(guò)ACID(原子性、一致性、隔離性、持久性)來(lái)保證。
數(shù)據(jù)庫(kù)中除查詢操作以外,插入(Insert)、刪除(Delete)和更新(Update)這三種操作都會(huì)對(duì)數(shù)據(jù)造成影響,因?yàn)槭聞?wù)處理能夠保證一系列操作可以完全地執(zhí)行或者完全不執(zhí)行,因此在一個(gè)事務(wù)被提交以后,該事務(wù)中的任何一條SQL語(yǔ)句在被執(zhí)行的時(shí)候,都會(huì)生成一條撤銷(xiāo)日志(Undo Log)。
1.2.2 Redis事務(wù)
redis事務(wù)提供了一種“將多個(gè)命令打包, 然后一次性、按順序地執(zhí)行”的機(jī)制, 并且事務(wù)在執(zhí)行的期間不會(huì)主動(dòng)中斷 —— 服務(wù)器在執(zhí)行完事務(wù)中的所有命令之后, 才會(huì)繼續(xù)處理其他客戶端的其他命令。
Redis中一個(gè)事務(wù)從開(kāi)始到執(zhí)行會(huì)經(jīng)歷開(kāi)始事務(wù)(muiti)、命令入隊(duì)和執(zhí)行事務(wù)(exec)三個(gè)階段,事務(wù)中的命令在加入時(shí)都沒(méi)有被執(zhí)行,直到提交時(shí)才會(huì)開(kāi)始執(zhí)行(Exec)一次性完成。
1.2.2.1 兩種錯(cuò)誤不同處理方式
1)代碼語(yǔ)法錯(cuò)誤(編譯時(shí)異常)
發(fā)生代碼語(yǔ)法錯(cuò)誤時(shí),所有命令都不執(zhí)行。
2)代碼邏輯錯(cuò)誤(運(yùn)行時(shí)錯(cuò)誤)
發(fā)生代碼邏輯錯(cuò)誤時(shí),其他命令可以正常執(zhí)行 (該點(diǎn)不保證事務(wù)的原子性)
為什么redis不支持回滾來(lái)保證原子性
1.2.2.2 這種做法的優(yōu)點(diǎn):
- Redis 命令只會(huì)因?yàn)殄e(cuò)誤的語(yǔ)法而失?。ú⑶疫@些問(wèn)題不能在入隊(duì)時(shí)發(fā)現(xiàn)),或是命令用在了錯(cuò)誤類(lèi)型的鍵上面:這也就是說(shuō),從實(shí)用性的角度來(lái)說(shuō),失敗的命令是由編程錯(cuò)誤造成的,而這些錯(cuò)誤應(yīng)該在開(kāi)發(fā)的過(guò)程中被發(fā)現(xiàn),而不應(yīng)該出現(xiàn)在生產(chǎn)環(huán)境中。
- 因?yàn)椴恍枰獙?duì)回滾進(jìn)行支持,所以 Redis 的內(nèi)部可以保持簡(jiǎn)單且快速。
鑒于沒(méi)有任何機(jī)制能避免程序員自己造成的錯(cuò)誤, 并且這類(lèi)錯(cuò)誤通常不會(huì)在生產(chǎn)環(huán)境中出現(xiàn), 所以 Redis 選擇了更簡(jiǎn)單、更快速的無(wú)回滾方式來(lái)處理事務(wù)。
1.3 事務(wù)監(jiān)控
redis使用watch key監(jiān)控指定數(shù)據(jù),相當(dāng)于加樂(lè)觀鎖
watch保證事務(wù)只能在所有被監(jiān)視鍵都沒(méi)有被修改的前提下執(zhí)行, 如果這個(gè)前提不能滿足的話,事務(wù)就不會(huì)被執(zhí)行。
watch執(zhí)行流程:
二、數(shù)據(jù)持久化
Redis是一種內(nèi)存型數(shù)據(jù)庫(kù),一旦服務(wù)器進(jìn)程退出,數(shù)據(jù)庫(kù)的數(shù)據(jù)就會(huì)丟失,為了解決這個(gè)問(wèn)題Redis供了兩種持久化的方案,將內(nèi)存中的數(shù)據(jù)保存到磁盤(pán)中,避免數(shù)據(jù)的丟失兩種持久化方式:快照(RDB文件)和追加式文件(AOF文件),下面分別為大家介紹兩種方式的原理。
- RDB持久化方式會(huì)在一個(gè)特定的間隔保存那個(gè)時(shí)間點(diǎn)的數(shù)據(jù)快照。
- AOF持久化方式則會(huì)記錄每一個(gè)服務(wù)器收到的寫(xiě)操作。在服務(wù)啟動(dòng)時(shí),這些記錄的操作會(huì)逐條執(zhí)行從而重建出原來(lái)的數(shù)據(jù)。寫(xiě)操作命令記錄的格式跟Redis協(xié)議一致,以追加的方式進(jìn)行保存。
- Redis的持久化是可以禁用的,就是說(shuō)你可以讓數(shù)據(jù)的生命周期只存在于服務(wù)器的運(yùn)行時(shí)間里。
- 兩種方式的持久化是可以同時(shí)存在的,但是當(dāng)Redis重啟時(shí),AOF文件會(huì)被優(yōu)先用于重建數(shù)據(jù)。
2.1 RDB持久化
RDB持久化產(chǎn)生的文件是一個(gè)經(jīng)過(guò)壓縮的二進(jìn)制文件,這個(gè)文件可以被保存到硬盤(pán)中,可以通過(guò)這個(gè)文件還原數(shù)據(jù)庫(kù)的狀態(tài),它可以手動(dòng)執(zhí)行,也可以在redis.conf配置文件中配置,定時(shí)執(zhí)行。
2.1.1 工作原理
在進(jìn)行RDB時(shí),redis的主進(jìn)程不會(huì)做io操作,會(huì)fork一個(gè)子進(jìn)程來(lái)完成該操作:
1)Redis 調(diào)用forks。同時(shí)擁有父進(jìn)程和子進(jìn)程。
2)子進(jìn)程將數(shù)據(jù)集寫(xiě)入到一個(gè)臨時(shí) RDB 文件中。
3)當(dāng)子進(jìn)程完成對(duì)新 RDB 文件的寫(xiě)入時(shí),Redis 用新 RDB 文件替換原來(lái)的 RDB 文件,并刪除舊的 RDB 文件。
這種工作方式使得 Redis 可以從寫(xiě)時(shí)復(fù)制(copy-on-write)機(jī)制中獲益(因?yàn)槭鞘褂米舆M(jìn)程進(jìn)行寫(xiě)操作,而父進(jìn)程依然可以接收來(lái)自客戶端的請(qǐng)求)
2.1.2 觸發(fā)機(jī)制
在Redis中RDB持久化的觸發(fā)分為兩種:自己手動(dòng)觸發(fā)與自動(dòng)觸發(fā)。
2.1.2.1 手動(dòng)觸發(fā)
1)save
save命令是同步的命令,會(huì)占用主進(jìn)程,會(huì)造成阻塞,阻塞所有客戶端的請(qǐng)求
2)bgsave
bgsave是異步進(jìn)行,進(jìn)行持久化的時(shí)候,redis還可以將繼續(xù)響應(yīng)客戶端請(qǐng)求
bgsave和save對(duì)比:
命令 | save | bgsave |
IO類(lèi)型 | 同步 | 異步 |
阻塞 | 是 | 是(阻塞發(fā)生在fock(),通常非常快) |
復(fù)雜度 | O(n) | O(n) |
優(yōu)點(diǎn) | 不會(huì)消耗額外的內(nèi)存 | 不阻塞客戶端命令 |
缺點(diǎn) | 阻塞客戶端命令 | 需要fock子進(jìn)程,消耗內(nèi)存 |
2.1.2.2 自動(dòng)觸發(fā)
觸發(fā)條件:
save自動(dòng)觸發(fā)配置,見(jiàn)下面配置,滿足m秒內(nèi)修改n次key,觸發(fā)rdb
# 時(shí)間策略 save m n m秒內(nèi)修改n次key,觸發(fā)rdb save 900 1 save 300 10 save 60 10000 # 文件名稱 dbfilename dump.rdb # 文件保存路徑 dir /home/work/app/redis/data/ # 如果持久化出錯(cuò),主進(jìn)程是否停止寫(xiě)入 stop-writes-on-bgsave-error yes # 是否壓縮 rdbcompression yes # 導(dǎo)入時(shí)是否檢查 rdbchecksum yes
1)從節(jié)點(diǎn)全量復(fù)制時(shí),主節(jié)點(diǎn)發(fā)送rdb文件給從節(jié)點(diǎn)完成復(fù)制操作,主節(jié)點(diǎn)會(huì)觸發(fā)bgsave命令;
2)執(zhí)行flushall命令,會(huì)觸發(fā)rdb
3)退出redis,且沒(méi)有開(kāi)啟aof時(shí)
2.1.3 RDB優(yōu)缺點(diǎn)
2.1.3.1 優(yōu)點(diǎn):
1)RDB 的內(nèi)容為二進(jìn)制的數(shù)據(jù),占用內(nèi)存更小,更緊湊,更適合做為備份文件;
2)RDB 對(duì)災(zāi)難恢復(fù)非常有用,它是一個(gè)緊湊的文件,可以更快的傳輸?shù)竭h(yuǎn)程服務(wù)器進(jìn)行 Redis 服務(wù)恢復(fù);
3)RDB 可以更大程度的提高 Redis 的運(yùn)行速度,因?yàn)槊看纬志没瘯r(shí) Redis 主進(jìn)程都會(huì) fork() 一個(gè)子進(jìn)程,進(jìn)行數(shù)據(jù)持久化到磁盤(pán),Redis 主進(jìn)程并不會(huì)執(zhí)行磁盤(pán) I/O 等操作;
4)與 AOF 格式的文件相比,RDB 文件可以更快的重啟。
2.1.3.2 缺點(diǎn):
1)因?yàn)?RDB 只能保存某個(gè)時(shí)間間隔的數(shù)據(jù),如果中途 Redis 服務(wù)被意外終止了,則會(huì)丟失一段時(shí)間內(nèi)的 Redis 數(shù)據(jù)。
2)RDB 需要經(jīng)常 fork() 才能使用子進(jìn)程將其持久化在磁盤(pán)上。如果數(shù)據(jù)集很大,fork() 可能很耗時(shí),并且如果數(shù)據(jù)集很大且 CPU 性能不佳,則可能導(dǎo)致 Redis 停止為客戶端服務(wù)幾毫秒甚至一秒鐘。
2.2 AOF持久化
以日志的形式來(lái)記錄每個(gè)寫(xiě)的操作,將Redis執(zhí)行過(guò)的所有指令記錄下來(lái)(讀操作不記錄),只許追加文件但不可以改寫(xiě)文件,redis啟動(dòng)之初會(huì)讀取該文件重新構(gòu)建數(shù)據(jù),換言之,redis重啟的話就根據(jù)日志文件的內(nèi)容將寫(xiě)指令從前到后執(zhí)行一次以完成數(shù)據(jù)的恢復(fù)工作。
2.2.1 AOF配置項(xiàng)
# 默認(rèn)不開(kāi)啟aof 而是使用rdb的方式 appendonly no # 默認(rèn)文件名 appendfilename "appendonly.aof" # 每次修改都會(huì)sync 消耗性能 # appendfsync always # 每秒執(zhí)行一次 sync 可能會(huì)丟失這一秒的數(shù)據(jù) appendfsync everysec # 不執(zhí)行 sync ,這時(shí)候操作系統(tǒng)自己同步數(shù)據(jù),速度最快 # appendfsync no
AOF的整個(gè)流程大體來(lái)看可以分為兩步,一步是命令的實(shí)時(shí)寫(xiě)入(如果是appendfsync everysec 配置,會(huì)有1s損耗),第二步是對(duì)aof文件的重寫(xiě)。
2.2.2 AOF 重寫(xiě)機(jī)制
隨著Redis的運(yùn)行,AOF的日志會(huì)越來(lái)越長(zhǎng),如果實(shí)例宕機(jī)重啟,那么重放整個(gè)AOF將會(huì)變得十分耗時(shí),而在日志記錄中,又有很多無(wú)意義的記錄,比如我現(xiàn)在將一個(gè)數(shù)據(jù) incr一千次,那么就不需要去記錄這1000次修改,只需要記錄最后的值即可。所以就需要進(jìn)行 AOF 重寫(xiě)。
Redis 提供了bgrewriteaof指令用于對(duì)AOF日志進(jìn)行重寫(xiě),該指令運(yùn)行時(shí)會(huì)開(kāi)辟一個(gè)子進(jìn)程對(duì)內(nèi)存進(jìn)行遍歷,然后將其轉(zhuǎn)換為一系列的 Redis 的操作指令,再序列化到一個(gè)日志文件中。完成后再替換原有的AOF文件,至此完成。
同樣的也可以在redis.config中對(duì)重寫(xiě)機(jī)制的觸發(fā)進(jìn)行配置:
通過(guò)將no-appendfsync-on-rewrite設(shè)置為yes,開(kāi)啟重寫(xiě)機(jī)制;auto-aof-rewrite-percentage 100意為比上次從寫(xiě)后文件大小增長(zhǎng)了100%再次觸發(fā)重寫(xiě);
auto-aof-rewrite-min-size 64mb意為當(dāng)文件至少要達(dá)到64mb才會(huì)觸發(fā)制動(dòng)重寫(xiě)。
2.2.3 觸發(fā)方式
在Redis中AOF持久化的觸發(fā)也分為兩種:自己手動(dòng)觸發(fā)與自動(dòng)觸發(fā)。
2.2.3.1 手動(dòng)觸發(fā)
bgrewriteaof
2.2.3.2 自動(dòng)觸發(fā)
就是根據(jù)配置規(guī)則來(lái)觸發(fā),當(dāng)然自動(dòng)觸發(fā)的整體時(shí)間還跟Redis的定時(shí)任務(wù)頻率有關(guān)系。
2.2.4 AOF的優(yōu)缺點(diǎn)
2.2.4.1 優(yōu)點(diǎn)
1)數(shù)據(jù)安全
aof 持久化可以配置 appendfsync 屬性,有 always,每進(jìn)行一次 命令操作就記錄到 aof 文件中一次。
2)解決數(shù)據(jù)一致性問(wèn)題。
通過(guò) append 模式寫(xiě)文件,即使中途服務(wù)器宕機(jī),可以通過(guò) redis-check-aof 工具解決數(shù)據(jù)一致性問(wèn)題。
3)AOF 機(jī)制的 rewrite 模式。
AOF 文件沒(méi)被 rewrite 之前(文件過(guò)大時(shí)會(huì)對(duì)命令 進(jìn)行合并重寫(xiě)),可以刪除其中的某些命令(比如誤操作的 flushall))
2.2.4.2 缺點(diǎn)
1)AOF 文件比 RDB 文件大,且恢復(fù)速度慢。
2)數(shù)據(jù)集大的時(shí)候,比 rdb 啟動(dòng)效率低。
2.3 rdb與aof對(duì)比
比較項(xiàng) | RDB | AOF |
啟動(dòng)優(yōu)先級(jí) | 低 | 高 |
體積 | 小 | 大 |
恢復(fù)速度 | 快 | 慢 |
數(shù)據(jù)安全性 | 性丟數(shù)據(jù) | 根據(jù)策略決定 |
總結(jié)
RDB基于快照方式在一個(gè)特定的間隔保存那個(gè)時(shí)間點(diǎn)的數(shù)據(jù),備份數(shù)據(jù)相對(duì)較小,恢復(fù)速度較塊,但是可能會(huì)發(fā)生數(shù)據(jù)丟失;AOF持久化方式則會(huì)記錄每一個(gè)服務(wù)器收到的寫(xiě)操作,備份文件體積較大,恢復(fù)速度較慢,但是這種方式制定一定的策略,不會(huì)丟失數(shù)據(jù),相對(duì)來(lái)說(shuō)數(shù)據(jù)安全性要比RDB高。
在真實(shí)的企業(yè)生產(chǎn)環(huán)境中,Redis數(shù)據(jù)備份策略,一般是同時(shí)開(kāi)啟RDB和AOF兩種備份方式,盡可能提高企業(yè)安全性的同時(shí),也可以針對(duì)某個(gè)時(shí)間點(diǎn)基于數(shù)據(jù)快照快速恢復(fù)數(shù)據(jù)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用RediSearch實(shí)現(xiàn)在Redis中全文檢索
RediSearch?是?Redis?的一個(gè)插件,它為?Redis?數(shù)據(jù)庫(kù)添加了全文搜索和查詢功能,使開(kāi)發(fā)人員能夠在?Redis?中高效地執(zhí)行全文檢索操作,下面我們就來(lái)看看是具體如何使用的吧2023-08-08詳解Redis如何優(yōu)雅地實(shí)現(xiàn)接口防刷
這篇文章主要為大家詳細(xì)介紹了Redis優(yōu)雅地實(shí)現(xiàn)接口防刷的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03redis.conf中使用requirepass不生效的原因及解決方法
本文主要介紹了如何啟用requirepass,以及啟用requirepass為什么不會(huì)生效,從代碼層面分析了不生效的原因,以及解決方法,需要的朋友可以參考下2023-07-07一文詳細(xì)介紹Redis7持久化機(jī)制RDB和AOF
這篇文章主要給大家分享一下Redis的數(shù)據(jù)持久化方式,Reids是一個(gè)高性能的緩存中間件,它的高性能是因?yàn)樗腔趦?nèi)存的,我們知道直接操縱內(nèi)存是比較快的,所以當(dāng)機(jī)器發(fā)生宕機(jī),那么數(shù)據(jù)就會(huì)完全丟失,所以本文詳細(xì)介紹Redis7持久化機(jī)制RDB和AOF2023-07-07Redis數(shù)據(jù)結(jié)構(gòu)類(lèi)型示例解析
這篇文章主要為大家介紹了Redis數(shù)據(jù)結(jié)構(gòu)類(lèi)型示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Redis監(jiān)控工具RedisInsight安裝與使用
這篇文章主要為大家介紹了Redis監(jiān)控工具RedisInsight的安裝步驟與使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03基于Redis實(shí)現(xiàn)共享Session登錄的實(shí)現(xiàn)
本文主要介紹了基于Redis實(shí)現(xiàn)共享Session登錄的實(shí)現(xiàn),包括發(fā)送短信驗(yàn)證碼、短信驗(yàn)證碼登錄和注冊(cè)、以及登錄狀態(tài)校驗(yàn)的流程,具有一定的參考價(jià)值,感興趣的可以了解一下2025-03-03如何利用 Redis 實(shí)現(xiàn)接口頻次限制
這篇文章主要介紹了如何利用 Redis 實(shí)現(xiàn)接口頻次限制,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02