Redis內(nèi)容整理
目錄
- 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)
- 持久化
- 主從架構(gòu)
- 哨兵模式
- 集群配置
1. 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)
string, value是一個(gè)字符串,在沒有確定數(shù)據(jù)結(jié)構(gòu)的復(fù)雜度時(shí),建議使用string
| 常用操作指令 | 說明 |
|---|---|
| set | 給key設(shè)置一個(gè)值 |
| get | 獲取一個(gè)key的值 |
| del | 刪除一個(gè)key |
| mset | 批量設(shè)置key的值 |
| mget | 批量獲取多個(gè)key的值 |
| setnx | 判斷key是否已經(jīng)存在,如果存在返回0不做操作,如果不存在插入并返回1 |
| exists | 判斷key是否存在 |
| incr | 給key設(shè)置自增+1 |
| incrby | 給key設(shè)置自增+n |
| decr | 給key設(shè)置自減-1 |
| decrby | 給key設(shè)置自減-n |
| expire | 給key設(shè)置過期時(shí)間 |
| ttl | 查看key的過期時(shí)間 |
hash,value是個(gè)<field, vlaue>的鍵值對(duì)集合,field沒有過期時(shí)間的屬性。可以存儲(chǔ)相對(duì)string比較復(fù)雜的數(shù)據(jù),單個(gè)key的field建議不超過5000
| 常用操作指令 | 說明 |
|---|---|
| hset | 給key設(shè)置一個(gè)field |
| hget | 獲取key的一個(gè)field |
| hdel | 刪除key的一個(gè)field |
| hmset | 給key設(shè)置多個(gè)field |
| hmget | 獲取key的多個(gè)field |
| hsetnx | 判斷key的field是否存在,如果存在返回0不做操作,如果不存在插入并返回1 |
| hlen | 獲取key的field個(gè)數(shù) |
| hgetall | 獲取key的所有field |
| hincr | key的field自增+1 |
list,value是個(gè)有序的鏈表,可以通過他實(shí)現(xiàn)棧(FILO),隊(duì)列(FIFO),阻塞隊(duì)列
| 常用操作指令 | 說明 |
|---|---|
| lpush | 在列表的最左端push一個(gè)值 |
| rpush | 在列表的最右端push一個(gè)值 |
| lpop | 在列表的最左端彈出一個(gè)值 |
| rpop | 在列表的最右端彈出一個(gè)值 |
| lbpop | 在列表的最左端彈出一個(gè)值,如果null就阻塞,直到有值可以被彈出 |
| rbpop | 在列表的最右端彈出一個(gè)值,如果null就阻塞,直到有值可以被彈出 |
| lrange | 在列表的最左端獲取對(duì)應(yīng)數(shù)量的值 |
| llen | 獲取列表的長度 |
| lindex | 獲取列表索引對(duì)應(yīng)的值 |
| lrem | 根據(jù)count移除等于value的值,count>0從頭,count<0從尾,count=0全部移除 |
| lset | 給索引位置設(shè)置一個(gè)值 |
| linsert | 給索引前或者后插入一個(gè)值 |
set,value是個(gè)集合,可以用該數(shù)據(jù)類型做一些交集,并集和隨機(jī)選舉的運(yùn)算
| 常用操作指令 | 說明 |
|---|---|
| sadd | 新增集合值 |
| smembers | 獲取集合所有值 |
| srem | 移除集合中對(duì)應(yīng)值 |
| scard | 獲取集合的長度 |
| sismember | 檢查集合中是否包含該值 |
| srandmember | 在集合中隨機(jī)選舉 |
| spop | 在集合中隨機(jī)選舉,并彈出 |
| sinter | 交集 |
| sinterstore | 將交集的結(jié)果存在一個(gè)新的集合中 |
| sunion | 并集 |
| sunionstore | 將并集的結(jié)果存在一個(gè)新的集合中 |
| sdiff | 差集 |
| sdiffstore | 將差集的結(jié)果存在一個(gè)新的集合中 |
zset,value是個(gè)集合,與set不同的是每個(gè)節(jié)點(diǎn)都有一個(gè)score,可以通過這個(gè)score值進(jìn)行排序
| 常用操作指令 | 說明 |
|---|---|
| zadd | 新增集合值 |
| zrem | 移除集合值 |
| zcard | 獲取集合長度 |
| zscore | 獲取集合成員的分值 |
| zrange | 獲取集合正序范圍區(qū)間值 |
| zrerange | 獲取集合倒序范圍區(qū)間值 |
| zinterstore | 將交集結(jié)果存到新集合 |
| zunionstore | 將并集結(jié)果存到新集合 |
2. 持久化
RDB持久化配置,使用二進(jìn)制rdb文件進(jìn)行存儲(chǔ)
save 和 bgsave命令可以手動(dòng)執(zhí)行,默認(rèn)配置文件的 save使用的是 bgsave,異步的進(jìn)行持久化
# 60秒內(nèi)1000個(gè)數(shù)據(jù)發(fā)生了變化,會(huì)將數(shù)據(jù)進(jìn)行一次持久化到rdb文件中
save 60 1000
| 命令 | IO類型 | 是否阻塞其他線程 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|---|
| save | 同步 | 是 | 不會(huì)消耗額外內(nèi)存 | 阻塞其他線程 |
| bgsave | 異步 | 否 | 不會(huì)阻塞其他線程 | 消耗額外的內(nèi)存 |
AOF持久化配置,根據(jù)配置規(guī)則將命令持久化到aop文件中
# 打開aop持久化開關(guān),默認(rèn)no
appendonly yes
# 每條操作數(shù)據(jù)的命令都進(jìn)行一次持久化,安全但效率不高
appendfsync always
# 每秒的操作數(shù)據(jù)命令,進(jìn)行一次持久化,建議使用此策略,兼顧安全與效率
appendfsync everysec
# no不是關(guān)閉,指的是交給系統(tǒng)去決定多久進(jìn)行一次持久化,有效率,但不安全
appendfsync no
AOF重寫,在aof文件中可能會(huì)有很多沒有用的指令,所以redis會(huì)對(duì)aof文件進(jìn)行重寫。重寫aof文件redis會(huì)fork一個(gè)子線程去執(zhí)行,所以不會(huì)對(duì)redis正常操作造成多大影響??梢允褂弥噶頱grewriteaof進(jìn)行重寫,也可以通過下面配置進(jìn)行重寫
# 配置重寫的最小文件限制,太小了沒有重寫的必要
auto-aof-rewrite-min-size 64mb
# 配置自上一次重寫,文件大小增長的百分比
auto-aof-rewrite-percentage 100
RDB體積小,恢復(fù)速度快,不過安全性差,易丟失數(shù)據(jù)
AOF體積大,恢復(fù)速度慢,安全性根據(jù)配置策略決定
在redis啟動(dòng)恢復(fù)數(shù)據(jù)時(shí),AOF相對(duì)RDB的優(yōu)先級(jí)要高,因?yàn)锳OF的數(shù)據(jù)要比RDB的更完整
Redis4.0 混合持久化
# 開啟混合持久化
aof-use-rdb-preamble yes
在開啟混合持久化后,當(dāng)aop文件發(fā)生重寫時(shí),會(huì)將重寫前的所有指令寫為rdb格式的內(nèi)容,在將后續(xù)的aof指令追加存放在一個(gè)新的aof文件中,重寫完成后替換appendonly.aof文件,redis重啟時(shí),先恢復(fù)rbd區(qū)域的數(shù)據(jù),然后再加載aof的數(shù)據(jù)指令 這樣就可以大大的加快了重啟速度

