DBA數(shù)據(jù)庫筆記之(七)Redis基礎(chǔ)知識(shí)

Redis常見類型及常見命令

redis應(yīng)用場景

  1. 緩存
  2. 計(jì)數(shù)器
  3. 排行榜
  4. 地理位置
  5. 隊(duì)列
  6. 評論和彈幕

Redis6安裝啟動(dòng)

redis官網(wǎng)安裝教程

  • 源碼編譯安裝
# 源碼編譯安裝
wget https://download.redis.io/releases/redis-6.2.13.tar.gz
# 解壓
tar zxvf redis-6.2.13.tar.gz
# 安裝redis依賴
yum install gcc -y
# 進(jìn)入解壓包
cd redis-6.2.13/
# PREFIX指定軟件安裝的路徑
make && make install PREFIX=/usr/local/redis6
# 創(chuàng)建其它目錄文件
make /data/redis7001/{conf,data,log} -p
  • 編輯配置文件
vim /data/redis7001/conf/redis.conf
# 內(nèi)容
# 啟動(dòng)端口
port 7001
# yes后臺(tái)運(yùn)行
daemonize yes
# 指定redis進(jìn)程pid文件路徑
pidfile "/data/redis7001/data/redis.pid"
# redis日志的詳細(xì)程度
loglevel notice
# 日志文件的路徑和文件名
logfile "/data/redis7001/log/redis.log"
# 支持的數(shù)據(jù)庫數(shù)量
databases 16
# redis的快照條件;1800秒以內(nèi)只要有一次更改就執(zhí)行一次快照保存(rdb落盤)
#save 1800 1
# rdb文件名稱
dbfilename "dump.rdb"
# 持久性文件的目錄
dir "/data/redis7001/data"

# 運(yùn)行使用的最大內(nèi)存量
maxmemory 1gb
# 當(dāng)redis內(nèi)存達(dá)到上限時(shí)所使用的淘汰策略
maxmemory-policy volatile-lru

# 是否開啟aof持久化
appendonly no
# aof日志文件的名稱
appendfilename "appendonly.aof"
# 慢查詢時(shí)間的預(yù)值 單位 微秒
slowlog-log-slower-than 10000
# 慢查詢?nèi)罩镜淖畲箝L度,最多記錄多少條慢查詢
slowlog-max-len 128

# redis的密碼;生產(chǎn)環(huán)境建議設(shè)置密碼
requirepass "IdfaUqTcdad82"
  • 啟動(dòng)并登錄redis
/usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
# 查看是否啟動(dòng)
ps -ef | grep redis 

# 修改環(huán)境變量
vim /etc/profile
# 增加
export PATH="/usr/local/redis6/bin:$PATH"
source /etc/profile

redis-cli -v

# 登錄redis
redis-cli -p 7001 -a IdfaUqTcdad82
  • redis常用數(shù)據(jù)類型
數(shù)據(jù)類型 描述
string 字符串類型,一個(gè)key對應(yīng)一個(gè)value
hash 鍵值對集合
list 字符串列表,按插入順序排隊(duì)
set string類型的無序集合,集合中元素是唯一的
zset 有序集合,它類似于SET,但每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè)分?jǐn)?shù)(score),分?jǐn)?shù)用來對元素進(jìn)行排序
HyperlogLog 用于估計(jì)集合基數(shù)的數(shù)據(jù)類型
bitmap 用戶存儲(chǔ)位數(shù)據(jù),適用于布爾值和計(jì)數(shù)值
GEO 存儲(chǔ)地理位置數(shù)據(jù),支持地理位置相關(guān)操作

常用數(shù)據(jù)類型的用法

  • string
# 設(shè)置
set string_test aaa
# 獲取
get string_test
# 刪除
del string_test

# 計(jì)數(shù)
incr count_test
# 增加指定計(jì)數(shù)量
incrby count_test 3
# 減去
decr count_test
# 減去指定數(shù)量
decrby count_test 2
# 查詢
get count_test
  • hash
# 設(shè)置
hset user:01 name martin
hset user:01 age 18
# 獲取
hget user:01 name
# 獲取所有字段和值
hgetall user:01
# 獲取hash表中字段數(shù)量
hlen user:01
# 獲取hash表中所有字段
hkeys user:01
# 刪除某個(gè)字段
hdel user:01 age
  • list
# 插入列表頭部
lpush list_test aaa
lpush list_test bbb
# 獲取所有元素
lrange list_test 0 -1
# 插入到列表尾部
rpush list_test ccc
# 獲取指定范圍的元素
lrange list_test 0 0
# 查詢前兩個(gè)元素
lrange list_test 0 1
# 獲取列表長度
llen list_test
# 移除并且獲取列表的第一個(gè)元素
lpop list_test
# 移除并且獲取列表的最后一個(gè)元素
rpop list_test
  • set
# 添加元素
sadd set_test one
# 添加多個(gè)元素2
sadd set_test two three
# 返回集合中所有元素
smembers set_test
# 判斷元素是否在集合中 返回1代表存在;0不存在
sismember set_test onne
# 刪除集合中的元素
srem set_test two
  • zset
