Redis基礎(chǔ)知識

1.Redis核心數(shù)據(jù)結(jié)構(gòu)

1.1 String

字符串常用操作
SET key value //存入字符串鍵值對
MSET key value [key value ...] //批量存儲字符串鍵值對
SETNX key value //存入一個不存在的字符串鍵值對
GET key //獲取一個字符串鍵值
MGET key [key ...] //批量獲取字符串鍵值
DEL key [key ...] //刪除一個鍵
EXPIRE key seconds //設(shè)置一個鍵的過期時間(秒)

原子加減
INCR key //將key中儲存的數(shù)字值加1
DECR key //將key中儲存的數(shù)字值減1
INCRBY key increment //將key所儲存的值加上increment
DECRBY key decrement //將key所儲存的值減去decrement

單值緩存
SET key value
GET key

對象緩存
1) SET user:1 value(json格式數(shù)據(jù))
2) MSET user:1:name zhuge user:1:balance 1888
MGET user:1:name user:1:balance

分布式鎖
SETNX product:10001 true //返回1代表獲取鎖成功
SETNX product:10001 true //返回0代表獲取鎖失敗
毅待。。。執(zhí)行業(yè)務(wù)操作
DEL product:10001 //執(zhí)行完業(yè)務(wù)釋放鎖

SET product:10001 true ex 10 nx //防止程序意外終止導(dǎo)致死鎖

計數(shù)器
INCR article:readcount:{文章id}
GET article:readcount:{文章id}

Web集群session共享
spring session + redis實現(xiàn)session共享

分布式系統(tǒng)全局序列號
INCRBY orderId 1000 //redis批量生成序列號提升性能

1.2 Hash

Hash常用操作
HSET key field value //存儲一個哈希表key的鍵值
HSETNX key field value //存儲一個不存在的哈希表key的鍵值
HMSET key field value [field value ...] //在一個哈希表key中存儲多個鍵值對
HGET key field //獲取哈希表key對應(yīng)的field鍵值
HMGET key field [field ...] //批量獲取哈希表key中多個field鍵值
HDEL key field [field ...] //刪除哈希表key中的field鍵值
HLEN key //返回哈希表key中field的數(shù)量
HGETALL key //返回哈希表key中所有的鍵值
HINCRBY key field increment //為哈希表key中field鍵的值加上增量increment

對象緩存
HMSET user {userId}:name zhuge {userId}:balance 1888
HMSET user 1:name zhuge 1:balance 1888
HMGET user 1:name 1:balance

電商購物車
1)以用戶id為key
2)商品id為field
3)商品數(shù)量為value

購物車操作
添加商品:hset cart:1001 10088 1
增加數(shù)量:hincrby cart:1001 10088 1
商品總數(shù):hlen cart:1001
刪除商品:hdel cart:1001 10088
獲取購物車所有商品:hgetall cart:1001

優(yōu)點(diǎn)
1)同類數(shù)據(jù)歸類整合儲存峡钓,方便數(shù)據(jù)管理
2)相比string操作消耗內(nèi)存與cpu更小
3)相比string儲存更節(jié)省空間

缺點(diǎn)
過期功能不能使用在field上习柠,只能用在key上
Redis集群架構(gòu)下不適合大規(guī)模使用

1.3 List

List常用操作
LPUSH key value [value ...] //將一個或多個值value插入到key列表的表頭(最左邊)
RPUSH key value [value ...] //將一個或多個值value插入到key列表的表尾(最右邊)
LPOP key //移除并返回key列表的頭元素
RPOP key //移除并返回key列表的尾元素
LRANGE key start stop //返回列表key中指定區(qū)間內(nèi)的元素喳坠,區(qū)間以偏移量start和stop指定

BLPOP key [key ...] timeout //從key列表表頭彈出一個元素构回,若列表中沒有元素谷炸,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待
BRPOP key [key ...] timeout //從key列表表尾彈出一個元素陈惰,若列表中沒有元素畦徘,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待

常用數(shù)據(jù)結(jié)構(gòu)
Stack(棧) = LPUSH + LPOP
Queue(隊列)= LPUSH + RPOP
Blocking MQ(阻塞隊列)= LPUSH + BRPOP

