真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Redis緩存在系統(tǒng)中用來做什么

本篇內(nèi)容介紹了“redis緩存在系統(tǒng)中用來做什么”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

成都創(chuàng)新互聯(lián)自2013年起,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目做網(wǎng)站、網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元祿勸做網(wǎng)站,已為上家服務(wù),為祿勸各地企業(yè)和個人服務(wù),聯(lián)系電話:18982081108

一、緩存在系統(tǒng)中用來做什么?

1. 少量數(shù)據(jù)存儲,高速讀寫訪問。通過數(shù)據(jù)全部in-momery 的方式來保證高速訪問,同時提供數(shù)據(jù)落地的功能,實際這正是Redis最主要的適用場景。

2. 海量數(shù)據(jù)存儲,分布式系統(tǒng)支持,數(shù)據(jù)一致性保證,方便的集群節(jié)點添加/刪除。Redis3.0以后開始支持集群,實現(xiàn)了半自動化的數(shù)據(jù)分片,不過需要smart-client的支持。

二、從不同的角度來詳細介紹redis

網(wǎng)絡(luò)模型:Redis使用單線程的IO復(fù)用模型,自己封裝了一個簡單的AeEvent事件處理框架,主要實現(xiàn)了epoll、kqueue和select,對于單純只有IO操作來說,單線程可以將速度優(yōu)勢發(fā)揮到最大,但是Redis也提供了一些簡單的計算功能,比如排序、聚合等,對于這些操作,單線程模型實際會嚴(yán)重影響整體吞吐量,CPU計算過程中,整個IO調(diào)度都是被阻塞住的。

內(nèi)存管理:Redis使用現(xiàn)場申請內(nèi)存的方式來存儲數(shù)據(jù),并且很少使用free-list等方式來優(yōu)化內(nèi)存分配,會在一定程度上存在內(nèi)存碎片,Redis跟據(jù)存儲命令參數(shù),會把帶過期時間的數(shù)據(jù)單獨存放在一起,并把它們稱為臨時數(shù)據(jù),非臨時數(shù)據(jù)是永遠不會被剔除的,即便物理內(nèi)存不夠,導(dǎo)致swap也不會剔除任何非臨時數(shù)據(jù)(但會嘗試剔除部分臨時數(shù)據(jù)),這點上Redis更適合作為存儲而不是cache。

數(shù)據(jù)一致性問題:在一致性問題上,個人感覺redis沒有memcached實現(xiàn)的好,Memcached提供了cas命令,可以保證多個并發(fā)訪問操作同一份數(shù)據(jù)的一致性問題。 Redis沒有提供cas 命令,并不能保證這點,不過Redis提供了事務(wù)的功能,可以保證一串命令的原子性,中間不會被任何操作打斷。

支持的KEY類型:Redis除key/value之外,還支持list,set,sorted set,hash等眾多數(shù)據(jù)結(jié)構(gòu),提供了KEYS進行枚舉操作,但不能在線上使用,如果需要枚舉線上數(shù)據(jù),Redis提供了工具可以直接掃描其dump文件,枚舉出所有數(shù)據(jù),Redis還同時提供了持久化和復(fù)制等功能。

客戶端支持:redis官方提供了豐富的客戶端支持,包括了絕大多數(shù)編程語言的客戶端,比如我此次測試就選擇了官方推薦了Java客戶端Jedis.里面提供了豐富的接口、方法使得開發(fā)人員無需關(guān)系內(nèi)部的數(shù)據(jù)分片、讀取數(shù)據(jù)的路由等,只需簡單的調(diào)用即可,非常方便。

數(shù)據(jù)復(fù)制:從2.8開始,Slave會周期性(每秒一次)發(fā)起一個Ack確認復(fù)制流(replication stream)被處理進度, Redis復(fù)制工作原理詳細過程如下:

1. 如果設(shè)置了一個Slave,無論是第一次連接還是重連到Master,它都會發(fā)出一個SYNC命令;

2. 當(dāng)Master收到SYNC命令之后,會做兩件事:

a) Master執(zhí)行BGSAVE:后臺寫數(shù)據(jù)到磁盤(rdb快照);

b) Master同時將新收到的寫入和修改數(shù)據(jù)集的命令存入緩沖區(qū)(非查詢類);

