Redis基礎(chǔ)知識(shí)(二)

微信公眾號(hào):運(yùn)維開(kāi)發(fā)故事,作者:wanger

Redis事務(wù)

redis中的事務(wù)是一組命令的集合,事務(wù)中的命令要么全部執(zhí)行,要么都不執(zhí)行,Redis 通過(guò) MULTI 、DISCARD 、EXEC 和 WATCH
四個(gè)命令來(lái)實(shí)現(xiàn)事務(wù)功能,multi表示事物的開(kāi)啟,exec表示事物的執(zhí)行,exec執(zhí)行后返回事務(wù)執(zhí)行的結(jié)果,discard表示放棄事務(wù)執(zhí)行,清空事務(wù)隊(duì)列中已有的所有命令并退出隊(duì)列,watch用于監(jiān)視給定的鍵,如果鍵被其他客戶端修改,將不會(huì)執(zhí)行事務(wù)。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 1
QUEUED
127.0.0.1:6379> get key
QUEUED
127.0.0.1:6379> exec
1) OK
2) "1"

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key1 1
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get key1
(nil)

這里我在另一個(gè)客戶端修改了被監(jiān)視的key,導(dǎo)致在這個(gè)客戶端事務(wù)沒(méi)有執(zhí)行

127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr key
QUEUED
127.0.0.1:6379> incr key  #客戶端2
(integer) 2
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get key
"2"

由于事務(wù)在執(zhí)行時(shí)會(huì)獨(dú)占服務(wù)器,所以盡量避免在事務(wù)中執(zhí)行過(guò)多命令,以免服務(wù)器阻塞

Redis Pipline

redis是一個(gè)cs模式的tcp server,使用和http類似的請(qǐng)求響應(yīng)協(xié)議。一個(gè)client可以通過(guò)一個(gè)socket連接發(fā)起多個(gè)請(qǐng)求命令。每個(gè)請(qǐng)求命令發(fā)出后client通常會(huì)阻塞并等待redis服務(wù)處理,redis處理完后請(qǐng)求命令后會(huì)將結(jié)果通過(guò)響應(yīng)報(bào)文返回給client。如果網(wǎng)絡(luò)延遲較大,那將會(huì)花費(fèi)太多的時(shí)間,redis提供了pipline可以解決這個(gè)問(wèn)題,redis可以在pipline中發(fā)送多個(gè)消息而無(wú)需等待每個(gè)消息的答復(fù)的過(guò)程。
這里我使用python的redis庫(kù)寫了個(gè)demo來(lái)演示使用pipline的效果

from redis import Redis
import time
conn=Redis(host="60.205.177.100",port="6379")

def usepipline():
    start_time=time.time()
    pipline=conn.pipeline()
    for i in range(300):
        pipline.incr("key")
    pipline.execute()
    print("usepipline:",time.time()-start_time)
def withoutpipline():
    start_time=time.time()
    for i in range(300):
        conn.incr("key1")
    print("withoutpipline:",time.time()-start_time)
usepipline()
withoutpipline()

響應(yīng)結(jié)果

usepipline: 1.2412519454956055
withoutpipline: 7.2261717319488525

可以看到使用pipline效果是很明顯的

Redis發(fā)布訂閱模式

Redis通過(guò)PUBLISH 、SUBSCRIBE 等命令實(shí)現(xiàn)了訂閱與發(fā)布模式,發(fā)布者可以向多個(gè)頻道發(fā)布消息,訂閱者可以訂閱多個(gè)頻道,當(dāng)然一個(gè)頻道也可以有多個(gè)訂閱者,發(fā)布者和訂閱者的這種分離可以允許更大的可伸縮性和更動(dòng)態(tài)的網(wǎng)絡(luò)拓?fù)洹?/p>

圖片

命令

向頻道發(fā)送消息

publish channel message

例如

返回的是接收到消息的訂閱者數(shù)量

127.0.0.1:6379> publish CCTV1 worldnews
(integer) 0
127.0.0.1:6379> publish CCTV1 chinanews
(integer) 0

訂閱頻道

subscribe channel [channel ...]