微博消息和微信公號消息
諸葛老師關(guān)注了MacTalk,備胎說車等大V
1)MacTalk發(fā)微博抬闯,消息ID為10018
LPUSH msg:{諸葛老師-ID} 10018
2)備胎說車發(fā)微博井辆,消息ID為10086
LPUSH msg:{諸葛老師-ID} 10086
3)查看最新微博消息
LRANGE msg:{諸葛老師-ID} 0 4

1.4 Set

Set常用操作
SADD key member [member ...] //往集合key中存入元素,元素存在則忽略溶握,
若key不存在則新建
SREM key member [member ...] //從集合key中刪除元素
SMEMBERS key //獲取集合key中所有元素
SCARD key //獲取集合key的元素個數(shù)
SISMEMBER key member //判斷member元素是否存在于集合key中
SRANDMEMBER key [count] //從集合key中選出count個元素杯缺,元素不從key中刪除
SPOP key [count] //從集合key中選出count個元素,元素從key中刪除

Set運(yùn)算操作
SINTER key [key ...] //交集運(yùn)算
SINTERSTORE destination key [key ..] //將交集結(jié)果存入新集合destination中
SUNION key [key ..] //并集運(yùn)算
SUNIONSTORE destination key [key ...] //將并集結(jié)果存入新集合destination中
SDIFF key [key ...] //差集運(yùn)算
SDIFFSTORE destination key [key ...] //將差集結(jié)果存入新集合destination中

微信抽獎小程序
1)點(diǎn)擊參與抽獎加入集合
SADD key {userlD}
2)查看參與抽獎所有用戶
SMEMBERS key
3)抽取count名中獎?wù)?br> SRANDMEMBER key [count] / SPOP key [count]

微信微博點(diǎn)贊睡榆,收藏萍肆,標(biāo)簽
1)點(diǎn)贊
SADD like:{消息ID} {用戶ID}
2) 取消點(diǎn)贊
SREM like:{消息ID} {用戶ID}
3)檢查用戶是否點(diǎn)過贊
SISMEMBER like:{消息ID} {用戶ID}
4)獲取點(diǎn)贊的用戶列表
SMEMBERS like:{消息ID}
5)獲取點(diǎn)贊用戶數(shù)
SCARD like:{消息ID}

集合操作實現(xiàn)微博微信關(guān)注模型

  1. 諸葛老師關(guān)注的人:
    zhugeSet-> {guojia, xushu}
  2. 楊過老師關(guān)注的人:
    yangguoSet--> {zhuge, baiqi, guojia, xushu}
  3. 郭嘉老師關(guān)注的人:
    guojiaSet-> {zhuge, yangguo, baiqi, xushu, xunyu)
  4. 我和楊過老師共同關(guān)注:
    SINTER zhugeSet yangguoSet--> {guojia, xushu}
  5. 我關(guān)注的人也關(guān)注他(楊過老師):
    SISMEMBER guojiaSet yangguo
    SISMEMBER xushuSet yangguo
  6. 我可能認(rèn)識的人:
    SDIFF yangguoSet zhugeSet->(zhuge, baiqi}

1.5 ZSet

ZSet常用操作
ZADD key score member [[score member]…] //往有序集合key中加入帶分值元素
ZREM key member [member …] //從有序集合key中刪除元素
ZSCORE key member //返回有序集合key中元素member的分值
ZINCRBY key increment member //為有序集合key中元素member的分值加上increment
ZCARD key //返回有序集合key中元素個數(shù)
ZRANGE key start stop [WITHSCORES] //正序獲取有序集合key從start下標(biāo)到stop下標(biāo)的元素
ZREVRANGE key start stop [WITHSCORES] //倒序獲取有序集合key從start下標(biāo)到stop下標(biāo)的元素

Zset集合操作
ZUNIONSTORE destkey numkeys key [key ...] //并集計算
ZINTERSTORE destkey numkeys key [key …] //交集計算

Zset集合操作實現(xiàn)排行榜
1)點(diǎn)擊新聞
ZINCRBY hotNews:20190819 1 守護(hù)香港
2)展示當(dāng)日排行前十
ZREVRANGE hotNews:20190819 0 9 WITHSCORES
3)七日搜索榜單計算
ZUNIONSTORE hotNews:20190813-20190819 7
hotNews:20190813 hotNews:20190814... hotNews:20190819
4)展示七日排行前十
ZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORES

2.Redis的單線程和高性能