3. 當(dāng)Master在后臺把數(shù)據(jù)保存到快照文件完成之后,Master會把這個快照文件傳送給Slave,而Slave則把內(nèi)存清空后,加載該文件到內(nèi)存中;

4. 而Master也會把此前收集到緩沖區(qū)中的命令,通過Reids命令協(xié)議形式轉(zhuǎn)發(fā)給Slave,Slave執(zhí)行這些命令,實現(xiàn)和Master的同步;

5. Master/Slave此后會不斷通過異步方式進行命令的同步,達到最終數(shù)據(jù)的同步一致;

6. 需要注意的是Master和Slave之間一旦發(fā)生重連都會引發(fā)全量同步操作。但在2.8之后,也可能是部分同步操作。

2.8開始,當(dāng)Master和Slave之間的連接斷開之后,他們之間可以采用持續(xù)復(fù)制處理方式代替采用全量同步。

Master端為復(fù)制流維護一個內(nèi)存緩沖區(qū)(in-memory backlog),記錄最近發(fā)送的復(fù)制流命令;同時,Master和Slave之間都維護一個復(fù)制偏移量(replication offset)和當(dāng)前Master服務(wù)器ID(Masterrun id)。

當(dāng)網(wǎng)絡(luò)斷開,Slave嘗試重連時:

a. 如果MasterID相同(即仍是斷網(wǎng)前的Master服務(wù)器),并且從斷開時到當(dāng)前時刻的歷史命令依然在Master的內(nèi)存緩沖區(qū)中存在,則Master會將缺失的這段時間的所有命令發(fā)送給Slave執(zhí)行,然后復(fù)制工作就可以繼續(xù)執(zhí)行了;

b. 否則,依然需要全量復(fù)制操作。

讀寫分離:redis支持讀寫分離,而且使用簡單,只需在配置文件中把redis讀服務(wù)器和寫服務(wù)器進行配置,多個服務(wù)器使用逗號分開如下:

Redis緩存在系統(tǒng)中用來做什么

水平動態(tài)擴展:歷時三年之久,終于等來了期待已由的Redis 3.0。新版本主要是實現(xiàn)了Cluster的功能,增刪集群節(jié)點后會自動的進行數(shù)據(jù)遷移。實現(xiàn) Redis 集群在線重配置的核心就是將槽從一個節(jié)點移動到另一個節(jié)點的能力。因為一個哈希槽實際上就是一些鍵的集合, 所以 Redis 集群在重哈希(rehash)時真正要做的,就是將一些鍵從一個節(jié)點移動到另一個節(jié)點。

數(shù)據(jù)淘汰策略:redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時候,就會施行數(shù)據(jù)淘汰策略。redis 提供 6種數(shù)據(jù)淘汰策略:

  • volatile-lru:從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰

  • volatile-ttl:從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰

  • volatile-random:從已設(shè)置過期時間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰

  • allkeys-lru:從數(shù)據(jù)集(server.db[i].dict)中挑選最近最少使用的數(shù)據(jù)淘汰

  • allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰

  • no-enviction(驅(qū)逐):禁止驅(qū)逐數(shù)據(jù)

三、集群(即分布式)

下面詳細介紹一下redis的集群功能,從3.0以后的版本開始支持集群功能,也就是正真意義上實現(xiàn)了分布式。

Redis 集群是一個分布式(distributed)、容錯(fault-tolerant)的 Redis 實現(xiàn), 集群可以使用的功能是普通單機 Redis 所能使用的功能的一個子集(subset)。

Redis 集群中不存在中心(central)節(jié)點或者代理(proxy)節(jié)點, 集群的其中一個主要設(shè)計目標(biāo)是達到線性可擴展性(linear scalability)。

Redis 集群為了保證一致性(consistency)而犧牲了一部分容錯性: 系統(tǒng)會在保證對網(wǎng)絡(luò)斷線(netsplit)和節(jié)點失效(node failure)具有有限(limited)抵抗力的前提下,盡可能地保持?jǐn)?shù)據(jù)的一致性。

集群特性:

(1)所有的redis節(jié)點彼此互聯(lián)(PING-PONG機制),內(nèi)部使用二進制協(xié)議優(yōu)化傳輸速度和帶寬。

(2)節(jié)點的fail是通過集群中超過半數(shù)的節(jié)點檢測失效時才生效。

(3)客戶端與redis節(jié)點直連,不需要中間proxy層.客戶端不需要連接集群所有節(jié)點,連接集群中任何一個可用節(jié)點即可。

