Redis 2/2
- 12 持久化—RDB
- 12.1 介紹
- 12.2 Fork
- 12.3 相關檔案及配置
- 12.4 恢復
- 12.5 優缺點
- 13 持久化—AOF
- 13.1 介紹
- 13.2 相關檔案及配置
- 13.3 AOF 的開啟、修復和恢復
- 13.4 AOF 的持久化流程
- 13.5 優缺點
- 13.6 RDB 與 AOF 用哪個?
- 14 主從復制
- 14.1 介紹
- 14.2 配置
- 14.3 一主二從
- 14.4 反客為主
- 14.5 薪火相傳
- 14.6 哨兵模式
- 15 集群
- 15.1 介紹
- 15.2 配置
- 15.3 原理及命令
- 15.4 Jedis 操作集群的 JedisCluster
- 15.5 集群的優缺點
12 持久化—RDB
12.1 介紹
-
RDB,Redis DataBase,在指定的時間間隔內將記憶體中的資料集快照(即Snapshot 快照)寫入磁盤, 恢復時直接將快照檔案讀到記憶體中,
-
Redis 會單獨創建(fork)一個子行程來進行持久化,先將資料寫入到 一個臨時檔案中,在持久化程序都結束時,再用這個臨時檔案替換上次持久化的檔案, 整個程序中,主行程是不進行任何IO操作的,這就確保了極高的性能,如果需要進行大規模資料的恢復,且對于資料恢復的完整性要求不是非常高,那么 RDB 方式要比 AOF 方式更加的高效,
-
RDB 的缺點是最后一次持久化的資料可能丟失,
-
RDB 默認開啟,
12.2 Fork
- Fork 的作用是復制一個與當前行程一樣的行程,新行程的所有資料(變數、環境變數、程式計數器等) 數值都和原行程一致,但是是一個全新的行程,并作為原行程的子行程
- 在 Linux 程式中,fork() 會產生一個和父行程完全相同的子行程,但子行程在此后多會被 exec 系統呼叫,出于效率考慮,Linux 中引入了“寫時復制技術”,
- 一般情況父行程和子行程會共用同一段物理記憶體,只有行程空間各段的內容要發生變化時,才會將父行程的內容復制一份給子行程,
12.3 相關檔案及配置
-
dump.rdb:存放 RDB 持久化資料的檔案,
dump.rdb 默認存放在啟動 Redis 的目錄下,如,在 /opt/ 下使用命令:redis-server ,則會在 /opt 下創建 dump.rdb 檔案,可以在 Redis.conf 中修改名稱和位置,

修改 dump.rdb 的保存位置:

-
觸發保存資料到持久化檔案中的事件:
(1)以shutdown方式正常退出 Redis 時,
(2)save 多少秒內 被修改的鍵的個數:當在 n 秒內,有 m 個 key 被修改(包括新建、修改、洗掉等)時,將這 m 個 key 保存到持久化檔案中,

-
save 和 bgsave:
save:阻塞式保存,需要手動保存,不建議使用,
bgsave:Redis 會在后臺異步進行快照操作(自動持久化資料), 快照同時還可以回應客戶端請求,

-
stop-writes-on-bgsave-error:當 Redis 無法將資料寫入磁盤時(如磁盤已滿),關掉 Redis 的寫操作,默認為 yes,

-
rdbcompression:是否將持久化檔案壓縮,默認為 yes,
對于存盤到磁盤中的快照,可以設定是否進行壓縮,如果為 yes,redis 會采用 LZF 演算法將持久化檔案進行壓縮,

-
rdbchecksum:檢查檔案完整性,默認為 yes,
讓 redis 使用 CRC64 演算法進行資料校驗,

