第一节 Redis 使用及哨兵集群 2022-1-2
Java組件總目錄
Redis 使用及哨兵集群
- Java組件總目錄
- 一 Redis基本數(shù)據(jù)類型使用場景
- 1 String
- 2 List 存儲列表結(jié)構(gòu)
- 3 Hash
- 4 Set
- 5 Zset
- 二級目錄
- 三級目錄
- 二 Redis 的補充數(shù)據(jù)類型
- 1 BitMap
- 2 HyperLogLog
- 3 Geospatial
- 三 Redis 消息模式 (了解)
- 3.1 隊列模式
- 注意事項:
- 缺點:
- 3.2 發(fā)布訂閱模式
- 四 Redis Stream
- 4.1 消息隊列相關(guān)命令:
- 4.2 消費者組相關(guān)命令:
- 五 Redis 事務(wù)
- 5.1 事務(wù)失敗處理
- Redis 語法錯誤
- Redis 運行錯誤
- 六 Redis 和lua 整合
- 6.1 Redis中使用lua的好處
- 6.2 EVAL命令
- 6.3 lua 腳本調(diào)用Redis 命令
- redis.call();
- redis.pcall();
- redis-cli --eval
- 七 Redis 持久化(重點)
- 7.1 RDB
- 7.2 AOF
- 1 AOF介紹
- 2 同步磁盤數(shù)據(jù)
- 3 AOF重寫原理(優(yōu)化AOF文件)
- 4 如何選擇RDB和AOF
- 7.3 混合持久化方式
- 八 Redis 主從復(fù)制
- 8.1 什么是主從復(fù)制
- 8.2 實現(xiàn)原理
- 1 數(shù)據(jù)同步
- 2 runid
- 3 復(fù)制偏移量
- 4 全量同步
- 5 增量同步
- 8.3 主從配置
- 8.3.1 安裝
- 8.3.2 配置說明
- 九 Redis 哨兵機制
- 9.1 Redis Sentinel 工作原理分析
- 1 為什么要用到哨兵
- 2 哨兵機制(sentinel)的高可用
- 3 哨兵的定時監(jiān)控
- 4 哨兵lerder選舉流程
- 5 自動故障轉(zhuǎn)移機制
- 9.2 哨兵進(jìn)程的作用
- 9.3 哨兵配置
- quorum的解釋如下:
- 如果有一個sentinel:
- 如果有2個sentinel
- 如果是經(jīng)典的3節(jié)點哨兵集群
一 Redis基本數(shù)據(jù)類型使用場景
redis:應(yīng)用的場景高并發(fā)所有數(shù)據(jù)都是保存在內(nèi)存中。存取速度快,適合于做緩存。一些重要數(shù)據(jù)一定要保存到關(guān)系型數(shù)據(jù)庫中,例如mysql。適合做緩存的: string, hash1 String
應(yīng)用: JSONstring 緩存功能 計數(shù)器 共享用戶Session 分布式鎖 setnx
2 List 存儲列表結(jié)構(gòu)
粉絲列表,文章評論列表, lrange 基于Redis實現(xiàn)簡單的高性能分頁, 簡單的消息隊列
3 Hash
應(yīng)用: 爆品 商品 秒殺倉庫 秒殺商品 商品1 庫存量
4 Set
基于Redis進(jìn)行全局的Set去重 共同好友 你可能認(rèn)識
5 Zset
排行榜,有權(quán)重的消息隊列 熱搜 前面是名稱 后面試熱度值
二級目錄
三級目錄
二 Redis 的補充數(shù)據(jù)類型
1 BitMap
BitMap 就是通過一個 bit 位來表示某個元素對應(yīng)的值或者狀態(tài), 其中的 key 就是對應(yīng)元素本身,實際上底層也是通過對字符串的操作來實現(xiàn)。Redis 從 2.2 版本之后新增了setbit, getbit, bitcount 等幾個bitmap 相關(guān)命令。雖然是新命令,但是本身都是對字符串的操作,我們先來看看語法
# 其中 offset 必須是數(shù)字,value 只能是 0 或者 1,offset參數(shù)要求大于或等于 0, # 并且小于 2^32(4,294,967,296)這將位圖限制在 512MB SETBIT key offset value設(shè)置最后一個可能的位時(偏移量等于 2^32-1)和存儲在鍵中的字符串值尚不保存字符串值,或持有一個小字符串值,Redis 需要分配所有中間內(nèi)存,這些中間內(nèi)存可能會阻塞服務(wù)器一段時間。完成第一次分配后,對同一key的 SETBIT的后續(xù)調(diào)用將無內(nèi)存分配開銷。
通過 bitcount可以很快速的統(tǒng)計,比傳統(tǒng)的關(guān)系型數(shù)據(jù)庫效率高很多。
BITOP operation destkey key [key …]
對一個或多個保存二進(jìn)制位的字符串 key 進(jìn)行位元操作,并將結(jié)果保存到 destkey 上。operation 可以是 AND 、 OR 、 NOT 、 XOR 這四種操作中的任意一種:
2 HyperLogLog
Redis 在 2.8.9 版本添加了 HyperLogLog 結(jié)構(gòu)。Redis HyperLogLog 是用來做基數(shù)統(tǒng)計的算法,HyperLogLog 的優(yōu)點是,在輸入元素的數(shù)量或者體積非常非常大時,計算基數(shù)所需的空間總是固定的、并且是很小的。
但是,因為 HyperLogLog 只會根據(jù)輸入元素來計算基數(shù),而不會儲存輸入元素本身,所以
HyperLogLog 不能像集合那樣,返回輸入的各個元素。
這個數(shù)據(jù)結(jié)構(gòu)的命令有三個:PFADD、PFCOUNT、PFMERGE
用途:記錄網(wǎng)站IP注冊數(shù),每日訪問的IP數(shù),頁面實時UV、在線用戶人數(shù)
局限性:只能統(tǒng)計數(shù)量,沒有辦法看具體信息。
3 Geospatial
底層數(shù)據(jù)結(jié)構(gòu) Zset。可以用來保存地理位置,并作位置距離計算或者根據(jù)半徑計算位置等。有沒有想過用Redis來實現(xiàn)附近的人?或者計算最優(yōu)地圖路徑?Geo本身不是一種數(shù)據(jù)結(jié)構(gòu),它本質(zhì)上還是借助于Sorted Set(ZSET)
Redis GEO 操作方法有:
- geoadd:添加地理位置的坐標(biāo)。
- geopos:獲取地理位置的坐標(biāo)。
- geodist:計算兩個位置之間的距離。
- georadius:根據(jù)用戶給定的經(jīng)緯度坐標(biāo)來獲取指定范圍內(nèi)的地理位置集合。
- georadiusbymember:根據(jù)儲存在位置集合里面的某個地點獲取指定范圍內(nèi)的地理位置集合。
- geohash:返回一個或多個位置對象的 geohash 值。
三 Redis 消息模式 (了解)
消息模式差于專門的消息系統(tǒng) Kafka、 RabbitMQ。消息有可能丟失, 可用于能夠接受消息丟失的場景。如 過濾等。
3.1 隊列模式
使用list類型的lpush和rpop實現(xiàn)消息隊列。
注意事項:
- 消息接收方如果不知道隊列中是否有消息,會一直發(fā)送rpop命令,如果這樣的話,會每一次都建立一次連接,這樣顯然不好。
- 可以使用brpop命令,它如果從隊列中取不出來數(shù)據(jù),會一直阻塞,在一定范圍內(nèi)沒有取出則 返回null
缺點:
- 做消費者確認(rèn)ACK麻煩,不能保證消費者消費消息后是否成功處理的問題(宕機或處理異常等),通常需要維護(hù)一個Pending列表,保證消息處理確認(rèn)。
- 不能做廣播模式,如pub/sub,消息發(fā)布/訂閱模型
- 不能重復(fù)消費,一旦消費就會被刪除
- 不支持分組消費
3.2 發(fā)布訂閱模式
- SUBSCRIBE,用于訂閱信道
- PUBLISH,向信道發(fā)送消息
- UNSUBSCRIBE,取消訂閱
此模式允許生產(chǎn)者只生產(chǎn)一次消息,由中間件負(fù)責(zé)將消息復(fù)制到多個消息隊列,每個消息隊列由對應(yīng)的消費組消費。 理解為群發(fā)消息。
四 Redis Stream
Redis 5.0 全新的數(shù)據(jù)類型:streams,官方把它定義為:以更抽象的方式建模日志的數(shù)據(jù)結(jié)構(gòu)。由于推出比較遲,應(yīng)用相對較少。Redis的streams主要是一個append only(AOF)的數(shù)據(jù)結(jié)構(gòu),至少在概念上它是一種在內(nèi)存中表示的抽象數(shù)據(jù)類型,只不過它們實現(xiàn)了更強大的操作,以克服日志文件本身的限制。
如果你了解MQ,那么可以把streams當(dāng)做基于內(nèi)存的MQ。如果你還了解kafka,那么甚至可以把streams當(dāng)做基于內(nèi)存的kafka。listpack存儲信息,Rax組織listpack 消息鏈表listpack是對ziplist的改進(jìn),它比ziplist少了一個定位最后一個元素的屬性。
streams數(shù)據(jù)結(jié)構(gòu)本身非常簡單,但是streams依然是Redis到目前為止最復(fù)雜的類型,其原因是實現(xiàn)的一些額外的功能:一系列的阻塞操作允許消費者等待生產(chǎn)者加入到streams的新數(shù)據(jù)。另外還有一個稱為Consumer Groups的概念,Consumer Group概念最先由kafka提出,Redis有一個類似實現(xiàn),和 kafka的Consumer Groups的目的是一樣的:允許一組客戶端協(xié)調(diào)消費相同的信息流!
一個組可以有多個消費者,加快了消息的消費。
4.1 消息隊列相關(guān)命令:
- XADD - 添加消息到末尾
- XTRIM - 對流進(jìn)行修剪,限制長度
- XDEL - 刪除消息
- XLEN - 獲取流包含的元素數(shù)量,即消息長度
- XRANGE - 獲取消息列表,會自動過濾已經(jīng)刪除的消息
- XREVRANGE - 反向獲取消息列表,ID 從大到小
- XREAD - 以阻塞或非阻塞方式獲取消息列表
4.2 消費者組相關(guān)命令:
- XGROUP CREATE - 創(chuàng)建消費者組
- XREADGROUP GROUP - 讀取消費者組中的消息
- XACK - 將消息標(biāo)記為"已處理"
- XGROUP SETID - 為消費者組設(shè)置新的最后遞送消息ID
- XGROUP DELCONSUMER - 刪除消費者
- XGROUP DESTROY - 刪除消費者組
- XPENDING - 顯示待處理消息的相關(guān)信息
- XCLAIM - 轉(zhuǎn)移消息的歸屬權(quán)
- XINFO - 查看流和消費者組的相關(guān)信息;
- XINFO GROUPS - 打印消費者組的信息;
- XINFO STREAM - 打印流信息
五 Redis 事務(wù)
嚴(yán)格意義上說 redis事務(wù)只是個批處理 有隔離性 但是沒有原子性。
- Redis 的事務(wù)是通過 MULTI(事務(wù)開始) 、 EXEC(事務(wù)執(zhí)行,并關(guān)閉) 、 DISCARD(清空事務(wù),并關(guān)閉) 和 WATCH(設(shè)置個事務(wù)監(jiān)控的鍵, 鍵改變時不執(zhí)行事務(wù),增加一個事務(wù)執(zhí)行的開關(guān)) 、UNWATCH (清除監(jiān)控的鍵)這五個命令來完成的。
- Redis 的單個命令都是原子性的,所以這里需要確保事務(wù)性的對象是命令集合。 Redis 將命令集合序列化并確保處于同一事務(wù)的命令集合連續(xù)且不被打斷的執(zhí)行
- Redis 不支持回滾操作。
5.1 事務(wù)失敗處理
Redis 語法錯誤
語法錯誤會將整個事務(wù)的命令在隊列里都清除。
Redis 運行錯誤
在隊列里正確的命令可以執(zhí)行 (弱事務(wù)性)
- 1、在隊列里正確的命令可以執(zhí)行 (非原子操作)
- 2、不支持回滾
Redis 不支持事務(wù)回滾(為什么呢)
- 1、大多數(shù)事務(wù)失敗是因為語法錯誤或者類型錯誤,這兩種錯誤,在開發(fā)階段都是可以預(yù)見的。
- 2、 Redis 為了性能方面就忽略了事務(wù)回滾。 (Mysql 使用redo-log 實現(xiàn)回滾)
六 Redis 和lua 整合
Redis整合lua是對Redis事務(wù)的補充。lua是一種輕量小巧的腳本語言,用標(biāo)準(zhǔn)C語言編寫并以源代碼形式開放, 其設(shè)計目的是為了嵌入應(yīng)用程序中,從而為應(yīng)用程序提供靈活的擴(kuò)展和定制功能。
6.1 Redis中使用lua的好處
本的過程中無需擔(dān)心會出現(xiàn)競態(tài)條件。 隔離性
6.2 EVAL命令
在redis客戶端中,執(zhí)行以下命令:
EVAL script numkeys key [key ...] arg [arg ...] eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second命令說明:
-
script參數(shù):是一段Lua腳本程序,它會被運行在Redis服務(wù)器上下文中,這段腳本不必(也不應(yīng)該)定義為一個Lua函數(shù)。
-
numkeys參數(shù):用于指定鍵名參數(shù)的個數(shù)。
-
key [key …]參數(shù): 從EVAL的第三個參數(shù)開始算起,使用了numkeys個鍵(key),表示在腳本中所用到的那些Redis鍵(key),這些鍵名參數(shù)可以在Lua中通過全局變量KEYS數(shù)組,用1為基址的形式訪問( KEYS[1] , KEYS[2] ,以此類推)。
-
arg [arg …]參數(shù):可以在Lua中通過全局變量ARGV數(shù)組訪問,訪問的形式和KEYS變量類似(ARGV[1] 、 ARGV[2] ,諸如此類)。
6.3 lua 腳本調(diào)用Redis 命令
redis.call();
返回值就是redis命令執(zhí)行的返回值。如果出錯,返回錯誤信息,不繼續(xù)執(zhí)行
redis.pcall();
返回值就是redis命令執(zhí)行的返回值,如果出錯了 記錄錯誤信息,繼續(xù)執(zhí)行
注意事項: 在腳本中,使用return語句將返回值返回給客戶端,如果沒有return,則返回nil
redis-cli --eval
可以使用redis-cli --eval命令指定一個lua腳本文件去執(zhí)行。
腳本文件(redis.lua),內(nèi)容如下:
local num = redis.call('GET', KEYS[1]); if not num then return 0; else local res = num * ARGV[1]; redis.call('SET',KEYS[1], res); return res; end在redis客戶機,執(zhí)行腳本命令:
# 之前設(shè)置在redis中設(shè)置過 a 為 1 [root@localhost bin]# ./redis-cli --eval redis.lua a , 8 (integer) 8[root@localhost bin]# ./redis-cli --eval redis.lua lua:incrbyml , 8 (integer) 0 # incr 遞增數(shù)字 [root@localhost bin]# ./redis-cli incr lua:incrbyml (integer) 1 [root@localhost bin]# ./redis-cli --eval redis.lua lua:incrbyml , 8 (integer) 8- –eval:告訴redis客戶端去執(zhí)行后面的lua腳本
- redis.lua:具體的lua腳本文件名稱
- lua:incrbymul : lua腳本中需要的key,具體的key值
- 8:lua腳本中需要的value
上面命令中keys和values中間需要使用逗號隔開,并且逗號兩邊都要有空格。 lua:incrbyml , 8
執(zhí)行.lua腳本 不需要寫key的個數(shù)
七 Redis 持久化(重點)
7.1 RDB
RDB 是 Redis 默認(rèn)采用的持久化方式。
RDB 方式是通過快照( snapshotting )完成的,當(dāng)符合一定條件時 Redis 會自動將內(nèi)存中的數(shù)據(jù)進(jìn)行快照并持久化到硬盤。 (將當(dāng)前內(nèi)存的數(shù)據(jù)保存。)
觸發(fā)RDB快照的時機:
主線程是單線程 4.0 I/O操作 已經(jīng)有多線程概念
設(shè)置快照規(guī)則:
save 多少秒內(nèi) 數(shù)據(jù)變了多少
save “” : 不使用RDB存儲
save 900 1 : 表示15分鐘(900秒鐘)內(nèi)至少1個鍵被更改則進(jìn)行快照。
save 300 10 : 表示5分鐘(300秒)內(nèi)至少10個鍵被更改則進(jìn)行快照。
save 60 10000 :表示1分鐘內(nèi)至少10000個鍵被更改則進(jìn)行快照。
RDB快照的實現(xiàn)原理
fork 是操作系統(tǒng)的函數(shù) linux/ uinx *nux, fork-調(diào)用一個子進(jìn)程,制作快照,生成RDB文件, 替換掉原來的RDB文件.
注意事項
RDB優(yōu)缺點:
- 缺點:使用 RDB 方式實現(xiàn)持久化,一旦 Redis 異常退出,就會丟失最后一次快照以后更改的所有數(shù)
據(jù)。這個時候我們就需要根據(jù)具體的應(yīng)用場景,通過組合設(shè)置自動快照條件的方式來將可能發(fā)生的
數(shù)據(jù)損失控制在能夠接受范圍。如果數(shù)據(jù)相對來說比較重要,希望將損失降到最小,則可以使用
AOF 方式進(jìn)行持久化 - 優(yōu)點: RDB 可以最大化 Redis 的性能:父進(jìn)程在保存 RDB 文件時唯一要做的就是 fork 出一個子進(jìn)
程,然后這個子進(jìn)程就會處理接下來的所有保存工作,父進(jìn)程無需執(zhí)行任何磁盤 I/O 操作。同時這
個也是一個缺點,如果數(shù)據(jù)集比較大的時候, fork 可以能比較耗時,造成服務(wù)器在一段時間內(nèi)停
止處理客戶端的請求;
7.2 AOF
1 AOF介紹
默認(rèn)情況下 Redis 沒有開啟 AOF ( append only file )方式的持久化。
開啟 AOF 持久化后,每執(zhí)行一條會更改 Redis 中的數(shù)據(jù)的命令, Redis 就會將該命令寫入硬盤中的 AOF文件,這一過程顯然會降低 Redis 的性能,但大部分情況下這個影響是能夠接受的,另外使用較快的硬盤可以提高 AOF 的性能。
2 同步磁盤數(shù)據(jù)
Redis 每次更改數(shù)據(jù)的時候, aof 機制都會將命令記錄到 aof 文件,但是實際上由于操作系統(tǒng)的緩存機制,數(shù)據(jù)并沒有實時寫入到硬盤,而是進(jìn)入硬盤緩存。再通過硬盤緩存機制去刷新到保存到文件。
最開始的數(shù)據(jù)它是通過讀取內(nèi)存中的數(shù)據(jù),轉(zhuǎn)換成命令。后邊的就是每次的更新指令,進(jìn)行存儲。
# 每次執(zhí)行寫入都會進(jìn)行同步, 這個是最安全但是是效率比較低的方式 appendfsync always # 每一秒執(zhí)行(默認(rèn)) appendfsync everysec # 不主動進(jìn)行同步操作,由操作系統(tǒng)去執(zhí)行,這個是最快但是最不安全的方式 appendfsync no3 AOF重寫原理(優(yōu)化AOF文件)
Redis 可以在 AOF 文件體積變得過大時,自動地在后臺對 AOF 進(jìn)行重寫。重寫后的新 AOF 文件包含了恢復(fù)當(dāng)前數(shù)據(jù)集所需的最小命令集合。AOF進(jìn)行優(yōu)化時候,并不是讀取原來的AOF文件 ,而是讀取redis db 進(jìn)行轉(zhuǎn)化。
AOF 文件有序地保存了對數(shù)據(jù)庫執(zhí)行的所有寫入操作, 這些寫入操作以 Redis 協(xié)議(RESP)的格式
保存, 因此 AOF 文件的內(nèi)容非常容易被人讀懂, 對文件進(jìn)行分析( parse )也很輕松。
4 如何選擇RDB和AOF
- 內(nèi)存數(shù)據(jù)庫 rdb(redis database)+aof 數(shù)據(jù)不能丟
- 緩存服務(wù)器 rdb
- 不建議 只使用 aof (性能差)
- 恢復(fù)時: 先aof再rdb
7.3 混合持久化方式
RDB 和 AOF 持久化各有利弊,RDB 可能會導(dǎo)致一定時間內(nèi)的數(shù)據(jù)丟失,而 AOF 由于文件較大則會影響Redis 的啟動速度,為了能同時擁有 RDB 和 AOF 的優(yōu)點,Redis 4.0 之后新增了混合持久化的方式,因此我們在必須要進(jìn)行持久化操作時,應(yīng)該選擇混合持久化的方式。
混合持久化是結(jié)合了 RDB 和 AOF 的優(yōu)點,在寫入的時候,先把當(dāng)前的數(shù)據(jù)以 RDB 的形式寫入文件的開頭,再將后續(xù)的操作命令以 AOF 的格式存入文件,這樣既能保證 Redis 重啟時的速度,又能減低數(shù)據(jù)丟失的風(fēng)險。
查詢是否開啟混合持久化可以使用 config get aof-use-rdb-preamble 命令,其中 yes 表示已經(jīng)開啟混合持久化,no 表示關(guān)閉。
需要注意的是,在非必須進(jìn)行持久化的業(yè)務(wù)中,可以關(guān)閉持久化,這樣可以有效的提升 Redis 的運行速度,不會出現(xiàn)間歇性卡頓的困擾。
八 Redis 主從復(fù)制
8.1 什么是主從復(fù)制
持久化保證了即使 Redis 服務(wù)重啟也不會丟失數(shù)據(jù),因為 Redis 服務(wù)重啟后會將硬盤上持久化的數(shù)據(jù)恢復(fù)到內(nèi)存中,但是當(dāng) Redis 服務(wù)器的硬盤損壞了可能會導(dǎo)致數(shù)據(jù)丟失,不過通過 Redis 的主從復(fù)制機制就可以避免這種單點故障,如下圖:
- 主 Redis 中的數(shù)據(jù)有兩個副本( replication )即從 redis1 和從 redis2 ,即使一臺 Redis 服務(wù)
器宕機其它兩臺 Redis 服務(wù)也可以繼續(xù)提供服務(wù)。 - 主 Redis 中的數(shù)據(jù)和從 Redis 上的數(shù)據(jù)保持實時同步,當(dāng)主 Redis 寫入數(shù)據(jù)時通過主從復(fù)制機制
會復(fù)制到兩個從 Redis 服務(wù)上。 - 只有一個主 Redis ,可以有多個從 Redis 。
- 主從復(fù)制不會阻塞 master ,在同步數(shù)據(jù)時, master 可以繼續(xù)處理 client 請求。
- 一個 Redis 可以即是主又是從服務(wù)器。
8.2 實現(xiàn)原理
1 數(shù)據(jù)同步
Redis在2.8及以上版本使用psync命令完成主從數(shù)據(jù)同步,同步過程分為:全量復(fù)制和部分復(fù)制
- 全量復(fù)制:一般用于初次復(fù)制場景,Redis早期支持的復(fù)制功能只有全量復(fù)制,它會把主節(jié)點全部
數(shù)據(jù)一次性發(fā)送給從節(jié)點,當(dāng)數(shù)據(jù)量較大時,會對主從節(jié)點和網(wǎng)絡(luò)造成很大的開銷。 - 部分復(fù)制:用于處理在主從復(fù)制中因網(wǎng)絡(luò)閃斷等原因造成的數(shù)據(jù)丟失場景,當(dāng)從節(jié)點再次連上主節(jié)
點后,如果條件允許,主節(jié)點會補發(fā)丟失數(shù)據(jù)給從節(jié)點。因為補發(fā)的數(shù)據(jù)遠(yuǎn)遠(yuǎn)小于全量數(shù)據(jù),可以
有效避免全量復(fù)制的過高開銷。
部分復(fù)制是對老版復(fù)制的重大優(yōu)化,有效避免了不必要的全量復(fù)制操作。因此當(dāng)使用復(fù)制功能時,盡量采用2.8以上版本的Redis。
psync命令運行需要以下組件支持:
- 主Redis的復(fù)制偏移量(replication offset)和從Redis的復(fù)制偏移量。
- 主Redis的復(fù)制積壓緩沖區(qū)(replication backlog)。
- Redis的運行ID(run ID)。
2 runid
Redis 服務(wù)器的隨機標(biāo)識符(用于 Sentinel 和集群),重啟后就會改變;當(dāng)復(fù)制時發(fā)現(xiàn)和之前的 run_id 不同時,將會對數(shù)據(jù)全量同步。
3 復(fù)制偏移量
通過對比主從節(jié)點的復(fù)制偏移量,可以判斷主從節(jié)點數(shù)據(jù)是否一致。
參與復(fù)制的主從節(jié)點都會維護(hù)自身復(fù)制偏移量。主節(jié)點(master)在處理完寫入命令后,會把命令
的字節(jié)長度做累加記錄,統(tǒng)計信息在info relication中的master_repl_offset指標(biāo)中:
從節(jié)點(slave)每秒鐘上報自身的復(fù)制偏移量給主節(jié)點,因此主節(jié)點也會保存從節(jié)點的復(fù)制偏移
量,統(tǒng)計指標(biāo)如下:
從節(jié)點在接收到主節(jié)點發(fā)送的命令后,也會累加記錄自身的偏移量。統(tǒng)計信息在info relication中 的slave_repl_offset指標(biāo)中:
4 全量同步
Redis 的全量同步過程主要分三個階段:
- 同步快照階段: Master 創(chuàng)建并發(fā)送快照給 Slave , Slave 載入并解析快照。 Master 同時將此階段所產(chǎn)生的新的寫命令存儲到緩沖區(qū)。
- 同步寫緩沖階段: Master 向 Slave 同步存儲在緩沖區(qū)的寫操作命令。
- 同步增量階段: Master 向 Slave 同步寫操作命令。
5 增量同步
- Redis 增量同步主要指 Slave 完成初始化后開始正常工作時, Master 發(fā)生的寫操作同步到
Slave 的過程。 - 通常情況下, Master 每執(zhí)行一個寫命令就會向 Slave 發(fā)送相同的寫命令,然后 Slave 接收并執(zhí)
行。
8.3 主從配置
8.3.1 安裝
# 第一步:安裝 C 語言需要的 GCC 環(huán)境 yum install -y gcc-c++ yum install -y wget # 第二步:下載并解壓縮 Redis 源碼壓縮包 wget http://download.redis.io/releases/redis-5.0.4.tar.gz tar -zxf redis-5.0.4.tar.gz # 編譯 Redis 源碼,進(jìn)入 redis-3.2.9 目錄,執(zhí)行編譯命令 cd redis-5.0.4 make # 安裝 Redis ,需要通過 PREFIX 指定安裝路徑 make install PREFIX=/kkb/server/redis # 將配置文件復(fù)制過來 cp /root/redis-5.0.4/redis.conf /kkb/server/redis/bin/# 配置監(jiān)聽ip和端口 守護(hù)模式運行 bind daemonize yes # 先打開服務(wù)端 ./redis-server ./redis.conf # 在打開客戶端 /kkb/server/redis/bin/redis-cli # 設(shè)置客戶端 訪問 服務(wù)端的 ip 和端口號 redis-cli -h 192.168.56.102 -p 63798.3.2 配置說明
- 主Redis配置 無需配置
- 修改從服務(wù)器上的 redis.conf 文件:
九 Redis 哨兵機制
9.1 Redis Sentinel 工作原理分析
1 為什么要用到哨兵
哨兵(Sentinel)主要是為了解決在主從復(fù)制架構(gòu)中出現(xiàn)宕機的情況,主要分為兩種情況:
-
1).從Redis宕機
這個相對而言比較簡單,在Redis中從庫重新啟動后會自動加入到主從架構(gòu)中,自動完成同步數(shù)據(jù)。在Redis2.8版本后,主從斷線后恢復(fù)的情況下實現(xiàn)增量復(fù)制。 -
2).主Redis宕機
這個相對而言就會復(fù)雜一些,需要以下2步才能完成
a. 在從數(shù)據(jù)庫中執(zhí)行SLAVEOF NO ONE命令,斷開主從關(guān)系并且提升為主庫繼續(xù)服務(wù)
b. 第二步,將主庫重新啟動后,執(zhí)行SLAVEOF命令,將其設(shè)置為其他庫的從庫,這時數(shù)據(jù)就能更新回來由于這個手動完成恢復(fù)的過程其實是比較麻煩的并且容易出錯,所以Redis提供的哨兵(sentinel)的功能來解決。
2 哨兵機制(sentinel)的高可用
Sentinel(哨兵)是Redis 的高可用性解決方案:由一個或多個Sentinel 實例 組成的Sentinel 系統(tǒng)可以監(jiān)視任意多個主服務(wù)器,以及這些主服務(wù)器屬下的所有從服務(wù)器,并在被監(jiān)視的主服務(wù)器進(jìn)入下線狀態(tài)時,自動將下線主服務(wù)器屬下的某個從服務(wù)器升級為新的主服務(wù)器。 原有主節(jié)點恢復(fù)將降為從節(jié)點。
3 哨兵的定時監(jiān)控
任務(wù)1:每個哨兵節(jié)點每10秒會向主節(jié)點和從節(jié)點發(fā)送info命令獲取最新拓?fù)浣Y(jié)構(gòu)圖,哨兵配置時只要配置對主節(jié)點的監(jiān)控即可,通過向主節(jié)點發(fā)送info,獲取從節(jié)點的信息,并當(dāng)有新的從節(jié)點加入時可以馬上感知到。
任務(wù)2:每個哨兵節(jié)點每隔2秒會向redis數(shù)據(jù)節(jié)點的指定頻道上發(fā)送該哨兵節(jié)點對于主節(jié)點的判斷以及當(dāng)前哨兵節(jié)點的信息,同時每個哨兵節(jié)點也會訂閱該頻道,來了解其它哨兵節(jié)點的信息及對主節(jié)點的判斷,其實就是通過消息publish和subscribe來完成的。
任務(wù)3:每隔1秒每個哨兵會向主節(jié)點、從節(jié)點及其余哨兵節(jié)點發(fā)送一次ping命令做一次心跳檢測,這個也是哨兵用來判斷節(jié)點是否正常的重要依據(jù)。
防止哨兵節(jié)點掛機,選用3個哨兵節(jié)點。
主觀下線:所謂主觀下線,就是單個sentinel認(rèn)為某個服務(wù)下線(有可能是接收不到訂閱,之間的網(wǎng)絡(luò)不通等等原因)。SDOWN
sentinel會以每秒一次的頻率向所有與其建立了命令連接的實例(master,從服務(wù),其他sentinel)發(fā)ping命令,通過判斷ping回復(fù)是有效回復(fù),還是無效回復(fù)來判斷實例時候在線(對該sentinel來說是“主觀在線”)。
sentinel配置文件中的down-after-milliseconds設(shè)置了判斷主觀下線的時間長度,如果實例在down-after-milliseconds毫秒內(nèi),返回的都是無效回復(fù),那么sentinel回認(rèn)為該實例已(主觀)下線,修改其flags狀態(tài)為SRI_S_DOWN。如果多個sentinel監(jiān)視一個服務(wù),有可能存在多個sentinel的down-after-milliseconds配置不同,這個在實際生產(chǎn)中要注意。
客觀下線:當(dāng)主觀下線的節(jié)點是主節(jié)點時,此時該哨兵3節(jié)點會通過指令sentinel is-masterdown-by-addr尋求其它哨兵節(jié)點對主節(jié)點的判斷,如果其他的哨兵也認(rèn)為主節(jié)點主觀線下了,則當(dāng)認(rèn)為主觀下線的票數(shù)超過了quorum(選舉)個數(shù),此時哨兵節(jié)點則認(rèn)為該主節(jié)點確實有問題,這樣就客觀下線了,大部分哨兵節(jié)點都同意下線操作,也就說是客觀下線 ODOWN 。
4 哨兵lerder選舉流程
如果主節(jié)點被判定為客觀下線之后,就要選取一個哨兵節(jié)點來完成后面的故障轉(zhuǎn)移工作,選舉出一個
leader的流程如下:
- 每個在線的哨兵節(jié)點都可以成為領(lǐng)導(dǎo)者,當(dāng)它確認(rèn)(比如哨兵3)主節(jié)點下線時,會向其它哨兵發(fā)is-master-down-by-addr命令,征求判斷并要求將自己設(shè)置為領(lǐng)導(dǎo)者,由領(lǐng)導(dǎo)者處理故障轉(zhuǎn)移;
- 當(dāng)其它哨兵收到此命令時,可以同意或者拒絕它成為領(lǐng)導(dǎo)者;
- 如果哨兵3發(fā)現(xiàn)自己在選舉的票數(shù)num 大于等于 (sentinels)/2+1時,將成為領(lǐng)導(dǎo)者,如果沒有超過,繼續(xù)選舉…………
如果Sentinel收到其他Sentinel的投票請求,在以下兩種情況下會把自己的票投給請求的Sentinel實例:
5 自動故障轉(zhuǎn)移機制
在從節(jié)點中選擇新的主節(jié)點
sentinel狀態(tài)數(shù)據(jù)結(jié)構(gòu)中保存了主服務(wù)的所有從服務(wù)信息,領(lǐng)頭sentinel按照如下的規(guī)則從從服務(wù)列表中
挑選出新的主服務(wù)
就繼續(xù)選擇
有就繼續(xù)
更新主從狀態(tài)
- 通過slaveof no one命令,讓選出來的從節(jié)點成為主節(jié)點;并通過slaveof命令讓其他節(jié)點成為其從節(jié)點。
- 將已下線的主節(jié)點設(shè)置成新的主節(jié)點的從節(jié)點,當(dāng)其回復(fù)正常時,復(fù)制新的主節(jié)點,變成新的主節(jié)點的從節(jié)點
同理,當(dāng)已下線的服務(wù)重新上線時,sentinel會向其發(fā)送slaveof命令,讓其成為新主的從
9.2 哨兵進(jìn)程的作用
- 監(jiān)控( Monitoring ): 哨兵( sentinel ) 會不斷地檢查你的 Master 和 Slave 是否運作正常。
- 提醒( Notification ): 當(dāng)被監(jiān)控的某個 Redis 節(jié)點出現(xiàn)問題時, 哨兵( sentinel ) 可以通過 API向管理員或者其他應(yīng)用程序發(fā)送通知。
- 自動故障遷移( Automatic failover ):當(dāng)一個 Master 不能正常工作時,哨兵( sentinel ) 會開始一次自動故障遷移操作
推薦的sentinel 集群是1主 2或多從,3哨兵;sentinel的啟動 是redis-sentinel
9.3 哨兵配置
sentinel.conf
# 設(shè)置端口 port 26379 # 是否守護(hù)進(jìn)程啟動 daemonize no # 守護(hù)進(jìn)程運行的時候需要保留pidfile pidfile /var/run/redis-sentinel.pid # 日志文件 logfile "/root/log/sentinel.log" ## sentinel monitor master-group-name hostname port quorum sentinel monitor mymaster 127.0.0.1 6379 3 # down-after-milliseconds,超過多少毫秒跟一個redis實例斷了連接(ping不通),哨兵就可能認(rèn)為這個redis實例掛了 sentinel down-after-milliseconds mymaster 30000 # parallel-syncs,新的master別切換之后,同時有多少個slave被切換到去連接新master,重新做同步,數(shù)字越低,花費的時間越多 # 比如:master宕機了,4個slave中有1個切換成了master,剩下3個slave就要掛到新的master上面去 # 這個時候,如果parallel-syncs是1,那么3個slave,一個一個地掛接到新的master上面去,1個掛接完,而且從新的master sync完數(shù)據(jù)之后,再掛接下一個。 # 如果parallel-syncs是3,那么一次性就會把所有slave掛接到新的master上去 sentinel parallel-syncs mymaster 1 #failover-timeout,執(zhí)行故障轉(zhuǎn)移的timeout超時時長,Default is 3 minutes. sentinel failover-timeout mymaster 180000quorum的解釋如下:
-
(1)至少多少個哨兵要一致同意,master進(jìn)程掛掉了,或者slave進(jìn)程掛掉了,或者要啟動一個故障轉(zhuǎn)移操作,quorum是用來識別故障的,真正執(zhí)行故障轉(zhuǎn)移的時候,還是要在哨兵集群執(zhí)行選舉,選舉一個哨兵進(jìn)程出來執(zhí)行故障轉(zhuǎn)移操作 。
-
(2)假設(shè)有5個哨兵,quorum設(shè)置了2,那么如果5個哨兵中的2個都認(rèn)為master掛掉了; 2個哨兵中的一個就會做一個選舉,選舉一個哨兵出來,執(zhí)行故障轉(zhuǎn)移; 如果5個哨兵中有3個哨兵都是運行的, 那么故障轉(zhuǎn)移才會被允許執(zhí)行。
原文是:Note that whatever is the ODOWN quorum, a Sentinel will require to be selected by the majority of the known Sentinels in order to start a failover, so no failover can be performed in minority.
如果有一個sentinel:
實際情況,其實單純從代碼的情況,其實1個Sentinel就能完成主觀下線(sdown,Subjectively Down),客觀下線(odown, Objectively Down) 的判斷,自動發(fā)現(xiàn) Sentinel 和從服務(wù)器,并且完成故障轉(zhuǎn)移。
如果有2個sentinel
2 個的一半以上 2;
如果哨兵集群僅僅部署了個2個哨兵實例,quorum=1。s1和s2中只要有1個哨兵認(rèn)為master宕機就可以還行切換,同時s1和s2中會選舉出一個哨兵來執(zhí)行故障轉(zhuǎn)移。同時這個時候,需要majority,也就是大多數(shù)哨兵都是運行的,2個哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=3),如果一個節(jié)點掛了那么哨兵也就掛了,哨兵只剩下一個,那么就無法完成故障轉(zhuǎn)移。
如果是經(jīng)典的3節(jié)點哨兵集群
Configuration: quorum = 2。
majority=2(majority不能配置,由redis自行計算所得。超過一半的最小值)
如果M1所在機器宕機了,那么三個哨兵還剩下2個,S2和S3可以一致認(rèn)為master宕機,然后選舉
出一個來執(zhí)行故障轉(zhuǎn)移。同時3個哨兵的majority是2,所以還剩下的2個哨兵運行著,就可以允許
執(zhí)行故障轉(zhuǎn)移。
這就是經(jīng)典的sentinel3個節(jié)點的集群。節(jié)省資源的同時又滿足了高可用。
總結(jié)
以上是生活随笔為你收集整理的第一节 Redis 使用及哨兵集群 2022-1-2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 笔试:常见题目总结,andro
- 下一篇: IBM小型机+Oracle数据库+EMC