动态

详情 返回 返回

Redis支持事務嗎?瞭解Redis的持久化機制嗎? - 动态 详情

Redis 支持事務嗎?與關係型數據庫事務的區別?

Redis 支持事務,但它的事務與 MSQL中的事務有所不同,MSOL中的事務主要支持 ACID 的特性,而 Redis中的事務主要保證的是多個命令執行的原子性,即所有的命令在一個原子操作中執行,不會被打斷。還有一個很重要的點,就是 MySQL 中的事務是支持回滾的,而 Redis 中的事務是不支持回滾的。

Redis事務是指將多條命令加入隊列,一次批量執行多條命令,每條命令會按順序執行,事務執行過程中不會被其他客户端發來的命令所打斷。也就是説,Redis事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令。

Redis事務和關係型數據庫的事務不太一樣,它不保證原子性,也沒有隔離級別的概念。

事務不保證原子性,但是Redis命令本身是原子性的

  1. Redis事務沒有隔離級別的概念:批量操作在發送 EXEC 命令前被放入隊列緩存,並不會被實際執行,也就不存在事務裏的查詢要看到本事務的更新或其它事務的修改更新操作的問題。(Mysql裏的事務的語句不是放入隊列,而是直接執行)
  2. Redis不保證原子性:Redis中,單條命令是原子性執行的,但事務不保證原子性,且沒有回滾。事務中任意命令執行失敗,其餘的命令仍會被執行。

WATCH命令

WATCH命令可以監控一個或多個鍵,一旦其中有一個鍵被修改,之後的事務就不會執行(類似於樂觀鎖)。執行EXEC命令之後,就會自動取消監控。

127.0.0.1:6379> watch name
OK
127.0.0.1:6379> set name 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name 2
QUEUED
127.0.0.1:6379> set gender 1
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get gender
(nil)

比如上面的代碼中:

  1. watch name開啓了對name這個key的監控
  2. 修改name的值
  3. 開啓事務a
  4. 在事務a中設置了namegender的值
  5. 使用EXEC命令進提交事務
  6. 使用命令get gender發現不存在,即事務a沒有執行

使用UNWATCH可以取消WATCH命令對key的監控,所有監控鎖將會被取消。

Redis事務支持隔離性嗎?

Redis 是單進程程序,並且它保證在執行事務時,不會對事務進行中斷,事務可以運行直到執行完所有事務隊列中的命令為止。因此,Redis 的事務是總是帶有隔離性的。

Redis事務保證原子性嗎,支持回滾嗎?

Redis單條命令是原子性執行的,但事務不保證原子性,且沒有回滾。事務中任意命令執行失敗,其餘的命令仍會被執行。

Redis 的 Lua 腳本功能是什麼?如何使用?

Redis 的 Lua 腳本功能允許用户在 Redis 服務器端執行自定義的 Lua 腳本,以實現原子操作和複雜邏輯。其核心點包括:

  • 原子性:Lua 腳本的所有命令在執行過程中是原子的,避免了併發修改帶來的問題。
  • 減少網絡往返次數:通過在服務器端執行腳本,減少了客户端和服務器之間的網絡往返次數,提高了性能。
  • 複雜操作:可以在 Lua 腳本中執行復雜的邏輯,比如批量更新、條件更新等,超過了單個 Redis 命令的能力。

例如常見基於 Redis 實現分佈式鎖就需要結合 lua 腳本來實現。

lua 本身是不具備原子性的,但由於 Redis的命令是單線程執行的,它會把整個|ua 腳本作為一個命令執行,會阻塞其間接受到的其他命令,這就保證了 lua 腳本的原子性。

Redis的持久化了解嗎?

詳細可以查看:https://www.seven97.top/database/redis/03-strategy1-persistence.html

持久化就是把內存的數據寫到磁盤中,防止服務宕機導致內存數據丟失。

Redis支持兩種方式的持久化,一種是RDB的方式,一種是AOF的方式。前者會根據指定的規則定時將內存中的數據存儲在硬盤上,而後者在每次執行完命令後將命令記錄下來。Redis 4.0 新增了 RDB 和 AOF 的混合持久化機制,一般將兩者結合使用。