(4)redis-cluster把所有的物理節(jié)點映射到[0-16383]slot上,cluster 負責(zé)維護node<->slot<->value

Redis 集群實現(xiàn)的功能子集:

Redis集群實現(xiàn)了單機 Redis 中, 所有處理單個數(shù)據(jù)庫鍵的命令。針對多個數(shù)據(jù)庫鍵的復(fù)雜計算操作, 比如集合的并集操作、合集操作沒有被實現(xiàn),那些理論上需要使用多個節(jié)點的多個數(shù)據(jù)庫鍵才能完成的命令也沒有被實現(xiàn)。在將來, 用戶也許可以通過 MIGRATE COPY 命令,在集群的計算節(jié)點(computation node)中執(zhí)行針對多個數(shù)據(jù)庫鍵的只讀操作, 但集群本身不會去實現(xiàn)那些需要將多個數(shù)據(jù)庫鍵在多個節(jié)點中移來移去的復(fù)雜多鍵命令。

Redis 集群不像單機Redis 那樣支持多數(shù)據(jù)庫功能, 集群只使用默認的 0 號數(shù)據(jù)庫, 并且不能使用 SELECT 命令。

Redis 集群協(xié)議中的客戶端和服務(wù)器:

Redis 集群中的節(jié)點有以下責(zé)任:

1. 持有鍵值對數(shù)據(jù)。

2. 記錄集群的狀態(tài),包括鍵到正確節(jié)點的映射(mappingkeys to right nodes)。

3. 自動發(fā)現(xiàn)其他節(jié)點,識別工作不正常的節(jié)點,并在有需要時,在從節(jié)點中選舉出新的主節(jié)點。

為了執(zhí)行以上列出的任務(wù), 集群中的每個節(jié)點都與其他節(jié)點建立起了“集群連接(cluster bus)”, 該連接是一個 TCP 連接, 使用二進制協(xié)議進行通訊。

節(jié)點之間使用Gossip 協(xié)議 來進行以下工作:

1. 傳播(propagate)關(guān)于集群的信息,以此來發(fā)現(xiàn)新的節(jié)點。

2. 向其他節(jié)點發(fā)送 PING 數(shù)據(jù)包,以此來檢查目標(biāo)節(jié)點是否正常運作。

3. 在特定事件發(fā)生時,發(fā)送集群信息。

4. 除此之外, 集群連接還用于在集群中發(fā)布或訂閱信息。

因為集群節(jié)點不能代理(proxy)命令請求, 所以客戶端應(yīng)該在節(jié)點返回 -MOVED 或者 -ASK 轉(zhuǎn)向(redirection)錯誤時,自行將命令請求轉(zhuǎn)發(fā)至其他節(jié)點。因為客戶端可以自由地向集群中的任何一個節(jié)點發(fā)送命令請求, 并可以在有需要時, 根據(jù)轉(zhuǎn)向錯誤所提供的信息, 將命令轉(zhuǎn)發(fā)至正確的節(jié)點,所以在理論上來說, 客戶端是無須保存集群狀態(tài)信息的。不過, 如果客戶端可以將鍵和節(jié)點之間的映射信息保存起來, 可以有效地減少可能出現(xiàn)的轉(zhuǎn)向次數(shù), 籍此提升命令執(zhí)行的效率。

鍵分布模型

Redis 集群的鍵空間被分割為 16384 個槽(slot), 集群的最大節(jié)點數(shù)量也是 16384 個。

推薦的最大節(jié)點數(shù)量為 1000 個左右。每個主節(jié)點都負責(zé)處理 16384 個哈希槽的其中一部分。

當(dāng)我們說一個集群處于“穩(wěn)定”(stable)狀態(tài)時, 指的是集群沒有在執(zhí)行重配(reconfiguration)操作,每個哈希槽都只由一個節(jié)點進行處理。重配置指的是將某個/某些槽從一個節(jié)點移動到另一個節(jié)點。一個主節(jié)點可以有任意多個從節(jié)點,這些從節(jié)點用于在主節(jié)點發(fā)生網(wǎng)絡(luò)斷線或者節(jié)點失效時, 對主節(jié)點進行替換。

集群節(jié)點屬性:

每個節(jié)點在集群中都有一個獨一無二的 ID , 該 ID 是一個十六進制表示的 160 位隨機數(shù), 在節(jié)點第一次啟動時由 /dev/urandom 生成。

節(jié)點會將它的 ID 保存到配置文件, 只要這個配置文件不被刪除,節(jié)點就會一直沿用這個 ID 。節(jié)點 ID 用于標(biāo)識集群中的每個節(jié)點。一個節(jié)點可以改變它的 IP 和端口號, 而不改變節(jié)點 ID 。集群可以自動識別出 IP/端口號的變化, 并將這一信息通過 Gossip 協(xié)議廣播給其他節(jié)點知道。

以下是每個節(jié)點都有的關(guān)聯(lián)信息, 并且節(jié)點會將這些信息發(fā)送給其他節(jié)點:

1. 節(jié)點所使用的 IP 地址和 TCP 端口號。

2. 節(jié)點的標(biāo)志(flags)。

3. 節(jié)點負責(zé)處理的哈希槽。

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

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

6. 集群將該節(jié)點標(biāo)記為下線的時間。

7. 該節(jié)點的從節(jié)點數(shù)量。

8. 如果該節(jié)點是從節(jié)點的話,那么它會記錄主節(jié)點的節(jié)點 ID 。如果這是一個主節(jié)點的話,那么主節(jié)點 ID 這一欄的值為 0000000 。

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

節(jié)點握手:

節(jié)點總是應(yīng)答(accept)來自集群連接端口的連接請求,并對接收到的 PING 數(shù)據(jù)包進行回復(fù), 即使這個 PING 數(shù)據(jù)包來自不可信的節(jié)點。然而,除了 PING 之外, 節(jié)點會拒絕其他所有并非來自集群節(jié)點的數(shù)據(jù)包。要讓一個節(jié)點承認另一個節(jié)點同屬于一個集群,只有以下兩種方法:

1. 一個節(jié)點可以通過向另一個節(jié)點發(fā)送 MEET 信息,來強制讓接收信息的節(jié)點承認發(fā)送信息的節(jié)點為集群中的一份子。 一個節(jié)點僅在管理員顯式地向它發(fā)送CLUSTER MEET ipport 命令時, 才會向另一個節(jié)點發(fā)送 MEET 信息。

2. 如果一個可信節(jié)點向另一個節(jié)點傳播第三者節(jié)點的信息, 那么接收信息的那個節(jié)點也會將第三者節(jié)點識別為集群中的一份子。也即是說, 如果 A 認識 B , B 認識 C , 并且 B 向 A 傳播關(guān)于 C 的信息, 那么 A 也會將 C 識別為集群中的一份子, 并嘗試連接 C 。

這意味著如果我們將一個/一些新節(jié)點添加到一個集群中, 那么這個/這些新節(jié)點最終會和集群中已有的其他所有節(jié)點連接起來。

這說明只要管理員使用 CLUSTER MEET 命令顯式地指定了可信關(guān)系,集群就可以自動發(fā)現(xiàn)其他節(jié)點。這種節(jié)點識別機制通過防止不同的 Redis 集群因為 IP 地址變更或者其他網(wǎng)絡(luò)事件的發(fā)生而產(chǎn)生意料之外的聯(lián)合(mix), 從而使得集群更具健壯性。當(dāng)節(jié)點的網(wǎng)絡(luò)連接斷開時,它會主動連接其他已知的節(jié)點。

MOVED 轉(zhuǎn)向:

一個 Redis 客戶端可以向集群中的任意節(jié)點(包括從節(jié)點)發(fā)送命令請求。節(jié)點會對命令請求進行分析, 如果該命令是集群可以執(zhí)行的命令, 那么節(jié)點會查找這個命令所要處理的鍵所在的槽。如果要查找的哈希槽正好就由接收到命令的節(jié)點負責(zé)處理,那么節(jié)點就直接執(zhí)行這個命令。另一方面, 如果所查找的槽不是由該節(jié)點處理的話, 節(jié)點將查看自身內(nèi)部所保存的哈希槽到節(jié)點 ID 的映射記錄,并向客戶端回復(fù)一個 MOVED 錯誤。