Redis是單線程嗎?
Redis 的單線程主要是指 Redis 的網(wǎng)絡(luò) IO 和鍵值對讀寫是由一個線程來完成的胀屿,這也是 Redis 對外提供鍵值存儲服務(wù)的主要流程塘揣。但 Redis 的其他功能,比如持久化碉纳、異步刪除勿负、集群數(shù)據(jù)同步等,其實是由額外的線程執(zhí)行的。

Redis 單線程為什么還能這么快奴愉?
因為它所有的數(shù)據(jù)都在內(nèi)存中琅摩,所有的運(yùn)算都是內(nèi)存級別的運(yùn)算,而且單線程避免了多線程的切換性能損耗問題锭硼。正因為 Redis 是單線程房资,所以要小心使用 Redis 指令,對于那些耗時的指令(比如keys)檀头,一定要謹(jǐn)慎使用轰异,一不小心就可能會導(dǎo)致 Redis 卡頓。

Redis 單線程如何處理那么多的并發(fā)客戶端連接暑始?
Redis的IO多路復(fù)用:redis利用epoll來實現(xiàn)IO多路復(fù)用搭独,將連接信息和事件放到隊列中,依次放到文件事件分派器廊镜,事件分派器將事件分發(fā)給事件處理器牙肝。

3.持久化

3.1 RDB快照(snapshot)

在默認(rèn)情況下, Redis 將內(nèi)存數(shù)據(jù)庫快照保存在名字為 dump.rdb 的二進(jìn)制文件中嗤朴。
你可以對 Redis 進(jìn)行設(shè)置配椭, 讓它在“ N 秒內(nèi)數(shù)據(jù)集至少有 M 個改動”這一條件被滿足時, 自動保存一次數(shù)據(jù)集雹姊。
比如說股缸, 以下設(shè)置會讓 Redis 在滿足“ 60 秒內(nèi)有至少有 1000 個鍵被改動”這一條件時, 自動保存一次數(shù)據(jù)集:
save 60 1000 //關(guān)閉RDB只需要將所有的save保存策略注釋掉即可

還可以手動執(zhí)行命令生成RDB快照吱雏,進(jìn)入redis客戶端執(zhí)行命令save或bgsave可以生成dump.rdb文件敦姻,每次命令執(zhí)行都會將所有redis內(nèi)存快照到一個新的rdb文件里,并覆蓋原有rdb快照文件歧杏。


3.2 AOF(append-only file)

快照功能并不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機(jī)替劈, 那么服務(wù)器將丟失最近寫入、且仍未保存到快照中的那些數(shù)據(jù)得滤。從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化盒犹,將修改的每一條指令記錄進(jìn)文件appendonly.aof中(先寫入os cache懂更,每隔一段時間fsync到磁盤)

appendfsync always:每次有新命令追加到 AOF 文件時就執(zhí)行一次 fsync ,非常慢急膀,也非常安全沮协。
appendfsync everysec:每秒 fsync 一次,足夠快卓嫂,并且在故障時只會丟失 1 秒鐘的數(shù)據(jù)慷暂。
appendfsync no:從不 fsync ,將數(shù)據(jù)交給操作系統(tǒng)來處理。更快行瑞,也更不安全的選擇奸腺。

推薦(并且也是默認(rèn))的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性血久。

AOF重寫:
AOF文件里可能有太多沒用指令突照,所以AOF會定期根據(jù)內(nèi)存的最新數(shù)據(jù)生成aof文件。

3.3 Redis 4.0 混合持久化

重啟 Redis 時氧吐,我們很少使用 RDB來恢復(fù)內(nèi)存狀態(tài)讹蘑,因為會丟失大量數(shù)據(jù)。我們通常使用 AOF 日志重放筑舅,但是重放 AOF 日志性能相對 RDB來說要慢很多座慰,這樣在 Redis 實例很大的情況下,啟動需要花費(fèi)很長的時間翠拣。 Redis 4.0 為了解決這個問題版仔,帶來了一個新的持久化選項——混合持久化。
通過如下配置可以開啟混合持久化(必須先開啟aof):
aof-use-rdb-preamble yes