RDB方式

RDB是 Redis 默認的持久化方案。RDB持久化時會將內存中的數據寫入到磁盤中,在指定目錄下生成一個dump.rdb文件。Redis 重啓會加載dump.rdb文件恢復數據。

bgsave是主流的觸發 RDB 持久化的方式,執行過程如下:

  • 執行BGSAVE命令
  • Redis 父進程判斷當前是否存在正在執行的子進程,如果存在,BGSAVE命令直接返回。
  • 父進程執行fork操作創建子進程,fork操作過程中父進程會阻塞。
  • 父進程fork完成後,父進程繼續接收並處理客户端的請求,而子進程開始將內存中的數據寫進硬盤的臨時文件
  • 當子進程寫完所有數據後會用該臨時文件替換舊的 RDB 文件

Redis啓動時會讀取RDB快照文件,將數據從硬盤載入內存。通過 RDB 方式的持久化,一旦Redis異常退出,就會丟失最近一次持久化以後更改的數據。

觸發 RDB 持久化的方式:

  1. 手動觸發:用户執行SAVEBGSAVE命令。SAVE命令執行快照的過程會阻塞所有客户端的請求,應避免在生產環境使用此命令。BGSAVE命令可以在後台異步進行快照操作,快照的同時服務器還可以繼續響應客户端的請求,因此需要手動執行快照時推薦使用BGSAVE命令。

  2. 被動觸發

    • 根據配置規則進行自動快照,如SAVE 100 10,100秒內至少有10個鍵被修改則進行快照。
    • 如果從節點執行全量複製操作,主節點會自動執行BGSAVE生成 RDB 文件併發送給從節點。
    • 默認情況下執行shutdown命令時,如果沒有開啓 AOF 持久化功能則自動執行·BGSAVE·。

優點

  1. Redis 加載 RDB 恢復數據遠遠快於 AOF 的方式
  2. 使用單獨子進程來進行持久化,主進程不會進行任何 IO 操作,保證了 Redis 的高性能

缺點

  1. RDB方式數據無法做到實時持久化。因為BGSAVE每次運行都要執行fork操作創建子進程,屬於重量級操作,頻繁執行成本比較高。
  2. RDB 文件使用特定二進制格式保存,Redis 版本升級過程中有多個格式的 RDB 版本,存在老版本 Redis 無法兼容新版 RDB 格式的問題

Redis 在生成 RDB 文件時如何處理請求?

在 Redis 生成 RDB文件時是異步的(使用 bgsave 命令),採用了fork子進程的方式來進行快照操作,生成 RD8文件的過程由子進程執行,主進程維續處理客户端清求,所以可以保證 Redis在生成快照的過程中依然對外提供服務,不會影響正常請求。

生成 RDB 文件的時候,數據可以修改嗎?

當然可以。主進程會正常處理客户端的請求,進行數據的修改,但數據被修改還叫快照嗎?

此時就運用了寫時複製的技術。當主進程 fork 出一個子進程後,並不會把主進程的所有內存數據重新複製一份給子進程,而是讓主進程和子進程共享相同的內存頁面。

底層的實現僅僅複製了頁表,但映射的物理內存還是同一個。這樣做可以加快 fork 的速度,減少性能損耗(fork會阻塞主進程)。

AOF方式

AOF(append only file)持久化:以獨立日誌的方式記錄每次寫命令,Redis重啓時會重新執行AOF文件中的命令達到恢復數據的目的。AOF的主要作用是解決了數據持久化的實時性,AOF 是Redis持久化的主流方式。

默認情況下Redis沒有開啓AOF方式的持久化,可以通過appendonly參數啓用:appendonly yes。開啓AOF方式持久化後每執行一條寫命令,Redis就會將該命令寫進aof_buf緩衝區,AOF緩衝區根據對應的策略向硬盤做同步操作。