例如

127.0.0.1:6379> subscribe CCTV1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "CCTV1"
3) (integer) 1
1) "message"
2) "CCTV1"
3) "chinanews"

退訂頻道

UNSUBSCRIBE [channel [channel ...]]

例如

127.0.0.1:6379> UNSUBSCRIBE CCTV1 CCTV2
1) "unsubscribe"
2) "CCTV1"
3) (integer) 0
4) "unsubscribe"
5) "CCTV2"
6) (integer) 0

訂閱模式

redis支持使用glob的方式來(lái)一次訂閱多個(gè)頻道

PSUBSCRIBE pattern [pattern ...]

例如

127.0.0.1:6379> publish CCTV2 chinanew
(integer) 1
127.0.0.1:6379> publish CCTV1 worldnews
(integer) 1
127.0.0.1:6379> PSUBSCRIBE CCTV*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "CCTV*"
3) (integer) 1
1) "pmessage"
2) "CCTV*"
3) "CCTV2"
4) "chinanews"
1) "pmessage"
2) "CCTV*"
3) "CCTV2"
4) "chinanew"

退訂模式

PUNSUBSCRIBE [pattern [pattern ...]]

例如

127.0.0.1:6379> PUNSUBSCRIBE CCTV*
1) "punsubscribe"
2) "CCTV*"
3) (integer) 0

python demo

redis_pub.py

from redis import Redis
import time
conn=Redis(host="60.205.177.100",port="6379")
def publish():
    while True:
        conn.publish("CCTV3","test")

redis_sub.py

from redis import Redis
import time
conn=Redis(host="60.205.177.100",port="6379")
def subscribe():
    subscribe=conn.pubsub()
    subscribe.subscribe('CCTV3')
    message=subscribe.parse_response()
    print(message)

Redis復(fù)制

雖然已經(jīng)有了aof和rdb做持久化了,但是為了防止單點(diǎn)故障,這就需要復(fù)制多個(gè)數(shù)據(jù)副本來(lái)保證數(shù)據(jù)安全

redis復(fù)制的基本特征

  • Redis使用異步復(fù)制,并以每秒一次的頻率向主服務(wù)器確認(rèn)復(fù)制進(jìn)度。

  • 一個(gè)主服務(wù)器可以有多個(gè)從服務(wù)器。

    從服務(wù)器也可以有多個(gè)從服務(wù)器,從服務(wù)器還可以以類似級(jí)聯(lián)的結(jié)構(gòu)連接到其他從服務(wù)器。

  • Redis復(fù)制在主服務(wù)器端無(wú)阻塞。

    這意味著當(dāng)一個(gè)或多個(gè)副本執(zhí)行初始同步或部分重新同步時(shí),主服務(wù)器將繼續(xù)處理查詢。

  • 復(fù)制在從服務(wù)器基本上也沒(méi)有阻塞。

    當(dāng)副本執(zhí)行初始同步時(shí),如果配置了replica-serve-stale-data參數(shù)為yes,則從服務(wù)器可以使用數(shù)據(jù)集的舊版本處理查詢。

    或者配置replica-serve-stale-data參數(shù)為no,在復(fù)制連接斷開(kāi)時(shí),向客戶端發(fā)送一個(gè)錯(cuò)誤,但是,在初始同步之后,從服務(wù)器刪除舊版本數(shù)據(jù)集并載入新版本數(shù)據(jù)集的那段時(shí)間內(nèi), 連接請(qǐng)求會(huì)被阻塞。

  • 復(fù)制功能可以單純地用于數(shù)據(jù)冗余(data redundancy), 也可以通過(guò)讓多個(gè)從服務(wù)器處理只讀命令請(qǐng)求來(lái)提升擴(kuò)展性(scalability)

  • 可以使用復(fù)制來(lái)避免讓主數(shù)據(jù)庫(kù)執(zhí)行持久化,而是復(fù)制到從服務(wù)器之后由從服務(wù)器進(jìn)行持久化,但是最好還是開(kāi)啟主服務(wù)器的持久化,因?yàn)橹匦聠?dòng)的主服務(wù)器將以空數(shù)據(jù)集開(kāi)始,如果從服務(wù)器嘗試與其同步,導(dǎo)致從服務(wù)器的數(shù)據(jù)也將被清空。

  • 缺點(diǎn)也很明顯,Redis主從模式仍具有單點(diǎn)風(fēng)險(xiǎn),一旦主服務(wù)器掛掉將無(wú)法進(jìn)行寫數(shù)據(jù)操作