如果開啟了混合持久化心剥,AOF在重寫時邦尊,不再是單純將內(nèi)存數(shù)據(jù)轉(zhuǎn)換為RESP命令寫入AOF文件,而是將重寫這一刻之前的內(nèi)存做RDB快照處理优烧,并且將RDB快照內(nèi)容和增量的AOF修改內(nèi)存數(shù)據(jù)的命令存在一起蝉揍,都寫入新的AOF文件,新的文件一開始不叫appendonly.aof畦娄,等到重寫完新的AOF文件才會進(jìn)行改名又沾,覆蓋原有的AOF文件,完成新舊兩個AOF文件的替換熙卡。
于是在 Redis 重啟的時候杖刷,可以先加載 RDB 的內(nèi)容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放驳癌,因此重啟效率大幅得到提升滑燃。

4.Redis架構(gòu)

4.1 主從架構(gòu)

如果你為master配置了一個slave,不管這個slave是否是第一次連接上Master颓鲜,它都會發(fā)送一個PSYNC命令給master請求復(fù)制數(shù)據(jù)表窘。

master收到PSYNC命令后,會在后臺進(jìn)行數(shù)據(jù)持久化通過bgsave生成最新的rdb快照文件甜滨,持久化期間乐严,master會繼續(xù)接收客戶端的請求,它會把這些可能修改數(shù)據(jù)集的請求緩存在內(nèi)存中衣摩。當(dāng)持久化進(jìn)行完畢以后昂验,master會把這份rdb文件數(shù)據(jù)集發(fā)送給slave,slave會把接收到的數(shù)據(jù)進(jìn)行持久化生成rdb,然后再加載到內(nèi)存中既琴。然后占婉,master再將之前緩存在內(nèi)存中的命令發(fā)送給slave。

當(dāng)master與slave之間的連接由于某些原因而斷開時呛梆,slave能夠自動重連Master锐涯,如果master收到了多個slave并發(fā)連接請求,它只會進(jìn)行一次持久化填物,而不是一個連接一次纹腌,然后再把這一份持久化的數(shù)據(jù)發(fā)送給多個并發(fā)連接的slave。

主從復(fù)制(全量復(fù)制)流程圖:

數(shù)據(jù)部分復(fù)制

當(dāng)master和slave斷開重連后滞磺,一般都會對整份數(shù)據(jù)進(jìn)行復(fù)制升薯。但從redis2.8版本開始,redis改用可以支持部分?jǐn)?shù)據(jù)復(fù)制的命令PSYNC去master同步數(shù)據(jù)击困,slave與master能夠在網(wǎng)絡(luò)連接斷開重連后只進(jìn)行部分?jǐn)?shù)據(jù)復(fù)制(斷點(diǎn)續(xù)傳)涎劈。

master會在其內(nèi)存中創(chuàng)建一個復(fù)制數(shù)據(jù)用的緩存隊列,緩存最近一段時間的數(shù)據(jù)阅茶,master和它所有的slave都維護(hù)了復(fù)制的數(shù)據(jù)下標(biāo)offset和master的進(jìn)程id蛛枚,因此,當(dāng)網(wǎng)絡(luò)連接斷開后脸哀,slave會請求master繼續(xù)進(jìn)行未完成的復(fù)制蹦浦,從所記錄的數(shù)據(jù)下標(biāo)開始。如果master進(jìn)程id變化了撞蜂,或者從節(jié)點(diǎn)數(shù)據(jù)下標(biāo)offset太舊盲镶,已經(jīng)不在master的緩存隊列里了,那么將會進(jìn)行一次全量數(shù)據(jù)的復(fù)制蝌诡。

主從復(fù)制(部分復(fù)制溉贿,斷點(diǎn)續(xù)傳)流程圖:

如果有很多從節(jié)點(diǎn),為了緩解主從復(fù)制風(fēng)暴(多個從節(jié)點(diǎn)同時復(fù)制主節(jié)點(diǎn)導(dǎo)致主節(jié)點(diǎn)壓力過大)浦旱,可以做如下架構(gòu)宇色,讓部分從節(jié)點(diǎn)與從節(jié)點(diǎn)(與主節(jié)點(diǎn)同步)同步數(shù)據(jù)

4.2 哨兵架構(gòu)


sentinel哨兵是特殊的redis服務(wù),不提供讀寫服務(wù)颁湖,主要用來監(jiān)控redis實例節(jié)點(diǎn)代兵。
哨兵架構(gòu)下client端第一次從哨兵找出redis的主節(jié)點(diǎn),后續(xù)就直接訪問redis的主節(jié)點(diǎn)爷狈,不會每次都通過sentinel代理訪問redis的主節(jié)點(diǎn),當(dāng)redis的主節(jié)點(diǎn)發(fā)生變化裳擎,哨兵會第一時間感知到涎永,并且將新的redis主節(jié)點(diǎn)通知給client端(這里面redis的client端一般都實現(xiàn)了訂閱功能,訂閱sentinel發(fā)布的節(jié)點(diǎn)變動消息)。