# 添加元素
zadd zset_test 1 zhangshan
zadd zset_test 2 lishi
zadd zset_test 3 wangwu
# 查看元素
zrange zset_test 0 -1
# 查看元素和分?jǐn)?shù)
zrange zset_test 0 -1 withscores
# 獲取指定元素的分?jǐn)?shù)
zscore zset_test "lishi"
# 從有序集合中移除元素
zrem zset_test "lishi"
# 獲取有序集合元素個(gè)數(shù)
zcard zset_test
  • HyperlogLog
# 添加元素
pfadd hll_test "apple" "banana" "cherry"
# 獲取集合中元素?cái)?shù)量
pfcount hll_test
  • bitmaps
# 簽到場景
# 第一天有簽到記錄
setbit user:1001 0 1
# 第二天有簽到記錄
setbit user:1001 1 1
# 第三天沒有簽到記錄
setbit user:1001 2 0
setbit user:1001 4 1
# 查看某一天是否簽到
getbit user:1001 1
getbit user:1001 2
# 統(tǒng)計(jì)簽到數(shù)量
bitcount user:1001
  • GEO
# 增加地理位置
geoadd geo_test 20 30 "a"
geoadd geo_test 40 60 "b"
# 求a和b之前的距離 單位km
geodist geo_test "a" "b" km
# 查詢指定范圍的地點(diǎn) 經(jīng)度 25 緯度 35 范圍1000km以內(nèi)的地點(diǎn)
georadius geo_test 25 35 1000 km

redis常用管理命令

  • 在redis中認(rèn)證
redis-cli -p 7001 -a IdfaUqTcdad82
或者
redis-cli -p 7001
auth IdfaUqTcdad82
  • 查看服務(wù)器的各種信息
info 
# 查看某一塊的信息
info CPU

redis info官方文檔

  • 查看所有的key
keys *
  • 查看某個(gè)前綴的key
keys name*
  • 找到某個(gè)前綴的key并刪除
# 查找以name開頭的key。--scan 掃描,--pattern 模式匹配 
redis-cli -p 7001 -a IdfaUqTcdad82 --scan --pattern "name*" 
# 并且刪除,xargs 代表對前面的結(jié)果進(jìn)行處理,-L 5000  每次處理5000條數(shù)據(jù)
redis-cli -p 7001 -a IdfaUqTcdad82 --scan --pattern "name*" | xargs -L 5000 redis-cli -p 7001 -a IdfaUqTcdad82 del
  • 重命名key
set hehe 1111
# 改名,重復(fù)會(huì)覆蓋
rename hehe hehe_bak
get hehe_bak

或者
set one 111
# renamenx 新名字必須是之前不存在的
renamenx one two
  • 判斷key是否存在
# 返回 1 存在,0不存在
exists hehe
  • 查看key類型
type hehe_bak
  • 查看key大小
# 單位字節(jié)
memory usage hehe_bak
  • 查看key的內(nèi)部信息
debug object hehe_bak
# key存放的內(nèi)存地址:引用計(jì)數(shù):鍵的編碼方式:key的序列化長度:key的lru值,最近最少使用的值:鍵自從上一次訪問的空閑時(shí)間
  • 設(shè)置key的過期時(shí)間
set martin 111
# 300秒過期
expire martin 300
# 查看過期時(shí)間
ttl martin
# 移除key的過期時(shí)間
persist martin
  • 發(fā)布訂閱
# 第一個(gè)窗口
SUBSCRIBE chat
# 第二個(gè)窗口
PUBLISH chat "hello redis"
# 第一個(gè)窗口就會(huì)收到對應(yīng)的消息
  • 切換數(shù)據(jù)庫
# 默認(rèn)在0數(shù)據(jù)庫,切換到2
select 2
set aaa 111
info keyspace
  • 返回當(dāng)前庫key的數(shù)量
dbsize
  • 清空當(dāng)前數(shù)據(jù)庫的所有key
flushdb
  • 清空redis
flushall
  • 查看和修改配置
# 查看所有配置
config get *
# 查看最大內(nèi)存
config get maxmemory
# 查看包含關(guān)鍵字的配置
config get *memory*
# 修改配置
config set maxmemory 2G
# 將修改的配置持久化到配置文件
config rewrite

# 查看配置文件
vim /data/redis7001/conf/redis.conf
  • 獲取慢查詢?nèi)罩?/li>
# 獲取5條
slowlog get 5
# 查看與慢查詢有關(guān)的參數(shù)
config get slow*
# slowlog-max-len 最多記錄多少條慢查詢記錄;slowlog-log-slower-than 超過這個(gè)時(shí)間就會(huì)記錄到慢查詢,單位微秒
  • 查看客戶端連接
client list
  • 殺掉某個(gè)連接
client kill 192.168.12.162:50732
  • 命令行直接執(zhí)行命令
redis-cli -p 7001 -a IdfaUqTcdad82 info
redis-cli -p 7001 -a IdfaUqTcdad82 client list
  • 讓redis服務(wù)崩潰