默認情況下系統每30秒會執行一次同步操作。為了防止緩衝區數據丟失,可以在Redis寫入AOF文件後主動要求系統將緩衝區數據同步到硬盤上。可以通過appendfsync參數設置同步的時機。

appendfsync always //每次寫入aof文件都會執行同步,最安全最慢,不建議配置
appendfsync everysec  //既保證性能也保證安全,建議配置
appendfsync no //由操作系統決定何時進行同步操作

接下來看一下 AOF 持久化執行流程:

  1. 所有的寫入命令會追加到 AOP 緩衝區中。
  2. AOF 緩衝區根據對應的策略向硬盤同步。
  3. 隨着 AOF 文件越來越大,需要定期對 AOF 文件進行重寫,達到壓縮文件體積的目的。AOF文件重寫是把Redis進程內的數據轉化為寫命令同步到新AOF文件的過程。
  4. 當 Redis 服務器重啓時,可以加載 AOF 文件進行數據恢復。

優點

  1. AOF可以更好的保護數據不丟失,可以配置 AOF 每秒執行一次fsync操作,如果Redis進程掛掉,最多丟失1秒的數據。
  2. AOF以append-only的模式寫入,所以沒有磁盤尋址的開銷,寫入性能非常高。

缺點

  1. 對於同一份文件AOF文件比RDB數據快照要大。
  2. 數據恢復比較慢。

RDF和AOF的區別?

  1. 記錄的數據不一樣:
    • RDB 快照就是記錄某一個瞬間的內存數據,記錄的是實際數據,而 AOF 文件記錄的是命令操作的日誌
    • AOF 文件的內容是操作命令;RDB 文件的內容是二進制數據
  2. 恢復數據和執行頻率:
    • RDB是全量快照,恢復數據更快,AOF則需要額外執行操作命令,相對更慢。
    • RDB是全量快照,不宜頻繁執行,而AOF數據文件更新比較及時,比RDB保存更完整的數據,這樣在數據恢復時能夠恢復儘量完整的數據,降低丟失數據的風險。因此發生故障時,RDB丟失的數據會比 AOF 持久化的方式更多
  3. 是否影響主進程
    • AOF的Always寫回策略是主進程執行的,總是調用fsync函數;Everysec異步執行,不影響主線程;No則redis不控制寫回,最終交給操作系統決定何時寫回;不影響主線程。
    • RDB可以將工作交給子進程來做,此時Redis主線程還可以繼續處理操作命令。

如果同時存在RDB文件和AOF文件,Redis會優先使用AOF文件進行數據恢復。

RDB和AOF如何選擇?

RDB 比 AOF 的數據恢復速度快,但是快照的頻率不好把握:

  • 如果頻率太低,兩次快照間一旦服務器發生宕機,就可能會比較多的數據丟失;
  • 如果頻率太高,頻繁寫入磁盤和創建子進程會帶來額外的性能開銷。

因此可以使用混合持久化,混合持久化就是混合使用 AOF 日誌和RDB

混合持久化工作在 AOF日誌重寫過程中:
會把 Redis 的持久化數據,以 RDB 的格式寫入到 AOF 文件的開頭,之後寫時複製時修改數據再以 AOF 的格式化追加的文件的末尾,寫入完成後再新的含有 RDB 格式和 AOF 格式的 AOF 文件替換舊的的 AOF 文件。

也就是説,使用了混合持久化,AOF 文件的前半部分是 RDB 格式的全量數據,後半部分是 AOF 格式的增量數據。

優點:

  • 混合持久化結合了 RDB 和 AOF 持久化的優點,開頭為 RDB 的格式,使得 Redis 可以更快的恢復數據,同時結合 AOF 的優點,減低了大量數據丟失的風險。

缺點:

  • AOF 文件中添加了 RDB 格式的內容,使得 AOF 文件的可讀性變得很差;
  • 兼容性差,如果開啓混合持久化,那麼此混合持久化 AOF 文件,就不能用在 Redis 4.0 之前版本了。

Add a new 评论

Some HTML is okay.