在redis3.0以前的版本要實現(xiàn)集群一般是借助哨兵sentinel工具來監(jiān)控master節(jié)點(diǎn)的狀態(tài)羡微,如果master節(jié)點(diǎn)異常谷饿,則會做主從切換,將某一臺slave作為master妈倔,哨兵的配置略微復(fù)雜博投,并且性能和高可用性等各方面表現(xiàn)一般,特別是在主從切換的瞬間存在訪問瞬斷的情況盯蝴,而且哨兵模式只有一個主節(jié)點(diǎn)對外提供服務(wù)毅哗,沒法支持很高的并發(fā),且單個主節(jié)點(diǎn)內(nèi)存也不宜設(shè)置得過大捧挺,否則會導(dǎo)致持久化文件過大虑绵,影響數(shù)據(jù)恢復(fù)或主從同步的效率。

單節(jié)點(diǎn)內(nèi)存不超過10G闽烙,過大會導(dǎo)致主從復(fù)制翅睛、aof重寫變得很慢。

4.3 集群架構(gòu)

redis集群是一個由多個主從節(jié)點(diǎn)群組成的分布式服務(wù)器群黑竞,它具有復(fù)制捕发、高可用和分片特性。Redis集群不需要sentinel哨兵·也能完成節(jié)點(diǎn)移除和故障轉(zhuǎn)移的功能很魂。需要將每個節(jié)點(diǎn)設(shè)置成集群模式扎酷,這種集群模式?jīng)]有中心節(jié)點(diǎn),可水平擴(kuò)展莫换,據(jù)官方文檔稱可以線性擴(kuò)展到上萬個節(jié)點(diǎn)(官方推薦不超過1000個節(jié)點(diǎn))霞玄。redis集群的性能和高可用性均優(yōu)于之前版本的哨兵模式,且集群配置非常簡單拉岁。

只有主節(jié)點(diǎn)可以讀寫坷剧,從節(jié)點(diǎn)只是備份。

Redis Cluster 將所有數(shù)據(jù)劃分為 16384 個 slots(槽位)喊暖,每個節(jié)點(diǎn)負(fù)責(zé)其中一部分槽位惫企。槽位的信息存儲于每個節(jié)點(diǎn)中。

當(dāng) Redis Cluster 的客戶端來連接集群時陵叽,它也會得到一份集群的槽位配置信息并將其緩存在客戶端本地狞尔。這樣當(dāng)客戶端要查找某個 key 時,可以直接定位到目標(biāo)節(jié)點(diǎn)巩掺。同時因為槽位的信息可能會存在客戶端與服務(wù)器不一致的情況偏序,還需要糾正機(jī)制來實現(xiàn)槽位信息的校驗調(diào)整。

4.3.1 槽位定位算法

Cluster 默認(rèn)會對 key 值使用 crc16 算法進(jìn)行 hash 得到一個整數(shù)值胖替,然后用這個整數(shù)值對 16384 進(jìn)行取模來得到具體槽位研儒。

HASH_SLOT = CRC16(key) mod 16384

4.3.2 跳轉(zhuǎn)重定位

當(dāng)客戶端向一個錯誤的節(jié)點(diǎn)發(fā)出了指令豫缨,該節(jié)點(diǎn)會發(fā)現(xiàn)指令的 key 所在的槽位并不歸自己管理,這時它會向客戶端發(fā)送一個特殊的跳轉(zhuǎn)指令攜帶目標(biāo)操作的節(jié)點(diǎn)地址端朵,告訴客戶端去連這個節(jié)點(diǎn)去獲取數(shù)據(jù)好芭。客戶端收到指令后除了跳轉(zhuǎn)到正確的節(jié)點(diǎn)上去操作冲呢,還會同步更新糾正本地的槽位映射表緩存舍败,后續(xù)所有 key 將使用新的槽位映射表。

4.3.3 Redis集群節(jié)點(diǎn)間的通信機(jī)制