redis復(fù)制原理

完全同步

主服務(wù)器后臺(tái)發(fā)送RDB文件給從服務(wù)器。從服務(wù)器接收rdb數(shù)據(jù)期間,主服務(wù)器會(huì)將新數(shù)據(jù)保存到復(fù)制客戶端緩沖區(qū),當(dāng)從服務(wù)器接收完rdb文件后,將其保存在磁盤上,然后將其加載到內(nèi)存中。加載完rdb文件后,如果開(kāi)啟aof,從服務(wù)器會(huì)進(jìn)行重寫操作。主服務(wù)器會(huì)把緩沖區(qū)的新數(shù)據(jù)發(fā)送給從服務(wù)器

部分同步

當(dāng)主從連接中斷后,從服務(wù)器使用psync命令向主服務(wù)器發(fā)送上次復(fù)制的偏移量,以及記錄的masterID,如果上次復(fù)制的偏移量仍存在主服務(wù)器的緩沖區(qū)中,并且masterID與主服務(wù)器的masterID一致,將會(huì)從緩沖區(qū)中上次斷開(kāi)的位置開(kāi)始增量復(fù)制,否則將會(huì)發(fā)生完全同步

psync命令

psync masterID offset

當(dāng)從服務(wù)器與主服務(wù)器建立連接時(shí),會(huì)判斷是不是初次復(fù)制,如果是的話,將會(huì)發(fā)送psync ? -1進(jìn)行完全同步,如果不是的話,會(huì)發(fā)送psync masterID offset嘗試部分同步,如果發(fā)送的masterID與主服務(wù)器一致且offset存在于主服務(wù)器的復(fù)制緩沖區(qū)中,將進(jìn)行部分同步,否則將會(huì)進(jìn)行完全同步
首先我們查看主服務(wù)器的masterID和offset

圖片

然后將masterID和offset復(fù)制到從服務(wù)器,期間我在主服務(wù)器寫了兩條數(shù)據(jù)

圖片

可以看到從服務(wù)器已經(jīng)有了主服務(wù)器的數(shù)據(jù)

redis復(fù)制配置

由于主服務(wù)器設(shè)置了密碼,需要在從服務(wù)器中指定主服務(wù)器的密碼
vim /etc/redis/6379.conf

masterauth 123456

由于我的redis版本是5.0,所以同步的命令較以前的命令不太一樣,但也兼容以前的同步命令

第一種方法:

配置文件修改
vim /etc/redis/6379.conf

replicaof masterip port   #5.0版本支持的命令
或者
slaveof masterip port

第二種方法:

在redis客戶端執(zhí)行命令,在客戶端執(zhí)行的同步命令將在重啟后失效

replicaof masterip port   #5.0版本支持的命令
或者
slaveof masterip port





配置好之后,主從的masterID信息是一樣的,這是主服務(wù)器的信息

圖片

這是從服務(wù)器的信息

圖片

主從同步后,從服務(wù)器將不能寫入數(shù)據(jù)

圖片

當(dāng)我們斷開(kāi)當(dāng)前數(shù)據(jù)庫(kù)的連接,與另一臺(tái)主服務(wù)器建立主從同步后,masterid也發(fā)生變化,將重新進(jìn)行完全同步

圖片

Redis哨兵