debug segfault
ps -ef | grep 7001
# 啟動(dòng)
/usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
  • 關(guān)閉redis服務(wù)器
# 在redis命令里執(zhí)行,建議此方式關(guān)閉redis
shutdown

詳解Redis RDB

把內(nèi)存中的數(shù)據(jù)存儲(chǔ)到磁盤中,當(dāng)redis重啟會(huì)讀取RDB文件恢復(fù)數(shù)據(jù)

幾種RDB持久化場景

  • 手動(dòng)執(zhí)行RDB持久化
# 這個(gè)命令會(huì)在主線程執(zhí)行,會(huì)導(dǎo)致阻塞,線上環(huán)境禁止使用
save
# 啟用子進(jìn)程來持久化,避免主線程阻塞
bgsave
# 查看數(shù)據(jù)目錄
config get dir
# 確定bgsave是否正確執(zhí)行,查看RDB相關(guān)參數(shù)
info persistence

loading:0 ;當(dāng)前是否在進(jìn)行RDB文件的加載操作
current_cow_size:0 ;寫時(shí)復(fù)制技術(shù)占用的內(nèi)存
current_cow_size_age:0 ;上一次current_cow_size的時(shí)間,單位秒
current_fork_perc:0.00 ;當(dāng)前fork進(jìn)程的進(jìn)度百分比
current_save_keys_processed:0 ;當(dāng)前RDB操作已處理keys的數(shù)量
current_save_keys_total:0 ;當(dāng)前RDB持久化進(jìn)程一共需要處理的鍵數(shù)量
rdb_changes_since_last_save:0 ;從上一次執(zhí)行RDB以來更改的數(shù)量
rdb_bgsave_in_progress:0 ;是否有RDB持久化的后臺(tái)進(jìn)程正在進(jìn)行,0表示RDB已經(jīng)操作完成
rdb_last_save_time:1694702221 ;上次執(zhí)行RDB持久化的時(shí)間戳
rdb_last_bgsave_status:ok ;上次執(zhí)行RDB持久化的執(zhí)行狀態(tài)
rdb_last_bgsave_time_sec:0 ;上一次執(zhí)行RDB持久化所花費(fèi)的時(shí)間
rdb_current_bgsave_time_sec:-1 ;當(dāng)前正在執(zhí)行的RDB持久化操作花費(fèi)的時(shí)間
rdb_last_cow_size:409600 ;上一次RDB持久化操作中使用的寫時(shí)復(fù)制技術(shù)的內(nèi)存大小
aof_enabled:0 ;
aof_rewrite_in_progress:0 ;
aof_rewrite_scheduled:0 ;
aof_last_rewrite_time_sec:-1 ;
aof_current_rewrite_time_sec:-1 ;
aof_last_bgrewrite_status:ok ;
aof_last_write_status:ok ;
aof_last_cow_size:0 ;
module_fork_in_progress:0 ;
module_fork_last_cow_size:0 ;

  • 配置自動(dòng)執(zhí)行RDB持久化
# 查看配置文件
vim /data/redis7001/conf/redis.conf

# 啟動(dòng)端口
port 7001
# yes后臺(tái)運(yùn)行
daemonize yes
# 指定redis進(jìn)程pid文件路徑
pidfile "/data/redis7001/data/redis.pid"
# redis日志的詳細(xì)程度
loglevel notice
# 日志文件的路徑和文件名
logfile "/data/redis7001/log/redis.log"
# 支持的數(shù)據(jù)庫數(shù)量
databases 16

# redis的快照條件;1800秒以內(nèi)只要有一次更改就執(zhí)行一次快照保存(rdb落盤)
#??save 1800 1  新增下列三行參數(shù)
save 900 1
save 300 10
save 60 10000

# rdb文件名稱
dbfilename "dump.rdb"
# 持久性文件的目錄
dir "/data/redis7001/data"

# 運(yùn)行使用的最大內(nèi)存量
maxmemory 1gb
# 當(dāng)redis內(nèi)存達(dá)到上限時(shí)所使用的淘汰策略
maxmemory-policy volatile-lru

# 是否開啟aof持久化
appendonly no
# aof日志文件的名稱
appendfilename "appendonly.aof"
# 慢查詢時(shí)間的預(yù)值 單位 微秒
slowlog-log-slower-than 10000
# 慢查詢?nèi)罩镜淖畲箝L度,最多記錄多少條慢查詢
slowlog-max-len 128

# redis的密碼;生產(chǎn)環(huán)境建議設(shè)置密碼
requirepass "IdfaUqTcdad82"


# 重啟 或者在redis命令行執(zhí)行
config set save "900 1"
  • 其他觸發(fā)RDB持久化的場景

在新建redis主從復(fù)制的時(shí)候,主節(jié)點(diǎn)會(huì)執(zhí)行一次bgsave保存RDB文件到本地,然后再發(fā)送給從節(jié)點(diǎn);
在執(zhí)行shutdown的時(shí)候,如果沒有開啟aof就會(huì)自動(dòng)執(zhí)行bgsave將內(nèi)存中的數(shù)據(jù)進(jìn)行落盤,保證在啟動(dòng)的時(shí)候數(shù)據(jù)不會(huì)丟失。