redis cluster節(jié)點(diǎn)間采取gossip協(xié)議進(jìn)行通信
維護(hù)集群的元數(shù)據(jù)(集群節(jié)點(diǎn)信息敬拓,主從角色邻薯,節(jié)點(diǎn)數(shù)量,各節(jié)點(diǎn)共享的數(shù)據(jù)等)有兩種方式:集中式和gossip

集中式:
優(yōu)點(diǎn)在于元數(shù)據(jù)的更新和讀取恩尾,時效性非常好弛说,一旦元數(shù)據(jù)出現(xiàn)變更立即就會更新到集中式的存儲中,其他節(jié)點(diǎn)讀取的時候立即就可以立即感知到翰意;不足在于所有的元數(shù)據(jù)的更新壓力全部集中在一個地方木人,可能導(dǎo)致元數(shù)據(jù)的存儲壓力。 很多中間件都會借助zookeeper集中式存儲元數(shù)據(jù)冀偶。

gossip:
gossip協(xié)議包含多種消息醒第,包括ping,pong进鸠,meet稠曼,fail等等。
meet:某個節(jié)點(diǎn)發(fā)送meet給新加入的節(jié)點(diǎn)客年,讓新節(jié)點(diǎn)加入集群中霞幅,然后新節(jié)點(diǎn)就會開始與其他節(jié)點(diǎn)進(jìn)行通信;
ping:每個節(jié)點(diǎn)都會頻繁給其他節(jié)點(diǎn)發(fā)送ping量瓜,其中包含自己的狀態(tài)還有自己維護(hù)的集群元數(shù)據(jù)司恳,互相通過ping交換元數(shù)據(jù)(類似自己感知到的集群節(jié)點(diǎn)增加和移除,hash slot信息等)绍傲;
pong: 對ping和meet消息的返回扔傅,包含自己的狀態(tài)和其他信息,也可以用于信息廣播和更新烫饼;
fail: 某個節(jié)點(diǎn)判斷另一個節(jié)點(diǎn)fail之后猎塞,就發(fā)送fail給其他節(jié)點(diǎn),通知其他節(jié)點(diǎn)杠纵,指定的節(jié)點(diǎn)宕機(jī)了荠耽。

gossip協(xié)議的優(yōu)點(diǎn)在于元數(shù)據(jù)的更新比較分散,不是集中在一個地方比藻,更新請求會陸陸續(xù)續(xù)铝量,打到所有節(jié)點(diǎn)上去更新伊履,有一定的延時,降低了壓力款违;缺點(diǎn)在于元數(shù)據(jù)更新有延時可能導(dǎo)致集群的一些操作會有一些滯后。

gossip通信的10000端口
每個節(jié)點(diǎn)都有一個專門用于節(jié)點(diǎn)間gossip通信的端口群凶,就是自己提供服務(wù)的端口號+10000插爹,比如7001,那么用于節(jié)點(diǎn)間通信的就是17001端口请梢。 每個節(jié)點(diǎn)每隔一段時間都會往另外幾個節(jié)點(diǎn)發(fā)送ping消息赠尾,同時其他幾點(diǎn)接收到ping消息之后返回pong消息。

4.3.4 網(wǎng)絡(luò)抖動

真實世界的機(jī)房網(wǎng)絡(luò)往往并不是風(fēng)平浪靜的毅弧,它們經(jīng)常會發(fā)生各種各樣的小問題气嫁。比如網(wǎng)絡(luò)抖動就是非常常見的一種現(xiàn)象,突然之間部分連接變得不可訪問够坐,然后很快又恢復(fù)正常寸宵。
為解決這種問題,Redis Cluster 提供了一種選項cluster-node-timeout元咙,表示當(dāng)某個節(jié)點(diǎn)持續(xù) timeout 的時間失聯(lián)時本股,才可以認(rèn)定該節(jié)點(diǎn)出現(xiàn)故障眨攘,需要進(jìn)行主從切換。如果沒有這個選項,網(wǎng)絡(luò)抖動會導(dǎo)致主從頻繁切換 (數(shù)據(jù)的重新復(fù)制)遭殉。

4.3.5 Redis集群選舉原理分析