在redis主從模式下,一旦主服務(wù)器宕機(jī),需要人工進(jìn)行干預(yù)將某個(gè)從服務(wù)器轉(zhuǎn)換為主服務(wù)器,還需要去監(jiān)視r(shí)edis的狀態(tài),費(fèi)事費(fèi)力,還會(huì)造成一段時(shí)間內(nèi)服務(wù)不可用,對(duì)于某些應(yīng)用場(chǎng)景,這種處理方法并不可取,redis在2.8版本開(kāi)始提供了RedisSentinel工具,通過(guò)心跳檢測(cè)的方式監(jiān)視多個(gè)主服務(wù)器以及它們屬下的所有從服務(wù)器,并在某個(gè)主服務(wù)器下線時(shí)自動(dòng)對(duì)其實(shí)施故障轉(zhuǎn)移,Sentinel將選擇一個(gè)從服務(wù)器并將其提升為主服務(wù)器,其他剩余的從服務(wù)器實(shí)例將自動(dòng)重新配置為使用新的主服務(wù)器。

圖片

哨兵功能

  • 監(jiān)控。

    Sentinel會(huì)不斷檢查主從節(jié)點(diǎn)是否按預(yù)期工作。

  • 通知。

    Sentinel通過(guò)API通知客戶端出現(xiàn)問(wèn)題的節(jié)點(diǎn)

  • 自動(dòng)故障轉(zhuǎn)移。

    當(dāng)主服務(wù)器不能正常工作時(shí),Sentinel可以進(jìn)行故障轉(zhuǎn)移操作,在該操作中將從服務(wù)器升級(jí)為主服務(wù)器,將其他從服務(wù)器改為復(fù)制新主服務(wù)器。

  • 配置提供程序。

    客戶端在初始化時(shí),通過(guò)連接到Sentinels,獲取當(dāng)前主服務(wù)器的節(jié)點(diǎn)地址。

哨兵搭建

環(huán)境準(zhǔn)備

192.168.179.131:6379 master
192.168.179.132:6379 slave
192.168.179.134:6379 slave
192.168.179.131:26379 sentinel
192.168.179.132:26379 sentinel
192.168.179.134:26379 sentinel

主從節(jié)點(diǎn)配置

#192.168.179.131
port 6379
daemonize yes
logfile /var/log/redis_6379.log
dbfilename dump.rdb

#192.168.179.132
port 6379
daemonize yes
logfile /var/log/redis_6379.log
dbfilename dump.rdb
replicaof 192.168.179.131 6379

#192.168.179.134
port 6379
daemonize yes
logfile /var/log/redis_6379.log
dbfilename dump.rdb
replicaof 192.168.179.131 6379

測(cè)試主從復(fù)制是否配置成功

圖片

哨兵節(jié)點(diǎn)配置

三個(gè)哨兵節(jié)點(diǎn)相同配置,最后一句配置的意思是監(jiān)控192.168.179.131這個(gè)主節(jié)點(diǎn),節(jié)點(diǎn)名稱是mymaster,并且至少需要兩個(gè)哨兵節(jié)點(diǎn)同意才能判定主節(jié)點(diǎn)故障并進(jìn)行自動(dòng)遷移

port 26379
daemonize yes
sentinel monitor mymaster 192.168.179.131 6379 2

啟動(dòng)哨兵節(jié)點(diǎn)

以下兩條命令啟動(dòng)都可以,可以看到哨兵已經(jīng)啟動(dòng)成功

./src/redis-sentinel sentinel.conf
./src/redis-server sentinel.conf --sentinel

圖片

故障轉(zhuǎn)移測(cè)試

這里我將192.168.179.131的redis給關(guān)掉,查看從節(jié)點(diǎn)的復(fù)制信息,可以看到redis的主節(jié)點(diǎn)已經(jīng)切換為192.168.179.132

圖片

將192.168.179.131上面的redis再次啟動(dòng),查看節(jié)點(diǎn)狀態(tài)已經(jīng)變?yōu)閺墓?jié)點(diǎn)了






圖片