RDB擴(kuò)展

  • 備份恢復(fù)測試
  • RDB壓縮
# 查看配置參數(shù) 默認(rèn)開啟,建議開啟
config get rdbcompression
  • 臨時(shí)修改RDB路徑
# 創(chuàng)建目錄
mkdir /data/redis7001/tem_data
# 修改路徑
config get dir
config set dir /data/redis7001/tem_data/

# 測試
bgsave

RDB注意事項(xiàng)

  • bgsave對redis也是有影響的
    建議在從庫落盤
  • 單機(jī)多實(shí)例的RDB備份盡量錯(cuò)開
  • RDB持久化并不能保證所有數(shù)據(jù)落盤

詳解Redis AOF

AOF介紹

  • 什么是AOF?

它會(huì)記錄Redis收到的每一條寫命令,如果Redis發(fā)生了崩潰,重啟之后就會(huì)更具日志文件的內(nèi)容將寫操作重頭到尾執(zhí)行一次,以完成數(shù)據(jù)的恢復(fù)。

  • 開啟AOF日志
vim /data/redis7001/conf/redis.conf
# 修改參數(shù)
appendonly yes
# 啟動(dòng)

# 查看配置
config get appendonly
# 動(dòng)態(tài)修改
config set appendonly yes
  • AOF的內(nèi)容
# 默認(rèn)在數(shù)據(jù)目錄

AOF相關(guān)配置

  • AOF持久化選項(xiàng)
config get appendfsync

everysec :表示每秒寫回,每個(gè)寫命令執(zhí)行完,只是先把日志寫到AOF的內(nèi)存緩存區(qū),每隔一秒把緩沖區(qū)中的內(nèi)容寫到磁盤
always :表示同步寫回,每個(gè)寫命令執(zhí)行完立馬同步到磁盤
no :表示操作系統(tǒng)控制寫回,每個(gè)寫命令執(zhí)行完只是先把日志寫到AOF的內(nèi)存緩存區(qū),由操作系統(tǒng)決定何時(shí)將緩存區(qū)的內(nèi)容寫回到磁盤
配置建議: 對性能要求很高并且對數(shù)據(jù)可靠性要求不高 no;高可靠性保證always;允許數(shù)據(jù)有一點(diǎn)丟失,性能不受太大影響 everysec。

  • AOF重寫機(jī)制

如果實(shí)例運(yùn)行比較久并且修改比較頻繁那么Redis的AOF文件可能會(huì)比較大,通過AOF重寫機(jī)制解決。會(huì)把AOF的內(nèi)容重寫只保留可以恢復(fù)數(shù)據(jù)的最小指令集。
AOF文件為什么可以變?。?/p>

  1. 舊日志文件中的多條命令再重寫后新日志中就變成了一條命令
  2. 已經(jīng)過期的key就不再寫入新的AOF文件中
# 手動(dòng)觸發(fā)一次AOF重寫
bgrewriteaof

# 配置參數(shù)讓AOF自動(dòng)觸發(fā)重寫,超過一次這個(gè)大小就會(huì)觸發(fā)一次AOF重寫
config get "auto-aof-rewrite-min-size"
# 當(dāng)前AOF文件空間超過上一次重寫后AOF文件空間的多少百分比就會(huì)觸發(fā)重寫
config get "auto-aof-rewrite-percentage"
  • AOF相關(guān)狀態(tài)參數(shù)
info persistence