當(dāng)slave發(fā)現(xiàn)自己的master變?yōu)镕AIL狀態(tài)時,便嘗試進(jìn)行Failover舍咖,以期成為新的master达箍。由于掛掉的master可能會有多個slave,從而存在多個slave競爭成為master節(jié)點(diǎn)的過程奢赂, 其過程如下:
1.slave發(fā)現(xiàn)自己的master變?yōu)镕AIL
2.將自己記錄的集群currentEpoch加1陪白,并廣播FAILOVER_AUTH_REQUEST 信息
3.其他節(jié)點(diǎn)收到該信息,只有master響應(yīng)呈驶,判斷請求者的合法性拷泽,并發(fā)送FAILOVER_AUTH_ACK,對每一個epoch只發(fā)送一次ack
4.嘗試failover的slave收集master返回的FAILOVER_AUTH_ACK
5.slave收到超過半數(shù)master的ack后變成新Master(這里解釋了集群為什么至少需要三個主節(jié)點(diǎn)袖瞻,如果只有兩個司致,當(dāng)其中一個掛了,只剩一個主節(jié)點(diǎn)是不能選舉成功的)
6.slave廣播Pong消息通知其他集群節(jié)點(diǎn)聋迎。

從節(jié)點(diǎn)并不是在主節(jié)點(diǎn)一進(jìn)入 FAIL 狀態(tài)就馬上嘗試發(fā)起選舉脂矫,而是有一定延遲,一定的延遲確保我們等待FAIL狀態(tài)在集群中傳播霉晕,slave如果立即嘗試選舉庭再,其它masters或許尚未意識到FAIL狀態(tài)捞奕,可能會拒絕投票
?延遲計算公式:
DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms
?SLAVE_RANK表示此slave已經(jīng)從master復(fù)制數(shù)據(jù)的總量的rank。Rank越小代表已復(fù)制的數(shù)據(jù)越新拄轻。這種方式下颅围,持有最新數(shù)據(jù)的slave將會首先發(fā)起選舉(理論上)。

4.3.6 集群腦裂數(shù)據(jù)丟失問題

redis集群沒有過半機(jī)制會有腦裂問題恨搓,網(wǎng)絡(luò)分區(qū)導(dǎo)致腦裂后多個主節(jié)點(diǎn)對外提供寫服務(wù)院促,一旦網(wǎng)絡(luò)分區(qū)恢復(fù),會將其中一個主節(jié)點(diǎn)變?yōu)閺墓?jié)點(diǎn)斧抱,這時會有大量數(shù)據(jù)丟失常拓。
規(guī)避方法可以在redis配置里加上參數(shù)(這種方法不可能百分百避免數(shù)據(jù)丟失,參考集群leader選舉機(jī)制):
min-replicas-to-write 1 //寫數(shù)據(jù)成功最少同步的slave數(shù)量辉浦,這個數(shù)量可以模仿大于半數(shù)機(jī)制配置弄抬,比如集群總共三個節(jié)點(diǎn)可以配置1,加上leader就是2宪郊,超過了半數(shù)
注意:這個配置在一定程度上會影響集群的可用性掂恕,比如slave要是少于1個,這個集群就算leader正常也不能提供服務(wù)了废膘,需要具體場景權(quán)衡選擇竹海。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市丐黄,隨后出現(xiàn)的幾起案子斋配,更是在濱河造成了極大的恐慌,老刑警劉巖灌闺,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艰争,死亡現(xiàn)場離奇詭異,居然都是意外死亡桂对,警方通過查閱死者的電腦和手機(jī)甩卓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蕉斜,“玉大人逾柿,你說我怎么就攤上這事≌耍” “怎么了机错?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長父腕。 經(jīng)常有香客問我弱匪,道長,這世上最難降的妖魔是什么璧亮? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任萧诫,我火速辦了婚禮斥难,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帘饶。我一直安慰自己哑诊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布及刻。 她就那樣靜靜地躺著搭儒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪提茁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天馁菜,我揣著相機(jī)與錄音茴扁,去河邊找鬼。 笑死汪疮,一個胖子當(dāng)著我的面吹牛峭火,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播智嚷,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼卖丸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盏道?” 一聲冷哼從身側(cè)響起稍浆,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猜嘱,沒想到半個月后衅枫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朗伶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年弦撩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片论皆。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡益楼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出点晴,到底是詐尸還是另有隱情感凤,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布觉鼻,位于F島的核電站俊扭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坠陈。R本人自食惡果不足惜萨惑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一捐康、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧庸蔼,春花似錦解总、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至掏膏,卻和暖如春劳翰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背馒疹。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工佳簸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人颖变。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓生均,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腥刹。 傳聞我的和親對象是個殘疾皇子马胧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容