哨兵管理命令

  • info sentinel:

    獲取監(jiān)控的所有主節(jié)點(diǎn)的基本信息

  • sentinel masters:

    獲取所有被監(jiān)視主節(jié)點(diǎn)的信息

  • sentinel master

    :獲取指定主節(jié)點(diǎn)的詳細(xì)信息

  • sentinel slaves

    :獲取指定主節(jié)點(diǎn)的從節(jié)點(diǎn)的詳細(xì)信息

  • sentinel sentinels

    :獲取指定主節(jié)點(diǎn)的哨兵節(jié)點(diǎn)的詳細(xì)信息

  • sentinel get-master-addr-by-name mymaster:

    獲取主節(jié)點(diǎn)的IP地址和端口

  • sentinel is-master-down-by-addr:

    哨兵節(jié)點(diǎn)之間可以通過(guò)該命令詢問(wèn)主節(jié)點(diǎn)是否下線,從而對(duì)是否客觀下線做出判斷

  • sentinel failover
    強(qiáng)制對(duì)主節(jié)點(diǎn)進(jìn)行故障轉(zhuǎn)移
  • sentinel ckquorum: 檢查可用的哨兵數(shù)量

  • sentinel flushconfig: 強(qiáng)制寫入配置文件

  • sentinel remove

    :取消對(duì)指定主節(jié)點(diǎn)的監(jiān)視

Redis集群模式

上面也說(shuō)到,Redis主從模式中如果主服務(wù)器宕掉將無(wú)法進(jìn)行寫操作,即使哨兵模式提供了Redis的高可用,但面對(duì)數(shù)據(jù)量比較大的場(chǎng)景,Redis單點(diǎn)就不太能滿足這個(gè)要求了
Redis 集群是一個(gè)分布式、容錯(cuò)的 Redis 實(shí)現(xiàn), 集群可以使用的功能是普通單機(jī) Redis 所能使用的功能的一個(gè)子集。
Redis 集群是Redis的分布式實(shí)現(xiàn),集群中不存在中心節(jié)點(diǎn)或者代理節(jié)點(diǎn), 集群的其中一個(gè)主要設(shè)計(jì)目標(biāo)是達(dá)到線性可擴(kuò)展性。集群的容錯(cuò)功能是通過(guò)使用主節(jié)點(diǎn)和從節(jié)點(diǎn)兩種角色的節(jié)點(diǎn)來(lái)實(shí)現(xiàn)的:主節(jié)點(diǎn)和從節(jié)點(diǎn)使用完全相同的服務(wù)器實(shí)現(xiàn), 它們的功能也完全一樣, 但從節(jié)點(diǎn)通常僅用于替換失效的主節(jié)點(diǎn)。如果不需要保證“先寫入,后讀取”操作的一致性, 那么可以使用從節(jié)點(diǎn)來(lái)執(zhí)行只讀查詢。
Redis 集群不像單機(jī) Redis 那樣支持多數(shù)據(jù)庫(kù)功能, 集群只使用默認(rèn)的 0 號(hào)數(shù)據(jù)庫(kù), 并且不能使用 SELECT index 命令。

Redis集群中節(jié)點(diǎn)的工作內(nèi)容

  • 保存鍵值對(duì)數(shù)據(jù)。

  • 記錄集群的狀態(tài),包括鍵到正確節(jié)點(diǎn)的映射。

  • 自動(dòng)發(fā)現(xiàn)其他節(jié)點(diǎn),識(shí)別工作不正常的節(jié)點(diǎn),并從節(jié)點(diǎn)中選舉出新的主節(jié)點(diǎn)。

鍵分布模型

Redis 集群的鍵空間被分割為 16384 個(gè)槽(slot), 集群的最大節(jié)點(diǎn)數(shù)量也是 16384 個(gè)。當(dāng)一個(gè)集群處于“穩(wěn)定”狀態(tài)時(shí), 集群每個(gè)哈希槽都不會(huì)進(jìn)行移動(dòng),當(dāng)需要添加一個(gè)節(jié)點(diǎn)的時(shí)候,只需要將其他節(jié)點(diǎn)的某些哈希槽轉(zhuǎn)移到新節(jié)點(diǎn)上,當(dāng)需要?jiǎng)h除一個(gè)節(jié)點(diǎn)的時(shí)候,就把此節(jié)點(diǎn)的哈希槽轉(zhuǎn)移到其他節(jié)點(diǎn)上就可以了。一個(gè)主節(jié)點(diǎn)可以有任意多個(gè)從節(jié)點(diǎn), 這些從節(jié)點(diǎn)用于在主節(jié)點(diǎn)發(fā)生網(wǎng)絡(luò)斷線或者節(jié)點(diǎn)失效時(shí), 對(duì)主節(jié)點(diǎn)進(jìn)行替換。