即使客戶端在重新發(fā)送 GET 命令之前, 等待了非常久的時間,以至于集群又再次更改了配置, 使得節(jié)點 127.0.0.1:6381 已經(jīng)不再處理槽 3999 , 那么當(dāng)客戶端向節(jié)點 127.0.0.1:6381 發(fā)送 GET 命令的時候, 節(jié)點將再次向客戶端返回 MOVED 錯誤, 指示現(xiàn)在負責(zé)處理槽 3999 的節(jié)點。

雖然我們用 ID 來標(biāo)識集群中的節(jié)點, 但是為了讓客戶端的轉(zhuǎn)向操作盡可能地簡單,,節(jié)點在 MOVED 錯誤中直接返回目標(biāo)節(jié)點的 IP 和端口號,而不是目標(biāo)節(jié)點的 ID 。但一個客戶端應(yīng)該記錄(memorize)下“槽 3999 由節(jié)點 127.0.0.1:6381 負責(zé)處理“這一信息, 這樣當(dāng)再次有命令需要對槽 3999 執(zhí)行時, 客戶端就可以加快尋找正確節(jié)點的速度。

注意, 當(dāng)集群處于穩(wěn)定狀態(tài)時, 所有客戶端最終都會保存有一個哈希槽至節(jié)點的映射記錄(map of hash slots to nodes), 使得集群非常高效: 客戶端可以直接向正確的節(jié)點發(fā)送命令請求, 無須轉(zhuǎn)向、代理或者其他任何可能發(fā)生單點故障(single point failure)的實體(entiy)。

除了 MOVED轉(zhuǎn)向錯誤之外, 一個客戶端還應(yīng)該可以處理稍后介紹的 ASK 轉(zhuǎn)向錯誤。

集群在線重配置:

Redis 集群支持在集群運行的過程中添加或者移除節(jié)點。實際上, 節(jié)點的添加操作和節(jié)點的刪除操作可以抽象成同一個操作,那就是, 將哈希槽從一個節(jié)點移動到另一個節(jié)點:添加一個新節(jié)點到集群, 等于將其他已存在節(jié)點的槽移動到一個空白的新節(jié)點里面。從集群中移除一個節(jié)點, 等于將被移除節(jié)點的所有槽移動到集群的其他節(jié)點上面去。

因此, 實現(xiàn)Redis 集群在線重配置的核心就是將槽從一個節(jié)點移動到另一個節(jié)點的能力。 因為一個哈希槽實際上就是一些鍵的集合, 所以 Redis 集群在重哈希(rehash)時真正要做的, 就是將一些鍵從一個節(jié)點移動到另一個節(jié)點。

要理解Redis 集群如何將槽從一個節(jié)點移動到另一個節(jié)點, 我們需要對 CLUSTER 命令的各個子命令進行介紹,這些命理負責(zé)管理集群節(jié)點的槽轉(zhuǎn)換表(slots translation table)。

以下是CLUSTER 命令可用的子命令:

Redis緩存在系統(tǒng)中用來做什么

最開頭的兩條命令A(yù)DDSLOTS 和 DELSLOTS 分別用于向節(jié)點指派(assign)或者移除節(jié)點,當(dāng)槽被指派或者移除之后, 節(jié)點會將這一信息通過 Gossip 協(xié)議傳播到整個集群。 ADDSLOTS 命令通常在新創(chuàng)建集群時, 作為一種快速地將各個槽指派給各個節(jié)點的手段來使用。

CLUSTERSETSLOT slot NODE node 子命令可以將指定的槽 slot 指派給節(jié)點node 。

至于CLUSTER SETSLOT slot MIGRATING node 命令和 CLUSTER SETSLOTslot IMPORTING node 命令, 前者用于將給定節(jié)點 node 中的槽 slot 遷移出節(jié)點, 而后者用于將給定槽 slot導(dǎo)入到節(jié)點 node :

當(dāng)一個槽被設(shè)置為MIGRATING 狀態(tài)時, 原來持有這個槽的節(jié)點仍然會繼續(xù)接受關(guān)于這個槽的命令請求, 但只有命令所處理的鍵仍然存在于節(jié)點時, 節(jié)點才會處理這個命令請求。

如果命令所使用的鍵不存在與該節(jié)點, 那么節(jié)點將向客戶端返回一個 -ASK 轉(zhuǎn)向(redirection)錯誤, 告知客戶端, 要將命令請求發(fā)送到槽的遷移目標(biāo)節(jié)點。

當(dāng)一個槽被設(shè)置為IMPORTING 狀態(tài)時, 節(jié)點僅在接收到 ASKING 命令之后, 才會接受關(guān)于這個槽的命令請求。