loading:0 ;當(dāng)前是否在進(jìn)行RDB文件的加載操作
current_cow_size:0 ;寫時(shí)復(fù)制技術(shù)占用的內(nèi)存
current_cow_size_age:0 ;上一次current_cow_size的時(shí)間,單位秒
current_fork_perc:0.00 ;當(dāng)前fork進(jìn)程的進(jìn)度百分比
current_save_keys_processed:0 ;當(dāng)前RDB操作已處理keys的數(shù)量
current_save_keys_total:0 ;當(dāng)前RDB持久化進(jìn)程一共需要處理的鍵數(shù)量
rdb_changes_since_last_save:0 ;從上一次執(zhí)行RDB以來更改的數(shù)量
rdb_bgsave_in_progress:0 ;是否有RDB持久化的后臺(tái)進(jìn)程正在進(jìn)行,0表示RDB已經(jīng)操作完成
rdb_last_save_time:1694702221 ;上次執(zhí)行RDB持久化的時(shí)間戳
rdb_last_bgsave_status:ok ;上次執(zhí)行RDB持久化的執(zhí)行狀態(tài)
rdb_last_bgsave_time_sec:0 ;上一次執(zhí)行RDB持久化所花費(fèi)的時(shí)間
rdb_current_bgsave_time_sec:-1 ;當(dāng)前正在執(zhí)行的RDB持久化操作花費(fèi)的時(shí)間
rdb_last_cow_size:409600 ;上一次RDB持久化操作中使用的寫時(shí)復(fù)制技術(shù)的內(nèi)存大小
aof_enabled:0 ;AOF是否開啟
aof_rewrite_in_progress:0 ;是否有AOF重寫操作正在進(jìn)行
aof_rewrite_scheduled:0 ;是否有AOF重寫操作已經(jīng)被調(diào)度
aof_last_rewrite_time_sec:-1 ;上一次AOF重寫操作的執(zhí)行時(shí)間
aof_current_rewrite_time_sec:-1 ;當(dāng)前正在執(zhí)行的AOF重寫操作花費(fèi)的時(shí)間
aof_last_bgrewrite_status:ok ;上一次AOF重寫操作的執(zhí)行狀態(tài)
aof_last_write_status:ok ;上一次AOF寫入操作的執(zhí)行狀態(tài)
aof_last_cow_size:0 ;上一次AOF操作中使用的cow機(jī)制內(nèi)存大小,cow=copy on write 寫時(shí)復(fù)制技術(shù)
module_fork_in_progress:0 ;
module_fork_last_cow_size:0 ;
aof_current_size:127 ;AOF當(dāng)前大小
aof_base_size:127 ;AOF基礎(chǔ)大小
aof_pending_rewrite:0 ;等待執(zhí)行AOF重寫的數(shù)量
aof_buffer_length:0 ;AOF緩沖區(qū)的大小
aof_rewrite_buffer_length:0 ;AOF重寫緩沖區(qū)的大小
aof_pending_bio_fsync:0 ;等待執(zhí)行AOF fsync操作的數(shù)量
aof_delayed_fsync:0 ;延遲執(zhí)行AOF fsync操作的數(shù)量

  • 重啟通過AOF恢復(fù)數(shù)據(jù)
  1. 寫入數(shù)據(jù)
  2. 關(guān)閉Redis并刪除RDB文件
shutdown
ps -ef | grep redis
cd /data/redis7001/data/
rm -rf dump.rdb
  1. 再啟動(dòng)Redis并確定數(shù)據(jù)
  • AOF異?;謴?fù)實(shí)驗(yàn)
  1. 構(gòu)造AOF異常場景
    修改AOF文件
  2. 重啟嘗試
shutdown
# 再重啟,無法正常啟動(dòng)
# 去查看日志
cd /data/redis7001/log/
tail -f redis.log
  1. 修復(fù)AOF文件
redis-check-aof --fix ../data/appendonly.aof
# 再啟動(dòng)redis

Redis 7.0 AOF變化

  • 安裝Redis7.0
  • 7.0配置AOF單獨(dú)目錄
  • 7.0的3個(gè)AOF文件
# 控制AOF文件夾的名字
config get appenddirname
# 開啟AOF
config set appendonly yes
# 進(jìn)入數(shù)據(jù)目錄,有個(gè)默認(rèn)的文件夾 appendonlydir
cd /data/redis7201/data/
cd appendonlydir 
ls

.base.rdb ;基礎(chǔ)的AOF,一個(gè)
.incr.aof ;增量AOF,可以有多個(gè)
.aof.manifest ;AOF的清單文件

AOF的一些相關(guān)問題

  • Redis采用AOF而不是WAL的原因

WAL :很多數(shù)據(jù)庫都是采用WAL,先把修改的數(shù)據(jù)記錄到日志中再進(jìn)行寫數(shù)據(jù)的提交,可以方便通過日志進(jìn)行數(shù)據(jù)恢復(fù)
AOF :先執(zhí)行寫命令,再把數(shù)據(jù)寫入到內(nèi)存中再寫日志文件;可以避免錯(cuò)誤命令的情況,AOF是在命令執(zhí)行后再記錄日志所以不會(huì)堵塞當(dāng)前的寫操作

  • AOF和RDB都開啟,重啟使用什么來恢復(fù)數(shù)據(jù)?
    Redis會(huì)使用AOF來恢復(fù)數(shù)據(jù),AOF數(shù)據(jù)更完整。
  • AOF的優(yōu)勢和劣勢
    優(yōu)勢:丟數(shù)據(jù)的概率低,且可讀性強(qiáng)
    劣勢:比RDB更占空間,因?yàn)橛涗浀氖敲恳粭l寫命令,且AOF恢復(fù)數(shù)據(jù)恢復(fù)速度慢很多,每一次讀寫都落盤性能也會(huì)有點(diǎn)問題。

建議:只做緩存建議都不開啟,當(dāng)數(shù)據(jù)庫用需要備份,可以在從庫開啟AOF和RDB落盤

Redis主從復(fù)制

準(zhǔn)備復(fù)制環(huán)境

  • 配置Redis主從復(fù)制
# 在從庫 
# 配置主庫的密碼
config set masterauth IdfaUqTcdad82
# 建立關(guān)系,配置主庫的ip和端口
replicaof 192.168.12.161 7001 

# 主從關(guān)系配置持久化
vim /data/redis7001/conf/redis.conf
# 新增參數(shù)
masterauth "IdfaUqTcdad82"
replicaof 192.168.12.161 7001 
  • 查看復(fù)制信息
# 在從庫redis
info replication
  • 確定數(shù)據(jù)同步

Redis復(fù)制原理

Redis復(fù)制原理.jpg