集群節(jié)點(diǎn)屬性

每個(gè)節(jié)點(diǎn)在集群中都有一個(gè)獨(dú)一無(wú)二的 ID , 該 ID 是一個(gè)十六進(jìn)制表示的 160 位隨機(jī)數(shù), 在節(jié)點(diǎn)第一次啟動(dòng)時(shí)由 /dev/urandom 生成。
節(jié)點(diǎn)會(huì)將它的 ID 保存到配置文件, 只要這個(gè)配置文件不被刪除, 節(jié)點(diǎn)就會(huì)一直沿用這個(gè) ID 。
節(jié)點(diǎn) ID 用于標(biāo)識(shí)集群中的每個(gè)節(jié)點(diǎn)。一個(gè)節(jié)點(diǎn)可以改變它的 IP 和端口號(hào), 而不改變節(jié)點(diǎn) ID 。集群可以自動(dòng)識(shí)別出 IP/端口號(hào)的變化, 并將這一信息通過(guò) Gossip 協(xié)議廣播給其他節(jié)點(diǎn)知道。
以下是每個(gè)節(jié)點(diǎn)都有的關(guān)聯(lián)信息, 并且節(jié)點(diǎn)會(huì)將這些信息發(fā)送給其他節(jié)點(diǎn):

  • 節(jié)點(diǎn)所使用的 IP 地址和 TCP 端口號(hào)。

  • 節(jié)點(diǎn)的標(biāo)志(flags)。

  • 節(jié)點(diǎn)負(fù)責(zé)處理的哈希槽。

  • 節(jié)點(diǎn)最近一次使用集群連接發(fā)送 PING 數(shù)據(jù)包(packet)的時(shí)間。

  • 節(jié)點(diǎn)最近一次在回復(fù)中接收到 PONG 數(shù)據(jù)包的時(shí)間。

  • 集群將該節(jié)點(diǎn)標(biāo)記為下線的時(shí)間。

  • 該節(jié)點(diǎn)的從節(jié)點(diǎn)數(shù)量。

  • 如果該節(jié)點(diǎn)是從節(jié)點(diǎn)的話,那么它會(huì)記錄主節(jié)點(diǎn)的節(jié)點(diǎn) ID 。

    如果這是一個(gè)主節(jié)點(diǎn)的話,那么主節(jié)點(diǎn) ID 這一欄的值為 0000000 。

以上信息的其中一部分可以通過(guò)向集群中的任意節(jié)點(diǎn)(主節(jié)點(diǎn)或者從節(jié)點(diǎn)都可以)發(fā)送 CLUSTER NODES 命令來(lái)獲得。

集群數(shù)據(jù)一致性

Redis集群是無(wú)法保證數(shù)據(jù)的強(qiáng)一致性的

  1. 原因之一是因?yàn)镽edis集群是異步復(fù)制的,當(dāng)客戶端向服務(wù)端的某個(gè)主節(jié)點(diǎn)寫數(shù)據(jù)時(shí),主服務(wù)器會(huì)先響應(yīng)客戶端,之后再把寫操作請(qǐng)求發(fā)送給從節(jié)點(diǎn),在這過(guò)程之中,如果主節(jié)點(diǎn)發(fā)生了宕機(jī),而從節(jié)點(diǎn)還沒(méi)有收到寫操作的請(qǐng)求,那么這條數(shù)據(jù)將會(huì)永久丟失,當(dāng)然可以通過(guò)強(qiáng)制數(shù)據(jù)庫(kù)在回復(fù)客戶端以前刷新數(shù)據(jù)到磁盤,但這樣會(huì)導(dǎo)致性能降低。

  2. 還有一種情況是網(wǎng)絡(luò)分區(qū)(network partition)帶來(lái)的,當(dāng)Redis集群出現(xiàn)網(wǎng)絡(luò)分區(qū)時(shí),客戶端仍對(duì)處于小分區(qū)的主節(jié)點(diǎn)進(jìn)行寫操作,當(dāng)達(dá)到集群的node timeout的時(shí)間限制后,處于大分區(qū)的那個(gè)從節(jié)點(diǎn)將會(huì)取代處于小分區(qū)的主節(jié)點(diǎn)稱為新的主節(jié)點(diǎn),而在node timeout這段時(shí)間里客戶端向主節(jié)點(diǎn)寫入的數(shù)據(jù)將會(huì)丟失