如果客戶端沒有向節(jié)點發(fā)送 ASKING 命令, 那么節(jié)點會使用 -MOVED 轉(zhuǎn)向錯誤將命令請求轉(zhuǎn)向至真正負責(zé)處理這個槽的節(jié)點。

上面關(guān)于MIGRATING 和 IMPORTING 的說明有些難懂, 讓我們用一個實際的實例來說明一下。

假設(shè)現(xiàn)在, 我們有 A 和 B 兩個節(jié)點, 并且我們想將槽8 從節(jié)點 A 移動到節(jié)點 B , 于是我們:

向節(jié)點 B 發(fā)送命令 CLUSTER SETSLOT 8 IMPORTING A

向節(jié)點 A 發(fā)送命令 CLUSTER SETSLOT 8 MIGRATING B

每當(dāng)客戶端向其他節(jié)點發(fā)送關(guān)于哈希槽 8 的命令請求時, 這些節(jié)點都會向客戶端返回指向節(jié)點 A 的轉(zhuǎn)向信息:

如果命令要處理的鍵已經(jīng)存在于槽 8 里面, 那么這個命令將由節(jié)點 A 處理。

如果命令要處理的鍵未存在于槽 8 里面(比如說,要向槽添加一個新的鍵), 那么這個命令由節(jié)點 B 處理。

這種機制將使得節(jié)點 A 不再創(chuàng)建關(guān)于槽 8 的任何新鍵。

與此同時, 一個特殊的客戶端 redis-trib 以及 Redis 集群配置程序(configuration utility)會將節(jié)點 A 中槽 8 里面的鍵移動到節(jié)點 B 。

鍵的移動操作由以下兩個命令執(zhí)行:

CLUSTERGETKEYSINSLOT slot count

上面的命令會讓節(jié)點返回 count 個 slot 槽中的鍵, 對于命令所返回的每個鍵, redis-trib 都會向節(jié)點 A 發(fā)送一條 MIGRATE 命令, 該命令會將所指定的鍵原子地(atomic)從節(jié)點 A 移動到節(jié)點 B (在移動鍵期間,兩個節(jié)點都會處于阻塞狀態(tài),以免出現(xiàn)競爭條件)。

以下為MIGRATE 命令的運作原理:

MIGRATEtarget_host target_port key target_database id timeout

執(zhí)行MIGRATE 命令的節(jié)點會連接到 target 節(jié)點, 并將序列化后的 key 數(shù)據(jù)發(fā)送給 target , 一旦 target 返回 OK , 節(jié)點就將自己的 key 從數(shù)據(jù)庫中刪除。

從一個外部客戶端的視角來看, 在某個時間點上, 鍵 key 要么存在于節(jié)點 A , 要么存在于節(jié)點 B , 但不會同時存在于節(jié)點 A 和節(jié)點 B 。

因為 Redis集群只使用 0 號數(shù)據(jù)庫, 所以當(dāng) MIGRATE 命令被用于執(zhí)行集群操作時, target_database 的值總是 0 。

target_database參數(shù)的存在是為了讓 MIGRATE 命令成為一個通用命令, 從而可以作用于集群以外的其他功能。

我們對MIGRATE 命令做了優(yōu)化, 使得它即使在傳輸包含多個元素的列表鍵這樣的復(fù)雜數(shù)據(jù)時, 也可以保持高效。

不過, 盡管MIGRATE 非常高效, 對一個鍵非常多、并且鍵的數(shù)據(jù)量非常大的集群來說, 集群重配置還是會占用大量的時間, 可能會導(dǎo)致集群沒辦法適應(yīng)那些對于響應(yīng)時間有嚴(yán)格要求的應(yīng)用程序。

ASK 轉(zhuǎn)向:

在之前介紹 MOVED 轉(zhuǎn)向的時候, 我們說除了 MOVED 轉(zhuǎn)向之外, 還有另一種 ASK 轉(zhuǎn)向。當(dāng)節(jié)點需要讓一個客戶端長期地(permanently)將針對某個槽的命令請求發(fā)送至另一個節(jié)點時,節(jié)點向客戶端返回 MOVED 轉(zhuǎn)向。另一方面, 當(dāng)節(jié)點需要讓客戶端僅僅在下一個命令請求中轉(zhuǎn)向至另一個節(jié)點時, 節(jié)點向客戶端返回 ASK 轉(zhuǎn)向。