12.4 恢復
Redis 每次啟動時,會自動在持久化檔案目錄下加載 dump.rdb 檔案,進行資料的恢復,
12.5 優缺點
優點:
- 適合大規模的資料恢復,
- 對資料完整性和一致性要求不高的場景,
- 節省磁盤空間,
- 恢復速度快,
缺點:
- Fork 時,記憶體中的資料被克隆了一份,大致 2 倍的膨脹性需要考慮,
- 雖然 Redis 在 fork 時使用了“寫時拷貝技術”,但是如果資料過于龐大,還是比較消耗性能,
- 可能會丟失最后一次持久化的資料,
13 持久化—AOF
13.1 介紹
- AOF,Append Only File,以日志的形式來記錄每個寫操作(增量保存),將 Redis 執行過的所有寫指令記錄下來(讀操作不記錄), 只許追加檔案但不可以改寫檔案,redis 在啟動時會讀取該檔案重新構建資料,即 redis 重啟時根據 AOF 檔案的內容將寫指令從前到后執行一次以完成資料的恢復作業,
- AOF 默認不開啟,
- AOF 和 RDB 同時開啟時,Redis 默認讀取 AOF 的資料,因為 AOF 的資料不會丟失,
13.2 相關檔案及配置
- appendonly.aof:存放 AOF 持久化資料的檔案,默認的存放目錄與 RDB 的目錄相同,
- AOF 同步頻率設定:
appendfsync always:始終同步,每次 Redis 的寫入操作都會立即記入日志,性能較差但資料完整性比較好,
appendfsync everysec:每秒同步,每秒記入日志一次,如果 Redis 死機,本秒的資料可能丟失,
appendfsync no:Redis 不主動進行同步,把同步時機交給作業系統, - Rewrite(壓縮):AOF 采用檔案追加方式,檔案會越來越大為避免出現此種情況,新增了重寫機制, 當 AOF 檔案的大小超過所設定的閾值時,Redis 就會啟動 AOF 檔案的內容壓縮, 只保留可以恢復資料的最小指令集,
(1)auto-aof-rewrite-min-size:設定重寫的基準值,最小檔案 64MB,當 AOF 檔案大小達到這個值時第一次觸發重寫,
(2)auto-aof-rewrite-percentage:設定重寫的基準值,默認是當前 AOF 檔案是上次重寫后的檔案大小的 1 倍時開始重寫,
(3)Redis 會記錄上次重寫時的 AOF 檔案大小,默認配置是當 AOF 檔案大小是上次 rewrite 后大小的 1 倍且檔案大于 64M 時第 n 次觸發,
例如:檔案達到 70MB 時開始重寫,第一次重寫將檔案大小降到 50MB,則當檔案大小達到 100MB 時開始下一次重寫,
13.3 AOF 的開啟、修復和恢復
- 開啟 AOF:AOF 服務默認不開啟,修改 Redis.conf 中的 appendonly no 為
appendonly yes,開啟 AOF, - appendonly.aof 檔案可能出現損壞、無法加載等例外,可以使用
redis-check-aof --fix appendonly.aof命令進行修復, - Redis 每次啟動時,會自動在持久化檔案目錄下加載 appendonly.aof 檔案,進行資料的恢復,當 AOF 和 RDB 同時開啟時,Redis 默認讀取 AOF 的資料,
13.4 AOF 的持久化流程
- 客戶端的寫命令會被 append 追加到 AOF 緩沖區內,
- AOF 緩沖區根據 AOF 持久化策略 [always,everysec,no] 將操作同步到磁盤的 AOF 檔案中,
- AOF 檔案大小超過重寫策略或手動重寫時,會對 AOF 檔案重寫,壓縮 AOF 檔案容量,
- Redis 服務重啟時,會重新加載 AOF 檔案中的寫操作達到資料恢復的目的,
13.5 優缺點
優點:
- 備份機制穩健,丟失資料的可能性很低,
- 可讀的日志文本,可以處理誤操作,
缺點:
- 與 RDB 相比占用更多的磁盤空間,
- 恢復備份速度更慢,
- 每次寫操作都同步時,有一定的性能壓力,
- 存在個別 Bug,造成不能恢復,
13.6 RDB 與 AOF 用哪個?
- 官方推薦兩個都啟用,
- 如果對資料不敏感,可以單獨使用 RDB,
- 不建議單獨使用 AOF,因為可能會出現 Bug,
- 如果只用作純記憶體快取,兩者可以都不使用,
14 主從復制
14.1 介紹
將 Redis 服務器分為主服務器和從服務器,主服務器負責寫操作,從服務器負責讀操作,主服務器負責將資料同步到所有的從服務器中,
主從復制的好處是可以實作讀寫分離,解決 Redis 的讀寫壓力,

14.2 配置
假設配置一主二從:
-
復制 3 份 Redis.conf 組態檔,分別命名為便于識別的名字,如,redis6379.conf、redis6380.conf、redis6381.conf,