節(jié)點(diǎn)失效檢測(cè)

  1. 當(dāng)一個(gè)節(jié)點(diǎn)向另一個(gè)節(jié)點(diǎn)發(fā)送 PING 命令時(shí), 目標(biāo)節(jié)點(diǎn)未能在node timeout內(nèi)返回 PING 命令的回復(fù)時(shí), 那么發(fā)送命令的節(jié)點(diǎn)會(huì)將目標(biāo)節(jié)點(diǎn)標(biāo)記為 PFAIL (可能已失效)。

  2. 每次當(dāng)節(jié)點(diǎn)對(duì)其他節(jié)點(diǎn)發(fā)送 PING 命令的時(shí)候, 它都會(huì)隨機(jī)地廣播三個(gè)它所知道的節(jié)點(diǎn)的信息, 這些信息里面的其中一項(xiàng)就是說(shuō)明節(jié)點(diǎn)是否已經(jīng)被標(biāo)記為 PFAIL 或者 FAIL 。

  3. 如果節(jié)點(diǎn)已經(jīng)將某個(gè)節(jié)點(diǎn)標(biāo)記為 PFAIL , 并且集群中的大部分其他主節(jié)點(diǎn)也認(rèn)為那個(gè)節(jié)點(diǎn)進(jìn)入了失效狀態(tài), 那么節(jié)點(diǎn)會(huì)將那個(gè)失效節(jié)點(diǎn)的狀態(tài)標(biāo)記為 FAIL 。

  4. 一旦某個(gè)節(jié)點(diǎn)被標(biāo)記為 FAIL , 關(guān)于這個(gè)節(jié)點(diǎn)已失效的信息就會(huì)被廣播到整個(gè)集群, 所有接收到這條信息的節(jié)點(diǎn)都會(huì)將失效節(jié)點(diǎn)標(biāo)記為 FAIL 。

集群搭建

編輯配置文件啟動(dòng)集群節(jié)點(diǎn)

每個(gè)集群實(shí)例都要開(kāi)啟,之后重啟redis實(shí)例

cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000

連接集群節(jié)點(diǎn)并分配槽

./redis-cli --cluster create 192.168.179.131:6379 192.168.179.131:6380 192.168.179.134:6379 192.168.179.134:6380 192.168.179.132:6379 192.168.179.132:6380 --cluster-replicas 1

圖片

可以查看集群的節(jié)點(diǎn)信息,輸入集群內(nèi)任意節(jié)點(diǎn)地址即可

./redis-cli --cluster check 192.168.179.132:6379

圖片

集群驗(yàn)證

當(dāng)我們set一個(gè)key 時(shí),會(huì)用CRC16算法來(lái)取模得到所屬的slot,然后將這個(gè)key 分到哈希槽區(qū)間的節(jié)點(diǎn)上,當(dāng)get數(shù)據(jù)的時(shí)候,也是通過(guò)這種方法去對(duì)應(yīng)的節(jié)點(diǎn)上獲取數(shù)據(jù)

./redis-cli -c -h 192.168.179.132 -p 6380
192.168.179.132:6380> set key 1
-> Redirected to slot [12539] located at 192.168.179.132:6379
OK
./redis-cli -c -h 192.168.179.134 -p 6379
192.168.179.134:6379> get key
-> Redirected to slot [12539] located at 192.168.179.132:6379
"1"


作者:wanger


歡迎關(guān)注:運(yùn)維開(kāi)發(fā)故事