比如說, 在我們上一節(jié)列舉的槽 8 的例子中, 因為槽 8 所包含的各個鍵分散在節(jié)點 A 和節(jié)點 B 中, 所以當(dāng)客戶端在節(jié)點 A 中沒找到某個鍵時, 它應(yīng)該轉(zhuǎn)向到節(jié)點 B 中去尋找, 但是這種轉(zhuǎn)向應(yīng)該僅僅影響一次命令查詢,而不是讓客戶端每次都直接去查找節(jié)點 B : 在節(jié)點 A 所持有的屬于槽 8 的鍵沒有全部被遷移到節(jié)點 B 之前, 客戶端應(yīng)該先訪問節(jié)點 A , 然后再訪問節(jié)點 B 。因為這種轉(zhuǎn)向只針對 16384 個槽中的其中一個槽, 所以轉(zhuǎn)向?qū)涸斐傻男阅軗p耗屬于可接受的范圍。

因為上述原因, 如果我們要在查找節(jié)點 A 之后, 繼續(xù)查找節(jié)點 B , 那么客戶端在向節(jié)點 B 發(fā)送命令請求之前, 應(yīng)該先發(fā)送一個 ASKING 命令, 否則這個針對帶有IMPORTING 狀態(tài)的槽的命令請求將被節(jié)點 B 拒絕執(zhí)行。接收到客戶端 ASKING 命令的節(jié)點將為客戶端設(shè)置一個一次性的標(biāo)志(flag), 使得客戶端可以執(zhí)行一次針對 IMPORTING 狀態(tài)的槽的命令請求。從客戶端的角度來看, ASK 轉(zhuǎn)向的完整語義(semantics)如下:

1. 如果客戶端接收到 ASK 轉(zhuǎn)向, 那么將命令請求的發(fā)送對象調(diào)整為轉(zhuǎn)向所指定的節(jié)點。

2. 先發(fā)送一個 ASKING 命令,然后再發(fā)送真正的命令請求。

3. 不必更新客戶端所記錄的槽 8 至節(jié)點的映射: 槽 8 應(yīng)該仍然映射到節(jié)點 A , 而不是節(jié)點 B 。

一旦節(jié)點 A 針對槽 8 的遷移工作完成, 節(jié)點 A 在再次收到針對槽 8 的命令請求時, 就會向客戶端返回 MOVED 轉(zhuǎn)向, 將關(guān)于槽 8 的命令請求長期地轉(zhuǎn)向到節(jié)點 B 。

注意, 即使客戶端出現(xiàn) Bug , 過早地將槽 8 映射到了節(jié)點 B 上面, 但只要這個客戶端不發(fā)送 ASKING 命令, 客戶端發(fā)送命令請求的時候就會遇上 MOVED 錯誤, 并將它轉(zhuǎn)向回節(jié)點 A 。

容錯:

節(jié)點失效檢測,以下是節(jié)點失效檢查的實現(xiàn)方法:

1. 當(dāng)一個節(jié)點向另一個節(jié)點發(fā)送 PING 命令, 但是目標(biāo)節(jié)點未能在給定的時限內(nèi)返回 PING 命令的回復(fù)時, 那么發(fā)送命令的節(jié)點會將目標(biāo)節(jié)點標(biāo)記為 PFAIL(possible failure,可能已失效)。等待 PING 命令回復(fù)的時限稱為“節(jié)點超時時限(node timeout)”, 是一個節(jié)點選項(node-wise setting)。

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

當(dāng)節(jié)點接收到其他節(jié)點發(fā)來的信息時, 它會記下那些被其他節(jié)點標(biāo)記為失效的節(jié)點。這稱為失效報告(failure report)。

3. 如果節(jié)點已經(jīng)將某個節(jié)點標(biāo)記為 PFAIL , 并且根據(jù)節(jié)點所收到的失效報告顯式,集群中的大部分其他主節(jié)點也認為那個節(jié)點進入了失效狀態(tài), 那么節(jié)點會將那個失效節(jié)點的狀態(tài)標(biāo)記為 FAIL 。

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