-
在這些組態檔中,使用:
include,引入 redis.conf 檔案(要使用絕對路徑),并修改下面這些配置:
(1)開啟 daemonize yes,
(2)pidfile 的存盤路徑(pidfile 用來保存 pid),
(3)指定埠 port,
(4)log 檔案名,
(5)dbfilename(RDB 持久化檔案名),路徑使用 dir 配置,
(6)關閉 AOF 持久化方式,或重命名 Appendonly.aof 檔案名,
(7)如果主服務器設定了密碼,從服務器的組態檔中要配置:masterauth,

其他組態檔改成相應的資訊即可, -
使用:
redis-server 組態檔路徑,啟動 3 臺服務器,

-
因為每臺服務器的埠號不同,因此使用:
redis-cli -h 服務器ip地址 -p 埠號,打開客戶端,

-
使用:
info replication,查看主從復制的相關資訊,

-
配從不配主,在需要配置成從服務器的客戶端內,使用:
salveof ip port,將本服務器設定為該 ip,port 的從服務器,如,將 6380 和 6381 設定為 6379 的從服務器,注意:在新版的 Redis 中,推薦使用:replicaof,代替 slaveof,

-
在主服務器上寫資料,這些資料會同步到所有的從服務器上,在從服務器上可以讀取這些資料,

注意:
- 主服務器可讀可寫,從服務器只能讀,

- 當主服務器掉線時,所有的從服務器都會處于等待狀態,role 仍然是 slave,當主服務器再次上線時,仍然是之前那些從服務器的主服務器,
- 當從服務器掉線時,主服務器的 slaves 串列中就會將該從服務器洗掉,當掉線的這個從服務器再次上線后,需要再次執行 slaveof 命令,才可以成為主服務器的從服務器,
- 可以在從服務器的組態檔中配置主服務器的資訊,配置后,當從服務器掉線再上線后,會自動成為從服務器,而不需要再次輸入 slaveof 命令,

14.3 一主二從
- 主機新接入的從機,會不會有接入之前的主機資料?
有,不管何時接入,主機都會將所有的資料同步到從機上, - 從機是否可以寫?
不可以,從機只能讀, - 主機 shutdown 后情況如何?從機是上位還是原地待命?
主機下線后,默認情況下,從機會原地待命(不會變成主機),直到主機再次上線, - 主機再次上線后,主機新增記錄,從機還能否順利復制?
能, - 其中一臺從機下線后情況如何?
從機下線后,主機的 slaves 串列中就會將這臺從機洗掉,就不會同步資料給這個下線的從機,當下線的從機再次上線后,主機會將所有資料都同步給這個剛上線的從機,
14.4 反客為主

在一般模式下,主機下線后,所有的從機都處于等待狀態,此時由于從機不具備寫操作,如果主機長時間不上線,那么 Redis 就會長時間處于不能寫,只能讀的狀態,這種狀態是我們不希望看到的,
解決辦法:
當主機下線后,在希望成為新的主機的從機內,使用:replicaof no one,將這個從機設定為新的主機,之后修改其他服務器為這個新主機的從機即可,

14.5 薪火相傳

在反客為主模式下,主機下線后需要兩部操作:
(1)從機使用 replicaof no one 變為新主機,
(2)其他從機使用 replicaof ip port 變為新主機的從機,
薪火相傳是指:
主機與從機之間類似于上圖所示的串聯結構:master 是 slave1 的主機,slave1 是 slave2 的主機,當 master 下線后,slave1 與 slave2 仍然構成了主從關系,此時只需在 slave1 中執行:replicaof no one,即可將 slave1 設定為 slave2 的主機,
實作方式:假設 6379 是 master,6380 是 slave1,6381 是 slave2,
方式1:臨時方式
(1)在 6380 客戶端中執行:replicaof 127.0.0.1 6379,
(2)在 6381 客戶端中執行:replicaof 127.0.0.1 6380,
方式2:永久方式
(1)6380 的組態檔 redis6380.conf 中,添加:replicaof 127.0.0.1 6379,
(2)6381 的組態檔 redis6381.conf 中,添加:replicaof 127.0.0.1 6380,

當 master 下線(shutdown)后,