3. 主從架構(gòu)

主從節(jié)點(diǎn)配置
# 設(shè)置master節(jié)點(diǎn)ip地址和端口
replicaof ip port
# 設(shè)置master的密碼
masterauth <yourpassword>
# 設(shè)置slave節(jié)點(diǎn)只讀
replica-read-only yes
# 對(duì)外暴露的ip
replica-announce-ip
# 對(duì)外暴露的端口
replica-announce-port
為一個(gè)master節(jié)點(diǎn)配置一個(gè)slave節(jié)點(diǎn),不管這個(gè)slave節(jié)點(diǎn)是否第一次連接,都會(huì)向master發(fā)送一個(gè)SYNC請(qǐng)求。master接收到這個(gè)SYNC請(qǐng)求后,會(huì)在后臺(tái)通過 bgsave進(jìn)行持久化rdb,在持久化新的rdb文件之前,所有接收到的請(qǐng)求命令都會(huì)同時(shí)放入到一個(gè)緩沖區(qū),rdb文件完成持久化后同步給slave節(jié)點(diǎn),slave節(jié)點(diǎn)將rdb文件持久化并加載到內(nèi)存中,之后master會(huì)將緩沖區(qū)的命令同步給slave節(jié)點(diǎn)。
如果因?yàn)槟承┰驍嚅_連接,slave會(huì)自動(dòng)重連master
如果master有多個(gè)slave節(jié)點(diǎn)并發(fā)連接,master只會(huì)持久化一次
master與slave斷開重連后,一般是對(duì)數(shù)據(jù)完整的復(fù)制,在redis2.8以后可以部分復(fù)制,實(shí)際上就是緩沖區(qū)同步的每個(gè)指令都有個(gè)offset標(biāo)記,重連后在master的緩沖區(qū)如果找到對(duì)應(yīng)的offset就直接同步緩沖區(qū)后面的命令,如果沒有對(duì)應(yīng)的offset就進(jìn)行全量同步