復(fù)制相關(guān)維護(hù)

  • 判斷主從延遲
# 在主節(jié)點(diǎn)執(zhí)行
info replication

slave0:ip=192.168.12.162,port=7001,state=online,offset=77035,lag=1
offset 表示從庫的偏移量
master_repl_offset:77035 主庫的偏移量,兩個(gè)一樣代表沒有延遲

  • 網(wǎng)絡(luò)閃斷導(dǎo)致全量復(fù)制
config get repl-backlog-size
  • 斷開復(fù)制關(guān)系
# 在從庫redis,情況主節(jié)點(diǎn)信息;斷開后不會(huì)清除已經(jīng)復(fù)制的數(shù)據(jù)
replicaof no one

復(fù)制架構(gòu)調(diào)整

  • 更換主節(jié)點(diǎn)
# 建立復(fù)制關(guān)系
config set masterauth IdfaUqTcdad82
replicaof 192.168.12.161 7001 
info replication

# 切換主節(jié)點(diǎn),切換主節(jié)點(diǎn)會(huì)刪除已經(jīng)復(fù)制的數(shù)據(jù)然后復(fù)制新主節(jié)點(diǎn)的數(shù)據(jù)
replicaof 192.168.12.163 7001 
  • 級聯(lián)復(fù)制配置
# 161->162->163
#在 162執(zhí)行
replicaof no one
config set masterauth IdfaUqTcdad82
replicaof 192.168.12.161 7001
# 在 163執(zhí)行
replicaof no one
config set masterauth IdfaUqTcdad82
replicaof 192.168.12.162 7001

# 查看復(fù)制狀態(tài)
info replication

# 如果需要配置持久化
config rewrite
  • 復(fù)制相關(guān)建議
  1. 建議在低峰時(shí)進(jìn)行新的主從配置
  2. 建議一個(gè)主節(jié)點(diǎn)別掛載太多的從節(jié)點(diǎn)
  3. 建議一臺(tái)物理機(jī)上運(yùn)行盡可能少的主節(jié)點(diǎn)

Redis主從之哨兵

哨兵的工作流程

Redis哨兵的工作流程.jpg

哨兵的選主邏輯

  • 首先:優(yōu)先級靠前的
# 參數(shù)越小優(yōu)先級越高
config get replica-priority
  • 其次:便宜量最大的
info replication
# salve_repl_offset 越大同步越靠前
  • 再次:ID最小的

部署哨兵集群

  • 配置一主兩從架構(gòu)
# 清空兩臺(tái)從庫配置關(guān)系
replicaof no one

# 每個(gè)實(shí)例修改
config set masterauth IdfaUqTcdad82
# 在兩個(gè)從庫執(zhí)行
replicaof 192.168.12.161 7001

# 在主庫查看信息
info replication
  • 配置哨兵文件
# 在每個(gè)Redis實(shí)例 創(chuàng)建哨兵文件夾(3個(gè))
mkdir /data/sentinel26379/{data,conf,log} -p
# 在每個(gè)節(jié)點(diǎn)增加配置文件(3個(gè))
vim /data/sentinel26379/conf/sentinel.conf

# 哨兵端口
port 26379
# 后臺(tái)運(yùn)行
daemonize yes
# 日志文件
logfile "/data/sentinel26379/log/26379.log"
# 數(shù)據(jù)目錄
dir /data/sentinel26379/data/
# sentinel監(jiān)控的Redis,監(jiān)控的集群名是mymaster,主的ip和端口,2表示至少有兩個(gè)哨兵同意就進(jìn)行故障切
sentinel monitor mymaster 192.16812.161 7001 2
# 被監(jiān)控Redis的密碼
sentinel auth-pass mymaster IdfaUgTcdad82
# 判斷Reids 主觀下線的閾值,單位毫秒
sentinel down-after-milliseconds mymaster 10000
  • 啟動(dòng)哨兵
# 在每個(gè)實(shí)例啟動(dòng)
redis-sentinel /data/sentinel26379/conf/sentinel.conf
# 查看是否啟動(dòng)
ps -ef|grep sentinel
# 哨兵啟動(dòng)后會(huì)在配置文件自動(dòng)新增一些參數(shù)

哨兵常用命令

  • 顯示其他哨兵的狀態(tài)
# 登錄哨兵
redis-cli -p 26379
# 顯示其他哨兵的狀態(tài)
sentinel sentinels mymaster
  • 顯示要監(jiān)控的集群狀態(tài)
sentinel masters
# 查看某一個(gè)master的狀態(tài)
sentinel master mymaster
# 查看某一個(gè)master的地址
sentinel get-master-addr-by-name mymaster
# 查看被監(jiān)控主的從庫狀態(tài)
sentinel replicas mymaster
  • 強(qiáng)制進(jìn)行故障轉(zhuǎn)移
sentinel failover mymaster
# 查看
sentinel get-master-addr-by-name mymaster
# 在去新的主查看
info replication

Go程序通過哨兵操作Redis

  1. 通過chatgpt編寫操作Redis的程序