薪火相傳模式下,master 中的資料會同步到 slave1,slave1 中的資料會同步到 slave2,最終實作資料的全同步,
優點:可以有效減輕 master 的寫壓力,去中心化,降低風險,
缺點:一旦中間的某個 slave 下線,則后面的 slave 都不能再備份新的資料,
14.6 哨兵模式
哨兵模式是反客為主的自動版,能夠在后臺監控主機是否出現故障,如果出現了故障,那么每個哨兵都會對現有的從機進行投票(每個哨兵 1 票),根據投票結果,將得票最多的從機自動轉換為新的主機,

實作步驟:
- 建立一主二從的關系:6379 為主機,6380 和 6381 為 6379 的兩個從機,

- 在 /opt/myRedis/ 下創建哨兵組態檔:
sentinel.conf, - 在組態檔中填寫:
(1)sentinel monitor 監控的主服務器別名(隨便寫) ip port 票數n,其中,票數 n 是指當有 n 個哨兵投票認為該主服務器出現故障時,才將這個主服務器認定為故障,
(2)后臺開啟哨兵模式:daemonize yes,這里為了演示效果,暫不使用后臺開啟,
(3)如果主機與從機設定了密碼,需要在組態檔中宣告:sentinel auth-pass 服務器別名 密碼,注意的是,sentinel 不能分別為 master 和 slave 設定不同的密碼,因此 master 和 slave 的密碼應該設定相同,

- 啟動哨兵,在任意位置執行:
redis-sentinel sentinel.conf檔案路徑,開啟哨兵模式,

- 當主機發生故障下線后,哨兵會在從機中投票選出一個新的主機,原主機的所有從機會自動變成新主機的從機,


新主機的選舉原則:
- 優先級越靠前越優先,可以在每個服務器的組態檔中(如,redis6379.conf)設定:
slave-priority n,n 表示作為從機時的優先級,默認為 100,值越小優先級越高,如 n = 10 要優先于 n = 50 被選作為新的主機, - 偏移量越大越優先,偏移量是指從機獲得的原主機中資料的多少,
- runid 越小越優先,每個 redis 服務啟動后都會隨機生成一個 40 位的 runid,
15 集群
15.1 介紹
容量不夠,Redis 如何進行擴容?并發寫操作,Redis 如何分攤?集群就是解決這些問題的方法,
Redis 集群實作了對 Redis 的水平擴容,即啟動 N 個 Redis 節點,將整個資料庫分布存盤在這 N 個節點中,每個節點存盤總資料的 1/N,
Redis 集群通過磁區(partition)來提供一定程度的可用性(availability):即使集群中有一部分節點失效或者無法進行通訊, 集群也可以繼續處理命令請求,
15.2 配置
- 洗掉之前實驗生成的 dump.rdb:
rm -rvf dump*.rdb,防止造成干擾,

- 模擬 6 個服務器,埠號使用 6379,6380,6381,6389,6390,6391,并創建這些服務器的組態檔,

(1)配置基本資訊:
1. 開啟 daemonize yes,
2. pidfile 的存盤路徑(pidfile 用來保存 pid),
3. 指定埠 port,
4. log 檔案名,
5. dbfilename(RDB 持久化檔案名),路徑使用 dir 配置,
6. 關閉 AOF 持久化方式,或重命名 Appendonly.aof 檔案名,
7. 參與集群的多 Redis 服務器,在集群之前不要設定密碼,否則會導致 Redirect 失敗,集群的密碼可以在之后設定,之前的專案我都設定了密碼,因此現在要把 redis.conf 中的 requirepass 注釋掉,并設定 protected-mode no,
(2)配置集群資訊:
1.cluster-enabled yes:打開集群模式,
2.cluster-config-file nodes-xxx.conf:設定節點組態檔名稱,
3.cluster-node-timeout 15000:設定節點失聯時間,超過該時間(毫秒),集群自動進行主從切換(相當于哨兵模式),


- 啟動這 6 個服務器,并檢查 nodes.conf 檔案是否正常生成,

- 將這 6 個服務器(節點)合并成一個集群,
(1)進入redis安裝目錄/src下,我的是:cd /opt/redis-6.2.2/src,
(2)執行命令:redis-cli [-a 密碼] --cluster create --cluster-replicas 1 192.168.61.128:6379 192.168.61.128:6380 192.168.61.128:6381 192.168.61.128:6389 192.168.61.128:6390 192.168.61.128:6391,此處的 ip 地址要使用服務器的真實地址(可以使用 ifconfig 查看),不能使用 127.0.0.1,-replicas 1:采用最簡單的方式配置集群,一臺主機,一臺從機,正好三組,