簡單來說, 一個節(jié)點要將另一個節(jié)點標(biāo)記為失效, 必須先詢問其他節(jié)點的意見, 并且得到大部分主節(jié)點的同意才行。因為過期的失效報告會被移除,所以主節(jié)點要將某個節(jié)點標(biāo)記為 FAIL 的話, 必須以最近接收到的失效報告作為根據(jù)。

從節(jié)點選舉:一旦某個主節(jié)點進入 FAIL 狀態(tài), 如果這個主節(jié)點有一個或多個從節(jié)點存在,那么其中一個從節(jié)點會被升級為新的主節(jié)點, 而其他從節(jié)點則會開始對這個新的主節(jié)點進行復(fù)制。

新的主節(jié)點由已下線主節(jié)點屬下的所有從節(jié)點中自行選舉產(chǎn)生,以下是選舉的條件:

1. 這個節(jié)點是已下線主節(jié)點的從節(jié)點。

2. 已下線主節(jié)點負責(zé)處理的槽數(shù)量非空。

3. 從節(jié)點的數(shù)據(jù)被認為是可靠的, 也即是, 主從節(jié)點之間的復(fù)制連接(replication link)的斷線時長不能超過節(jié)點超時時限(nodetimeout)乘以REDIS_CLUSTER_SLAVE_VALIDITY_MULT 常量得出的積。

如果一個從節(jié)點滿足了以上的所有條件, 那么這個從節(jié)點將向集群中的其他主節(jié)點發(fā)送授權(quán)請求, 詢問它們,是否允許自己(從節(jié)點)升級為新的主節(jié)點。

如果發(fā)送授權(quán)請求的從節(jié)點滿足以下屬性, 那么主節(jié)點將向從節(jié)點返FAILOVER_AUTH_GRANTED 授權(quán), 同意從節(jié)點的升級要求:

1. 發(fā)送授權(quán)請求的是一個從節(jié)點, 并且它所屬的主節(jié)點處于 FAIL狀態(tài)。

2. 在已下線主節(jié)點的所有從節(jié)點中, 這個從節(jié)點的節(jié)點 ID 在排序中是最小的。

3. 這個從節(jié)點處于正常的運行狀態(tài): 它沒有被標(biāo)記為 FAIL 狀態(tài),也沒有被標(biāo)記為 PFAIL 狀態(tài)。

一旦某個從節(jié)點在給定的時限內(nèi)得到大部分主節(jié)點的授權(quán),它就會開始執(zhí)行以下故障轉(zhuǎn)移操作:

1. 通過 PONG 數(shù)據(jù)包(packet)告知其他節(jié)點, 這個節(jié)點現(xiàn)在是主節(jié)點了。

2. 通過 PONG 數(shù)據(jù)包告知其他節(jié)點, 這個節(jié)點是一個已升級的從節(jié)點(promoted slave)。

3. 接管(claiming)所有由已下線主節(jié)點負責(zé)處理的哈希槽。

4. 顯式地向所有節(jié)點廣播一個 PONG 數(shù)據(jù)包, 加速其他節(jié)點識別這個節(jié)點的進度,而不是等待定時的 PING / PONG 數(shù)據(jù)包。

所有其他節(jié)點都會根據(jù)新的主節(jié)點對配置進行相應(yīng)的更新:

  • 所有被新的主節(jié)點接管的槽會被更新。

  • 已下線主節(jié)點的所有從節(jié)點會察覺到 PROMOTED 標(biāo)志,并開始對新的主節(jié)點進行復(fù)制。

  • 如果已下線的主節(jié)點重新回到上線狀態(tài), 那么它會察覺到PROMOTED 標(biāo)志, 并將自身調(diào)整為現(xiàn)任主節(jié)點的從節(jié)點。

  • 可獲取一份Java架構(gòu)進階技術(shù)精品視頻。(高并發(fā)+Spring源碼+JVM原理解析+分布式架構(gòu)+微服務(wù)架構(gòu)+多線程并發(fā)原理+BATJ面試寶典)

在集群的生命周期中, 如果一個帶有 PROMOTED 標(biāo)識的主節(jié)點因為某些原因轉(zhuǎn)變成了從節(jié)點,那么該節(jié)點將丟失它所帶有的 PROMOTED 標(biāo)識。

“Redis緩存在系統(tǒng)中用來做什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!


當(dāng)前文章:Redis緩存在系統(tǒng)中用來做什么
URL標(biāo)題:http://weahome.cn/article/jsoohj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部