編寫一個(gè)Go程序,能連接Redis的哨兵,有3個(gè)哨兵實(shí)例19216812161:26379,19216812162:26379,19216812163:26379,Redis密碼是xxx
幫忙每秒往Redis里面寫一個(gè)唯一的key
寫入成功,輸出success;
寫入失敗,輸出錯(cuò)誤,但是循環(huán)繼續(xù)

  1. 修改代碼(redis密碼)
  2. 測試代碼

故障切換測試

  1. 關(guān)閉住主實(shí)例并查看程序輸出
# 關(guān)閉主
info replication
shutdown
  1. 分析故障恢復(fù)過程的哨兵日志
# 查看日志文件
tail -n 30 /data/sentinel26379/log/26379.log
  1. 確定新的復(fù)制架構(gòu)
# 在新主查看信息
info replication
# 再啟動(dòng)關(guān)閉的實(shí)力
redis-sentinel /data/sentinel26379/conf/sentinel.conf
# 再查看信息
info replication

關(guān)于哨兵的建議

  1. 至少需要3個(gè)sentinel實(shí)例才能實(shí)現(xiàn)穩(wěn)健的部署
  2. sentinel放在不同的機(jī)柜上
  3. 需要保證客戶端支持sentinel

Redis Cluster架構(gòu)

Redis Cluster架構(gòu).jpg

Redis Cluster部署

需要部署六臺(tái)redis

  • 讓chatgpt編寫Redis部署腳本
    ??... ...
    在每臺(tái)實(shí)例運(yùn)行部署腳本(三臺(tái)服務(wù)器,每臺(tái)安裝2個(gè)redis)
# 與常規(guī)安裝redis相比新增集群參數(shù)
# 開啟集群
cluster-enabled yes
cluster-config0file /data/redis8001/data/nodes8001.conf
# 節(jié)點(diǎn)的超時(shí)事件,毫秒
cluster-node-timeout 5000

# 需要密碼的話
masterauth "IdfaUqTcdad82"
  • 創(chuàng)建集群
# 隨便一臺(tái)機(jī)器執(zhí)行; --cluster 表示加集群的參數(shù);create 創(chuàng)建集群;后面跟集群節(jié)點(diǎn);--cluster-replicas 表示每個(gè)節(jié)點(diǎn)分配幾個(gè)從節(jié)點(diǎn);-a 表示密碼(生產(chǎn)環(huán)境也是建議每個(gè)節(jié)點(diǎn)分配一個(gè)從節(jié)點(diǎn))
redis-cli --cluster create 192.168.12.161:8001 192.168.12.161:8002 192.168.12.162:8001 192.168.12.162:8002 192.168.12.163:8001 192.168.12.163:8002 --cluster-replicas 1 -a IdfaUqTcdad82

# 查看集群的狀態(tài)
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82

# 查看集群配置文件(啟動(dòng)集群后redis自動(dòng)創(chuàng)建)
cat /data/redis8001/data/node8001.conf

集群使用

  • 數(shù)據(jù)測試
# Redis Cluster 可以通過任意一個(gè)節(jié)點(diǎn)redis連接集群;-c 表示按集群的方式連接redis
redis-cli -p 8001 -a IdfaUqTcdad82 -c

# 查看集群信息,在redis內(nèi)執(zhí)行
cluster nodes
  • 集群相關(guān)命令
# 查看某個(gè)key在哪個(gè)槽上
cluster keyslot aaa
# 查看某個(gè)槽有多少個(gè)key,只能查詢本節(jié)點(diǎn)槽的數(shù)量
cluster countkeysinslot 10439
# 返回某個(gè)槽的某些key;10 查詢槽中10個(gè)key
cluster getkeysinslot 13785 10

通過Go程序連接Redis Cluster

查看某些開發(fā)語言怎么連接redis官方文檔

  • 通過chatgpt編寫Go連接Redis Cluster的代碼

編寫Go程序,需要連接帶密碼的Redis Cluster
每秒寫入一個(gè)唯一的key
寫入成功和失敗都輸出帶時(shí)間的日志

  • 修改代碼
  • 運(yùn)行代碼

故障恢復(fù)測試

  • 關(guān)閉一個(gè)主實(shí)例
# 登錄redis后執(zhí)行
shutdown
  • 查看集群狀態(tài)
cluster nodes
  • 啟動(dòng)關(guān)掉的實(shí)例
# 新啟動(dòng)的實(shí)例會(huì)變成從節(jié)點(diǎn)
/usr/local/redis6/bin/redise-serrver /data/redis8001/conf/redis.conf
# 極端場景,主和從都掛掉,是否繼續(xù)提供服務(wù)參數(shù);yes 表示主和從不可用的時(shí)候整個(gè)集群就不可用;no 這個(gè)主從節(jié)點(diǎn)不可用,其他節(jié)點(diǎn)可用,但是掛的節(jié)點(diǎn)的數(shù)據(jù)不可查詢
config get cluster-require-full-coverage

Redis Cluster擴(kuò)容

  • 部署要擴(kuò)容的Redis實(shí)例