(3)以集群的方式進入客戶端:redis-cli -c -p port,

- 使用命令:
cluster nodes:命令查看集群資訊,

- 在某一個客戶端使用 set 命令時,會將添加的資料自動對應一個 slot(插槽),并將服務器跳轉到對應的埠,get 命令也可以自動跳轉到包含所需資料的服務器內,

15.3 原理及命令
- redis cluster 如何分配這六個節點?
一個集群至少要有三個主節點,
選項:--cluster-replicas n,表示為集群中的每個主節點創建 n 個從節點,
分配原則:(1)盡量保證每個主服務器運行在不同的 ip 地址上(2)盡量保證每個主服務器和它的從服務器不運行在同一個 ip 地址上, - slots 插槽:
一個 Redis 集群包含 16384 個插槽(hash slot), 資料庫中的每個鍵都屬于這 16384 個插槽的其中一個,集群中的每個節點負責處理一部分插槽, 例如,一個集群有 3 個主節點, 那么:
節點 A 負責處理 0 - 5460 號插槽,
節點 B 負責處理 5461 - 10922 號插槽,
節點 C 負責處理 10923 - 16383 號插槽, - 在集群中錄入值:
(1)使用 redis-cli 啟動的客戶端,每次錄入、查詢鍵值,redis 都會計算出該 key 應該送往的插槽,如果不是該客戶端對應服務器的插槽,redis 會報錯,并告知應前往的 redis 實體地址和埠,
(2)使用 redis-cli -c -p 啟動的客戶端,提供了 –c 引數實作自動重定向,每次錄入、查詢鍵值對可以自動重定向,
(3)不在一個同 slot 下的鍵值,不能使用 mget,mset 等批量操作,
(4)可以通過{}定義鍵所在的組,這樣就可以使組相同的鍵存盤到同一個 slot 中,

- 集群的一些命令:
(1)cluster keyslot k:計算鍵 k 對應的插槽,
(2)cluster countkeysinslot s:獲取插槽 s 中包含的鍵值對數量,
(3)cluster getkeysinslot s c:回傳 c 個 插槽 s 中的鍵,如,獲取插槽 1230 中的 5 個鍵,

- 集群的故障處理:
(1)如果主節點下線,從節點能否自動升為主節點?若超時 15 秒還沒有上線,則從節點上升為主節點,
(2)主節點恢復后,主從關系會如何?主節點再次上線后變成從節點,
(3)如果某一段插槽的主從節點都下線了,那么 Redis 服務是否還能繼續?不能,這種情況受到 redis.conf 中的引數 cluster-require-full-coverage 約束,該引數為 yes 表示 16384 個插槽都正常時,才能對外提供服務,
如果某一段插槽的主從都掛掉,而 cluster-require-full-coverage 為 yes ,則整個集群都不能使用,無法進行讀取操作;若 cluster-require-full-coverage 為 no ,則該段插槽將不能使用,這段插槽無法進行讀取操作,
15.4 Jedis 操作集群的 JedisCluster
Jedis 類與 JedisCluster 類的區別是啟動客戶端的方式不同,類內的許多方法都是相同的,
public class MyCluster {
public static void main(String[] args) {
HashSet<HostAndPort> nodes = new HashSet<>();
HostAndPort hostAndPort = new HostAndPort("192.168.61.128",6379);
nodes.add(hostAndPort);
JedisCluster cluster = new JedisCluster(nodes);
// cluster.set("jedisClusterKey","jedisClusterVal");
String key = cluster.get("jedisClusterKey");
System.out.println(key);
cluster.close();
}
}
15.5 集群的優缺點
優點:
- 實作擴容
- 分攤壓力
- 無中心配置相對簡單
缺點:
- 不支持多鍵操作,
- 不支持多鍵事務,
- 不支持 lUA 腳本,
- 由于 Redis Cluster 集群方案出現較晚,很多公司已經采用了其他的集群方案,而代理或客戶端分片的方案想要遷移至 Redis Cluster,需要整體遷移而非逐步過渡,復雜度較大,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/282607.html
標籤:其他