4. 高可用哨兵架構(gòu)
sentinel哨兵
是redis的一種特殊服務(wù),他本身不提供讀寫服務(wù),用作監(jiān)聽redis實(shí)例節(jié)點(diǎn)。哨兵架構(gòu)下redis client通過sentinel獲取redis的master節(jié)點(diǎn),后續(xù)訪問master節(jié)點(diǎn),并不會(huì)一直連接sentinel節(jié)點(diǎn)。當(dāng)有master節(jié)點(diǎn)故障,sentinel會(huì)選舉新的節(jié)點(diǎn)通知給client(一般client都實(shí)現(xiàn)了訂閱功能,訂閱了sentinel發(fā)布節(jié)點(diǎn)變動(dòng)消息)
選主機(jī)制
主觀下線:每個(gè)sentinel節(jié)點(diǎn)會(huì)對(duì)redis集群節(jié)點(diǎn)發(fā)送心跳包,如果有節(jié)點(diǎn)在 down-after-milliseconds內(nèi)沒有回復(fù)心跳,則認(rèn)為該節(jié)點(diǎn)主觀下線
客觀下線:當(dāng)其中一個(gè)節(jié)點(diǎn)被sentinel節(jié)點(diǎn)認(rèn)為主觀下線時(shí),并不意味真的下線了,需要其他sentinel節(jié)點(diǎn)共同認(rèn)為主觀下線才可以。超過 quorum數(shù)量的sentinel節(jié)點(diǎn)認(rèn)同主觀下線,則是客觀下線。如果下線的是sentinel節(jié)點(diǎn) 或者slave節(jié)點(diǎn),那么就到此結(jié)束了,如果是master節(jié)點(diǎn),那么就開始從slave節(jié)點(diǎn)中選取一個(gè)master節(jié)點(diǎn)
選取主節(jié)點(diǎn)前,sentinel節(jié)點(diǎn)之間需要競(jìng)選一個(gè)leader,每個(gè)節(jié)點(diǎn)都可能成為leader,與確認(rèn)客觀下線一樣,在sentinel節(jié)點(diǎn)發(fā)現(xiàn)有master節(jié)點(diǎn)主管下線時(shí),就會(huì)給所有sentinel發(fā)起一個(gè)請(qǐng)求,如果同意的數(shù)量大于等于 quorum節(jié)點(diǎn),那么這個(gè)sentinel節(jié)點(diǎn)競(jìng)選成功
sentinel選舉規(guī)則
- 優(yōu)先排除故障節(jié)點(diǎn)
- 選擇優(yōu)先級(jí)slave-priority最大的
- offset偏移量最大的
- 選擇runid最小的
配置sentinel
復(fù)制一份sentinel.conf然后配置如下
# 配置監(jiān)聽redis集群的mater節(jié)點(diǎn),quorum是指多少個(gè)sentinel節(jié)點(diǎn)認(rèn)為一個(gè)master失效
sentinel monitor <master ip> <port> <quorum>
redis-sentinel sentinel.conf // 運(yùn)行sentinel節(jié)點(diǎn)
sentinel節(jié)點(diǎn)一般是建議配置三個(gè)或者基數(shù)節(jié)點(diǎn),因?yàn)橹挥谐^半數(shù)才能完成選主流程,例如(2/2+1 = 1)
5. 集群架構(gòu)
集群模式需要配置多個(gè)主從,因?yàn)樵诙鄠€(gè)主節(jié)點(diǎn)之間是分片進(jìn)行存儲(chǔ)的,如果沒有配置主從,當(dāng)其中一個(gè)master出現(xiàn)故障時(shí),會(huì)直接導(dǎo)致落在這個(gè)節(jié)點(diǎn)的請(qǐng)求失敗,無法立即做出響應(yīng)。配置了主從后,當(dāng)其中有mater節(jié)點(diǎn)發(fā)生故障時(shí),它下面的從節(jié)點(diǎn)會(huì)第一時(shí)間發(fā)現(xiàn),并發(fā)送fail的請(qǐng)求給其他集群節(jié)點(diǎn),這時(shí)其他正常的master節(jié)點(diǎn)會(huì)收到fail請(qǐng)求,并會(huì)對(duì)第一個(gè)接收到的fail請(qǐng)求做出ack響應(yīng),故障的master節(jié)點(diǎn)下面的從節(jié)點(diǎn)接收到ack數(shù)量超過master節(jié)點(diǎn)總數(shù)的一半,就會(huì)被選為新的master節(jié)點(diǎn)
集群模式建議配置奇數(shù)節(jié)點(diǎn),3,5,7 因?yàn)樵诋?dāng)有mater節(jié)點(diǎn)發(fā)生故障時(shí),偶數(shù)的節(jié)點(diǎn)無法做出選舉,選舉的條件是超過總master節(jié)點(diǎn)總數(shù)的一半
總線端口是留給gossip協(xié)議用作每個(gè)節(jié)點(diǎn)通信,在不同服務(wù)器上部署時(shí),注意開放端口訪問權(quán)限,默認(rèn)此端口是redis服務(wù)端口加10000
集群配置
# 暴露被訪問的地址,也就是所使用的網(wǎng)卡被分配的ip(或者全部注釋掉,默認(rèn)掃描全部可以被訪問的地址)
bind 0.0.0.0
# 關(guān)閉安全保護(hù)模式,如果打開的話,沒有設(shè)置bind參數(shù)并且沒有設(shè)置密碼,只有本地可以訪問
protected-mode no
# 因?yàn)榧鹤詣?dòng)分配主從,每個(gè)節(jié)點(diǎn)如果都設(shè)置了密碼。需要在這里配置好對(duì)應(yīng)密碼供節(jié)點(diǎn)之間能夠相互訪問
masterauth <yourpassword>
# 打開集群模式
cluster-enabled yes
# 配置當(dāng)前節(jié)點(diǎn)的集群配置文件名稱,文件名稱盡量對(duì)應(yīng)當(dāng)前節(jié)點(diǎn)的端口
cluster-config-file nodes-6379.conf
# 配置當(dāng)前節(jié)點(diǎn)故障,重連的超時(shí)時(shí)間,不要設(shè)置太短,網(wǎng)絡(luò)抖動(dòng)并非真的故障會(huì)導(dǎo)致服務(wù)頻繁主從切換
cluster-node-timeout 15000
# 當(dāng)前節(jié)點(diǎn)暴露的ip,如果沒有當(dāng)前節(jié)點(diǎn)沒有被發(fā)現(xiàn),可以配置暴露ip
cluster-announce-ip
# 當(dāng)前節(jié)點(diǎn)暴露的port
cluster-announce-port
# 當(dāng)前節(jié)點(diǎn)暴露的總線端口,gossip協(xié)議使用此端口用來節(jié)點(diǎn)之間通信,默認(rèn)是port加偏移量10000
cluster-announce-bus-port
啟動(dòng)cluster節(jié)點(diǎn)
redis-server redis.conf // 逐個(gè)節(jié)點(diǎn)啟動(dòng)
redis-cli -a <password> —cluster create [ host port ] —cluster-replicas <slave num> // 開啟集群 并配置集群信息。 服務(wù)自動(dòng)分配master和slave節(jié)點(diǎn),并為其分片