# 在兩臺(tái)實(shí)例上各部署一個(gè)Redis
  • 添加新的主從實(shí)例到集群
# 192.168.12.161:8003 新增的節(jié)點(diǎn);192.168.12.161:8001 已經(jīng)存在的任一節(jié)點(diǎn)
redis-cli --cluster add-node 192.168.12.161:8003 192.168.12.161:8001 -a IdfaUqTcdad82
# 查看集群狀態(tài)
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82

# 為新增的主實(shí)例添加從實(shí)例;192.168.12.162:8003 新增的節(jié)點(diǎn);192.168.12.161:8001 已經(jīng)存在的任一節(jié)點(diǎn);--cluster-slave 以從節(jié)點(diǎn)加入;--cluster-master-id 主節(jié)點(diǎn)的id
redis-cli --cluster add-node 192.168.12.162:8003 192.168.12.161:8001 --cluster-slave --cluster-master-id 70502ee36d2476e6f39d335d56373d141daa4653  -a IdfaUqTcdad82

# 查看集群狀態(tài);此時(shí)新加的主從節(jié)點(diǎn)還沒有槽
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
  • 進(jìn)行槽遷移
# 192.168.12.161:8001 集群任一節(jié)點(diǎn);reshard 重新分配槽;槽總數(shù)/主從個(gè)數(shù)=新增節(jié)點(diǎn)的槽
redis-cli --cluster reshard 192.168.12.161:8001 -a IdfaUqTcdad82

Redis Cluster縮容

  • 轉(zhuǎn)移要縮容節(jié)點(diǎn)的槽
# --cluster-from 表示要遷移槽的源節(jié)點(diǎn);...a4777 要遷移到哪個(gè)節(jié)點(diǎn);--cluster-slots 要遷移槽的數(shù)量;192.168.12.161:8001 集群任意一節(jié)點(diǎn)的ip和端口
redis-cli --cluster reshard --cluster-from 70502ee36d2476e6f39d335d56373d141daa4653 --cluster-to 70502ee36d2476e6f39d335d56373d141daa4777 --cluster-slots 1365 192.168.12.161:8001 -a IdfaUqTcdad82
# 遷移時(shí)最好遷移到連續(xù)編號的槽節(jié)點(diǎn)
  • 刪除要縮容的節(jié)點(diǎn)
# 192.168.12.161:8001 集群任意一節(jié)點(diǎn)的ip和端口;...a4653 要?jiǎng)h除的節(jié)點(diǎn)
redis-cli --cluster del-node 192.168.12.161:8001 70502ee36d2476e6f39d335d56373d141daa4653 -a IdfaUqTcdad82
redis-cli --cluster del-node 192.168.12.161:8001 70502ee36d2476e6f39d335d56373d141daa4666 -a IdfaUqTcdad82
# 查看集群狀態(tài)
redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82

Redis Cluster原理解析

  • 虛擬槽和哈希標(biāo)簽

Redis Cluster采用虛擬槽分區(qū),一個(gè)集群有16384個(gè)虛擬槽,虛擬槽類似數(shù)據(jù)分區(qū),每個(gè)鍵值對都會(huì)根據(jù)它的key再按照CRC16算法計(jì)算一個(gè)16bit的值,然后這個(gè)16bit的值對16384進(jìn)行取模,通過模來映射到槽中。

# 有時(shí)候想要某些key在一個(gè)槽里面,可以用哈希標(biāo)簽
redis-cli -p 8001 -a IdfaUqTcdad82 -c
set {user001}.name aaa
set {user001}.email aaa@qq.com
# 查看在哪個(gè)槽
cluster keyslot {user001}.name
# 查看這個(gè)槽下所有key
cluster getkeysinslot 1390 10

# 不能過度使用,可能會(huì)導(dǎo)致數(shù)據(jù)分表不均勻
  • 客戶端怎樣定位數(shù)據(jù)的?

在客戶端和集群建立連接后,實(shí)例就會(huì)把hash槽的分片信息發(fā)送給客戶端,每個(gè)實(shí)例會(huì)把自己的hash槽信息發(fā)送給集群內(nèi)其它實(shí)例,這樣每個(gè)實(shí)例都會(huì)知道所有hash槽和實(shí)例的對應(yīng)關(guān)系。

  • 故障轉(zhuǎn)移

集群內(nèi)每個(gè)節(jié)點(diǎn)都會(huì)定期向集群中其它節(jié)點(diǎn)發(fā)送ping命令,互相探測,這樣可以交換節(jié)點(diǎn)狀態(tài)信息。

# 選取資格判斷參數(shù)
config get cluster-node-timeout

# 如果這個(gè)參數(shù)設(shè)置為0,那么不管斷開多久多會(huì)參與選舉
config get cluster-slave-validity-factor

Redis Cluster的優(yōu)勢

  1. 無中心架構(gòu)
  2. 動(dòng)態(tài)擴(kuò)縮容
  3. 高可用性

Redis Cluster的限制

  1. key批量操作支持有限
  2. 不能將一個(gè)大的鍵值對象映射到不同的節(jié)點(diǎn)
  3. 只支持單個(gè)庫
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容