最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

第一部分:Redis篇

2023-08-24 17:18 作者:OopsSan  | 我要投稿

一、什么是緩存穿透? 怎么解決?

緩存穿透

緩存穿透是指緩存和數(shù)據(jù)庫都沒有數(shù)據(jù),導(dǎo)致所有請(qǐng)求都到了數(shù)據(jù)庫,如果從數(shù)據(jù)庫查不到數(shù)據(jù)且不寫入緩存,造成數(shù)據(jù)庫短時(shí)間內(nèi)承受大量的請(qǐng)求而導(dǎo)致宕機(jī)。

解決

1、布隆過濾器

將查詢的參數(shù)存儲(chǔ)到一個(gè)bitmap中,在查詢緩存前,如果 bitmap 存在則進(jìn)行底層緩存的數(shù)據(jù)查詢,如果不存在則進(jìn)行攔截,不再進(jìn)行緩存的數(shù)據(jù)查詢。

優(yōu)點(diǎn):內(nèi)存占用較少,沒有多余key;

缺點(diǎn):實(shí)現(xiàn)復(fù)雜,存在誤判,元素不能刪除

2、緩存空對(duì)值

如果數(shù)據(jù)庫查詢的為空,則依然把這個(gè)數(shù)據(jù)緩存并設(shè)置過期時(shí)間,當(dāng)多次訪問的時(shí)候可以直接返回結(jié)果,避免造成多次訪問數(shù)據(jù)庫,但要保證當(dāng)數(shù)據(jù)庫有數(shù)據(jù)時(shí)及時(shí)更新緩存。

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單;

缺點(diǎn):消耗內(nèi)存,可能會(huì)發(fā)生不一致的問題

布隆過濾器

bitmap(位圖):相當(dāng)于是一個(gè)以bit為單位的數(shù)組,數(shù)組中每個(gè)單元只能存儲(chǔ)二進(jìn)制數(shù)0或1

布隆過濾器:一種節(jié)省空間的概率數(shù)據(jù)結(jié)構(gòu),它實(shí)際上是由一個(gè)很長的二進(jìn)制向量(位圖)和一系列隨機(jī)映射函數(shù)組成,用于檢索一個(gè)元素是否在一個(gè)集合中。它的優(yōu)點(diǎn)是空間效率和查詢時(shí)間比一般算法要好很多,但也有一定概率的誤判性。它會(huì)告訴你某東西一定不存在或者可能存在。

實(shí)現(xiàn)原理:先初始化一個(gè)比較大數(shù)組,一開始都是0,當(dāng)一個(gè)key后經(jīng)過3次hash計(jì)算,模于數(shù)組長度得到數(shù)據(jù)的下標(biāo)然后把數(shù)組中原來的0改為1。這樣的話,三個(gè)數(shù)組的位置就能標(biāo)明一個(gè)key的存在。查找的過程也是一樣的。

二、什么是緩存擊穿 ? 怎么解決 ?

緩存擊穿

設(shè)置了過期時(shí)間且為熱點(diǎn)的key,在失效的瞬間,恰好對(duì)這個(gè)Key有大量的并發(fā)請(qǐng)求過來,擊穿了緩存,直接請(qǐng)求數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫崩潰。

解決

1、使用互斥鎖

請(qǐng)求查詢A,發(fā)現(xiàn)緩存中沒有。對(duì)A這個(gè)key加鎖,同時(shí)去數(shù)據(jù)庫查詢數(shù)據(jù),寫?緩存,再返回給?戶,這樣后?的請(qǐng)求就可以從緩存中拿到數(shù)據(jù)了。

2、設(shè)置邏輯過期

1、在設(shè)置key的時(shí)候,設(shè)置一個(gè)過期時(shí)間字段存入緩存中,不給當(dāng)前 key設(shè)置過期時(shí)間

2、當(dāng)查詢的時(shí)候,從redis取出數(shù)據(jù)后判斷時(shí)間是否過期

3、如果過期則開通另外一個(gè)線程進(jìn)行數(shù)據(jù)同步,當(dāng)前線程正常返回?cái)?shù)據(jù),這個(gè)數(shù)據(jù)不是最新。

三、什么是緩存雪崩 ? 怎么解決 ?

緩存雪崩

某一時(shí)刻發(fā)生大規(guī)模的緩存失效的情況,例如緩存服務(wù)宕機(jī)、大量key在同一時(shí)間過期,這樣的后果就是大量的請(qǐng)求直接到數(shù)據(jù)庫,數(shù)據(jù)庫無響應(yīng),最后可能導(dǎo)致整個(gè)系統(tǒng)的崩潰。

解決

1、利用Redis集群提高服務(wù)的可用性

通過集群來提升緩存的可用性,可以利用Redis本身的Redis Cluster或者第三方集群方案如Codis等。

2、給業(yè)務(wù)添加多級(jí)緩存

設(shè)置多級(jí)緩存,設(shè)置一級(jí)緩存本地(Guava,Caffeine)緩存,第一級(jí)緩存失效的基礎(chǔ)上再訪問二級(jí)緩存redis,每一級(jí)緩存的失效時(shí)間都不同。

3、過期時(shí)間

1、為了避免大量的緩存在同一時(shí)間過期,可以把不同的 key 過期時(shí)間隨機(jī)生成,避免過期時(shí)間太過集中。

2、熱點(diǎn)數(shù)據(jù)設(shè)置邏輯過期。

4、熔斷降級(jí)

熔斷

當(dāng)緩存服務(wù)器宕機(jī)或超時(shí)響應(yīng)時(shí),為了防止整個(gè)系統(tǒng)出現(xiàn)雪崩,可以使用hystrix 類似 的熔斷,暫時(shí)停止業(yè)務(wù)服務(wù)訪問數(shù)據(jù)庫, 或者其他被依賴的服務(wù),避免 MySQL 被打死。

降級(jí)

當(dāng)出現(xiàn)大量緩存失效,而且處在高并發(fā)高的情況下,在業(yè)務(wù)系統(tǒng)內(nèi)部暫時(shí)舍棄對(duì)一些非核心的接口和數(shù)據(jù)的請(qǐng)求,而直接返回一個(gè)提前準(zhǔn)備好的 fallback(退路)錯(cuò)誤處理信息。

四、常用的緩存讀寫策略詳解

Cache aside

?????? 先更新完數(shù)據(jù)庫,再刪除緩存。這種策略發(fā)生數(shù)據(jù)庫和緩存數(shù)據(jù)不一致的概率很低,因?yàn)橥ǔ?shù)據(jù)庫更新操作比內(nèi)存操作耗時(shí)多出幾個(gè)數(shù)量級(jí),讀請(qǐng)求的回寫緩存速度非???,通常會(huì)在寫請(qǐng)求更新數(shù)據(jù)庫之前完成。

讀請(qǐng)求

寫請(qǐng)求


先更新數(shù)據(jù)庫,再更新緩存

1.?????? 線程A:更新了數(shù)據(jù)庫

2.?????? 線程B:更新了數(shù)據(jù)庫

3.?????? 線程B:更新了緩存

4.?????? 線程A:更新了緩存

數(shù)據(jù)庫數(shù)據(jù)與緩存數(shù)據(jù)的不一致

先刪緩存,再更新數(shù)據(jù)庫

1.?????? 線程A:刪除緩存

2.?????? 線程B:查詢緩存,發(fā)現(xiàn)緩存中沒有想要的數(shù)據(jù)

3.?????? 線程B:查詢數(shù)據(jù)庫中的舊數(shù)據(jù)

4.?????? 線程B:將查詢到的舊數(shù)據(jù)寫入緩存

5.?????? 線程A:將新數(shù)據(jù)寫入數(shù)據(jù)庫

數(shù)據(jù)庫數(shù)據(jù)與緩存數(shù)據(jù)的不一致

Read/Write Through

Read/Write Through中服務(wù)端把 cache 視為主要數(shù)據(jù)存儲(chǔ),從中讀取數(shù)據(jù)并將數(shù)據(jù)寫入其中。

寫(Write Through)

l? 先查 cache,cache 中不存在,直接更新 db。

l? cache 中存在,則先更新 cache,然后 cache 服務(wù)自己更新 db(同步更新 cache 和 db)。


讀(Read Through)

l? 從 cache 中讀取數(shù)據(jù),讀取到就直接返回 。

讀取不到的話,先從 db 加載,寫入到 cache 后返回響應(yīng)。

Write Behind

?????? 與Read/Write Through Pattern 很相似,兩者都是由 cache 服務(wù)來負(fù)責(zé) cache 和 db 的讀寫。但是,兩個(gè)又有很大的不同:Read/Write是同步更新 cache 和 db,而 Write Behind 則是只更新緩存,不直接更新 db,而是改為異步批量的方式來更新 db。????

?????? 這種方式對(duì)數(shù)據(jù)一致性帶來了更大的挑戰(zhàn),比如 cache 數(shù)據(jù)可能還沒異步更新 db 的話,cache 服務(wù)可能就就掛掉了。

五、redis做為緩存,數(shù)據(jù)的持久化是怎么做的?

RDB

RDB全稱Redis Database Backup file,也被叫做Redis數(shù)據(jù)快照。簡(jiǎn)單來說就是把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中。當(dāng)Redis實(shí)例故障重啟后,從磁盤讀取快照文件,恢復(fù)數(shù)據(jù)。

觸發(fā)方式

①save和bgsave

bgsave開始時(shí)會(huì)fork主進(jìn)程得到子進(jìn)程,子進(jìn)程共享主進(jìn)程的內(nèi)存數(shù)據(jù)。完成fork后讀取內(nèi)存數(shù)據(jù)并寫入 RDB 文件。fork采用的是copy-on-write技術(shù):

當(dāng)主進(jìn)程執(zhí)行讀操作時(shí),訪問共享內(nèi)存;

當(dāng)主進(jìn)程執(zhí)行寫操作時(shí),則會(huì)拷貝一份數(shù)據(jù),執(zhí)行寫操作。


②自動(dòng)

Redis會(huì)將數(shù)據(jù)集的快照dump到dump.rdb文件中。 此外,我們也可以通過配置文件來修改Redis服務(wù)器dump快照的頻率。

#在900秒(15分鐘)之后,如果至少有1個(gè)key發(fā)生變化,則dump內(nèi)存快照。

save 900 1

#在300秒(5分鐘)之后,如果至少有10個(gè)key發(fā)生變化,則dump內(nèi)存快照。

save 300 10

#在60秒(1分鐘)之后,如果至少有10000個(gè)key發(fā)生變化,則dump內(nèi)存快照。

save 60 10000

AOF

AOF 持久化全稱 append only file,以日志形式記錄每個(gè)寫操作,將 redis 執(zhí)行過的所有寫操作指令記錄下來(讀操作不記錄)。

AOF默認(rèn)是關(guān)閉的,需要修改redis.conf配置文件來開啟AOF:

# 是否開啟AOF功能,默認(rèn)是no

appendonly yes

# AOF文件的名稱

appendfilename "appendonly.aof"

AOF的命令記錄的頻率也可以通過redis.conf文件來配:

# 表示每執(zhí)行一次寫命令,立即記錄到AOF文件

appendfsync always

# 寫命令執(zhí)行完先放入AOF緩沖區(qū),然后表示每隔1秒將緩沖區(qū)數(shù)據(jù)寫到AOF文件,是默認(rèn)方案

appendfsync everysec

# 寫命令執(zhí)行完先放入AOF緩沖區(qū),由操作系統(tǒng)決定何時(shí)將緩沖區(qū)內(nèi)容寫回磁盤

appendfsync no

可以通過bgrewriteaof 命令,可以將 AOF 文件進(jìn)行壓縮,也可以選擇自動(dòng)觸發(fā),在配置文件中配置

# AOF文件比上次文件 增長超過多少百分比則觸發(fā)重寫

auto-aof-rewrite-percentage 100

# AOF文件體積最小多大以上才觸發(fā)重寫

auto-aof-rewrite-min-size 64mb

RDB vs AOF

RDB和AOF各有自己的優(yōu)缺點(diǎn),如果對(duì)數(shù)據(jù)安全性要求較高,在實(shí)際開發(fā)中往往會(huì)結(jié)合兩者來使用。

六、Redis的數(shù)據(jù)過期刪除策略有哪些?

Redis對(duì)數(shù)據(jù)設(shè)置有效時(shí)間,數(shù)據(jù)過期以后,就需要將數(shù)據(jù)從內(nèi)存中刪除掉??梢园凑詹煌囊?guī)則進(jìn)行刪除,這種刪除規(guī)則就被稱之為數(shù)據(jù)的刪除策略(數(shù)據(jù)過期策略)。

Redis的過期刪除策略:惰性刪除 + 定期刪除兩種策略進(jìn)行配合使用。

惰性刪除

惰性刪除指的是當(dāng)我們查詢key的時(shí)候????才對(duì)key進(jìn)行檢測(cè),如果已經(jīng)達(dá)到過期時(shí)間,則刪除。

優(yōu)點(diǎn):對(duì)CPU友好,只會(huì)在使用該key時(shí)才會(huì)進(jìn)行過期檢查,對(duì)于很多用不到的key不用浪費(fèi)時(shí)間進(jìn)行過期檢查。

缺點(diǎn):對(duì)內(nèi)存不友好,如果一個(gè)key已經(jīng)過期,但是一直沒有使用,那么該key就會(huì)一直存在內(nèi)存中,內(nèi)存永遠(yuǎn)不會(huì)釋放。

定期刪除

指的是redis默認(rèn)是每隔 100ms (10hz)就隨機(jī)抽取一些設(shè)置了過期時(shí)間的 key,檢查其是否過期,如果過期就刪除。

優(yōu)點(diǎn):可以通過限制刪除操作執(zhí)行的時(shí)長和頻率來減少刪除操作對(duì) CPU 的影響。另外定期刪除,也能有效釋放過期鍵占用的內(nèi)存。

缺點(diǎn):難以確定刪除操作執(zhí)行的時(shí)長和頻率。

七、Redis的數(shù)據(jù)淘汰策略有哪些?

如果某個(gè)key過期后,定期刪除沒刪除成功,然后也沒再次去請(qǐng)求key,也就是說惰性刪除也沒生效。 這時(shí),如果大量過期的key堆積在內(nèi)存中,redis的內(nèi)存會(huì)越來越高,導(dǎo)致redis的內(nèi)存塊耗盡。那么就應(yīng)該采用內(nèi)存淘汰機(jī)制。

Redis支持8種不同策略來選擇要?jiǎng)h除的key:

u? no-eviction:不淘汰任何key,但是內(nèi)存滿時(shí)不允許寫入新數(shù)據(jù),默認(rèn)就是這種策略。

u? volatile-ttl:對(duì)設(shè)置了TTL的key,比較key的剩余TTL值,TTL越小越先被淘汰。

u? allkeys-random:對(duì)全體key,隨機(jī)進(jìn)行淘汰。

u? volatile-random:對(duì)設(shè)置了TTL的key,隨機(jī)進(jìn)行淘汰。

u? allkeys-lru:對(duì)全體key,基于LRU(Least Recently Used,最近最久未使用)算法進(jìn)行淘汰。

u? volatile-lru:對(duì)設(shè)置了TTL的key,基于LRU算法進(jìn)行淘汰。

u? allkeys-lfu:對(duì)全體key,基于LFU(Least Frequently Used ,最近最少使用)算法進(jìn)行淘汰。

u? volatile-lfu:對(duì)設(shè)置了TTL的key,基于LFU算法進(jìn)行淘汰。

使用建議:

  1. 優(yōu)先使用 allkeys-lru 策略。充分利用 LRU 算法的優(yōu)勢(shì),把最近最常訪問的數(shù)據(jù)留在緩存中。如果業(yè)務(wù)有明顯的冷熱數(shù)據(jù)區(qū)分,建議使用。

  2. 如果業(yè)務(wù)中數(shù)據(jù)訪問頻率差別不大,沒有明顯冷熱數(shù)據(jù)區(qū)分,建議使用 allkeys-random,隨機(jī)選擇淘汰。

  3. 如果業(yè)務(wù)中有置頂?shù)男枨?,可以使?volatile-lru 策略,同時(shí)置頂數(shù)據(jù)不設(shè)置過期時(shí)間,這些數(shù)據(jù)就一直不被刪除,會(huì)淘汰其他設(shè)置過期時(shí)間的數(shù)據(jù)。

  4. 如果業(yè)務(wù)中有短時(shí)高頻訪問的數(shù)據(jù),可以使用 allkeys-lfu 或 volatile-lfu 策略。

八、Redis分布式鎖如何實(shí)現(xiàn)?

redis分布式鎖

redis是一個(gè)單獨(dú)的非業(yè)務(wù)服務(wù),不會(huì)受到其他業(yè)務(wù)服務(wù)的限制,所有的業(yè)務(wù)服務(wù)都可以向redis發(fā)送寫入命令, 且只有一個(gè)業(yè)務(wù)服務(wù)可以寫入命令成功,那么這個(gè)寫入命令成功的服務(wù)即獲得了鎖,可以進(jìn)行后續(xù)對(duì)資源的操作,其他未寫入成功的服務(wù),則進(jìn)行其他處理。

# 添加鎖,NX是互斥、EX是設(shè)置超時(shí)時(shí)間(設(shè)置超時(shí)時(shí)間避免死鎖,用一條命令保證原子性)

SET lock value NX EX 10

# 釋放鎖,刪除即可

DEL key

redisson實(shí)現(xiàn)的分布式鎖

①執(zhí)行流程

在redisson中需要手動(dòng)加鎖,并且可以控制鎖的失效時(shí)間和等待時(shí)間,當(dāng)鎖住的一個(gè)業(yè)務(wù)還沒有執(zhí)行完成的時(shí)候,在redisson中引入了一個(gè)看門狗機(jī)制,就是說每隔一段時(shí)間就檢查當(dāng)前業(yè)務(wù)是否還持有鎖,如果持有就增加加鎖的持有時(shí)間,當(dāng)業(yè)務(wù)執(zhí)行完成之后釋放鎖就可以了。

在高并發(fā)下,一個(gè)業(yè)務(wù)有可能會(huì)執(zhí)行很快,先客戶1持有鎖的時(shí)候,客戶2來了以后并不會(huì)馬上拒絕,它會(huì)自旋不斷嘗試獲取鎖,如果客戶1釋放之后,客戶2就可以馬上持有鎖,性能也得到了提升。

②可重入

在內(nèi)部就是判斷是否是當(dāng)前線程持有的鎖,如果是當(dāng)前線程持有的鎖就會(huì)計(jì)數(shù),如果釋放鎖就會(huì)在計(jì)算上減1。在存儲(chǔ)數(shù)據(jù)的時(shí)候采用的hash結(jié)構(gòu),大key可以按照自己的業(yè)務(wù)進(jìn)行定制,其中field是當(dāng)前線程的唯一標(biāo)識(shí),小value是當(dāng)前線程重入的次數(shù)

?③主從一致性

redis集群中主從數(shù)據(jù)并不是強(qiáng)一致性。 當(dāng)主節(jié)點(diǎn)宕機(jī)后,主節(jié)點(diǎn)的數(shù)據(jù)還未來得及同步到從節(jié)點(diǎn),進(jìn)行主從切換后,新的主節(jié)點(diǎn)并沒有舊的主節(jié)點(diǎn)的全部數(shù)據(jù),這就會(huì)導(dǎo)致剛寫入到舊的主節(jié)點(diǎn)的鎖在新的主節(jié)點(diǎn)并沒有,其他服務(wù)來獲取鎖時(shí)還是會(huì)加鎖成功。此時(shí)則會(huì)有2個(gè)服務(wù)都可以操作公共資源,此時(shí)的分布式鎖是不安全的。

RedLock:要實(shí)現(xiàn)高可用的RedLock,不能只在一個(gè)redis實(shí)例上創(chuàng)建鎖,應(yīng)該是在多個(gè)redis實(shí)例(n / 2 + 1)上創(chuàng)建鎖。高可用的RedLock會(huì)導(dǎo)致性能降低,不太建議使用RedLock。

使用redis分布式鎖,是追求高性能,在CAP理論中,追求的是AP而不是CP。所以,如果追求高可用,建議使用 zookeeper分布式鎖。

九、Redis集群方案之主從同步

全量同步

一般用于初次同步場(chǎng)景,Redis早期支持的復(fù)制功能只有全量復(fù)制,它會(huì)把主節(jié)點(diǎn)全部數(shù)據(jù)一次性發(fā)送給從節(jié)點(diǎn),當(dāng)數(shù)據(jù)量較大時(shí),會(huì)對(duì)主從節(jié)點(diǎn)和網(wǎng)絡(luò)造成很大的開銷。

Replication Id:簡(jiǎn)稱replid,是數(shù)據(jù)集的標(biāo)記,id一致則說明是同一數(shù)據(jù)集。每一個(gè)master都有唯一的replid,slave則會(huì)繼承master節(jié)點(diǎn)的replid。

offset:偏移量,隨著記錄在repl_baklog中的數(shù)據(jù)增多而逐漸增大。slave完成同步時(shí)也會(huì)記錄當(dāng)前同步的offset。如果slave的offset小于master的offset,說明slave數(shù)據(jù)落后于master,需要更新。

因此slave做數(shù)據(jù)同步,必須向master聲明自己的replication id 和offset,master才可以判斷到底需要同步哪些數(shù)據(jù)。

增量同步

使用psync命令實(shí)現(xiàn)。當(dāng)從節(jié)點(diǎn)正在復(fù)制主節(jié)點(diǎn)時(shí),如果出現(xiàn)網(wǎng)絡(luò)閃斷或者命令丟失等異常情況時(shí),從節(jié)點(diǎn)會(huì)向主節(jié)點(diǎn)要求補(bǔ)發(fā)丟失的命令數(shù)據(jù),如果主節(jié)點(diǎn)的復(fù)制積壓緩沖區(qū)內(nèi)存在這部分?jǐn)?shù)據(jù)則直接發(fā)送給從節(jié)點(diǎn),這樣就可以保持主從節(jié)點(diǎn)復(fù)制的一致性。


十、Redis集群方案之哨兵模式

哨兵模式

Redis提供了哨兵(Sentinel)機(jī)制來實(shí)現(xiàn)主從集群的自動(dòng)故障恢復(fù)。哨兵的結(jié)構(gòu)和作用如下:

監(jiān)控:Sentinel 會(huì)不斷檢查您的master和slave是否按預(yù)期工作。

1、每隔1秒發(fā)送一次ping命令,如果超過一定時(shí)間沒有相向則認(rèn)為是主觀下線。

2、如果大多數(shù)sentinel都認(rèn)為實(shí)例主觀下線,則判定服務(wù)下線。

自動(dòng)故障恢復(fù):如果master故障,Sentinel會(huì)將一個(gè)slave提升為master。當(dāng)故障實(shí)例恢復(fù)后也以新的master為主。

1、首先選定一個(gè)slave作為新的master,執(zhí)行slaveof no one

2、然后讓所有節(jié)點(diǎn)都執(zhí)行slaveof 新master

3、修改故障節(jié)點(diǎn),執(zhí)行slaveof 新master

通知:Sentinel充當(dāng)Redis客戶端的服務(wù)發(fā)現(xiàn)來源,當(dāng)集群發(fā)生故障轉(zhuǎn)移時(shí),會(huì)將最新信息推送給Redis的客戶端。

腦裂

在一個(gè)高可用集群中,當(dāng)多個(gè)服務(wù)器在指定的時(shí)間內(nèi),由于網(wǎng)絡(luò)的原因無法互相檢測(cè)到對(duì)方,而各自形成一個(gè)新的小規(guī)模集群,并且各小集群當(dāng)中,會(huì)選舉新的master節(jié)點(diǎn),都對(duì)外提供獨(dú)立的服務(wù),由于網(wǎng)絡(luò)斷裂的原因,一個(gè)高可用集群中,實(shí)際上分裂為多個(gè)小的集群,這種情況就稱為腦裂。

十一、Redis集群方案之分片集群

主從和哨兵可以解決高可用、高并發(fā)讀的問題。但是依然有兩個(gè)問題沒有解決:

???????? 海量數(shù)據(jù)存儲(chǔ)問題

???????? 高并發(fā)寫的問題

使用分片集群可以解決上述問題,分片集群特征:

???????? 集群中有多個(gè)master,每個(gè)master保存不同數(shù)據(jù)

???????? 每個(gè)master都可以有多個(gè)slave節(jié)點(diǎn)

???????? master之間通過ping監(jiān)測(cè)彼此健康狀態(tài)

???????? 客戶端請(qǐng)求可以訪問集群任意節(jié)點(diǎn),最終都會(huì)被轉(zhuǎn)發(fā)到正確節(jié)點(diǎn)

散列插槽

Redis會(huì)把每一個(gè)master節(jié)點(diǎn)映射到0~16383共16384個(gè)插槽上。每個(gè)key的有效部分通過CRC16校驗(yàn)后對(duì)16384取模來決定放置哪個(gè)槽,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分hash 槽。

集群伸縮

Redis集群提供了靈活的節(jié)點(diǎn)擴(kuò)容和收縮方案,可以在不影響集群對(duì)外服務(wù)的情況下,為集群添加節(jié)點(diǎn)進(jìn)行擴(kuò)容也可以下線部分節(jié)點(diǎn)進(jìn)行縮容。

其實(shí),集群擴(kuò)容和縮容的關(guān)鍵點(diǎn),就在于槽和節(jié)點(diǎn)的對(duì)應(yīng)關(guān)系,擴(kuò)容和縮容就是將一部分槽和數(shù)據(jù)遷移給新節(jié)點(diǎn)。

故障轉(zhuǎn)移

Redis集群的故障轉(zhuǎn)移和哨兵的故障轉(zhuǎn)移類似,但是Redis集群中所有的節(jié)點(diǎn)都要承擔(dān)狀態(tài)維護(hù)的任務(wù)。

故障發(fā)現(xiàn)

Redis集群內(nèi)節(jié)點(diǎn)通過ping/pong消息實(shí)現(xiàn)節(jié)點(diǎn)通信,集群中每個(gè)節(jié)點(diǎn)都會(huì)定期向其他節(jié)點(diǎn)發(fā)送ping消息,接收節(jié)點(diǎn)回復(fù)pong 消息作為響應(yīng)。如果在cluster-node-timeout時(shí)間內(nèi)通信一直失敗,則發(fā)送節(jié)點(diǎn)會(huì)認(rèn)為接收節(jié)點(diǎn)存在故障,把接收節(jié)點(diǎn)標(biāo)記為主觀下線(pfail)狀態(tài)。

當(dāng)某個(gè)節(jié)點(diǎn)判斷另一個(gè)節(jié)點(diǎn)主觀下線后,相應(yīng)的節(jié)點(diǎn)狀態(tài)會(huì)跟隨消息在集群內(nèi)傳播。通過Gossip消息傳播,集群內(nèi)節(jié)點(diǎn)不斷收集到故障節(jié)點(diǎn)的下線報(bào)告。當(dāng)半數(shù)以上持有槽的主節(jié)點(diǎn)都標(biāo)記某個(gè)節(jié)點(diǎn)是主觀下線時(shí)。觸發(fā)客觀下線流程。

故障恢復(fù)

故障節(jié)點(diǎn)變?yōu)榭陀^下線后,如果下線節(jié)點(diǎn)是持有槽的主節(jié)點(diǎn)則需要在它的從節(jié)點(diǎn)中選出一個(gè)替換它,從而保證集群的高可用。

故障恢復(fù)流程

1. 資格檢查:每個(gè)從節(jié)點(diǎn)都要檢查最后與主節(jié)點(diǎn)斷線時(shí)間,判斷是否有資格替換故障的主節(jié)點(diǎn)。

2. 準(zhǔn)備選舉時(shí)間:當(dāng)從節(jié)點(diǎn)符合故障轉(zhuǎn)移資格后,更新觸發(fā)故障選舉的時(shí)間,只有到達(dá)該時(shí)間后才能執(zhí)行后續(xù)流程。

3. 發(fā)起選舉:當(dāng)從節(jié)點(diǎn)定時(shí)任務(wù)檢測(cè)到達(dá)故障選舉時(shí)間(failover_auth_time)到達(dá)后,發(fā)起選舉流程。

4. 選舉投票:持有槽的主節(jié)點(diǎn)處理故障選舉消息。投票過程其實(shí)是一個(gè)領(lǐng)導(dǎo)者選舉的過程,如集群內(nèi) 有N個(gè)持有槽的主節(jié)點(diǎn)代表有N張選票。由于在每個(gè)配置紀(jì)元內(nèi)持有槽的主節(jié)點(diǎn)只能投票給一個(gè)從節(jié)點(diǎn),因此只能有一個(gè)從節(jié)點(diǎn)獲得N/2+1的選票,保證能夠找出唯一的從節(jié)點(diǎn)。

5. 替換主節(jié)點(diǎn) 當(dāng)從節(jié)點(diǎn)收集到足夠的選票之后,觸發(fā)替換主節(jié)點(diǎn)操作。

十二、Redis是單線程的,但是為什么還那么快?

基于內(nèi)存

Redis是基于內(nèi)存的緩存數(shù)據(jù)庫,用于存儲(chǔ)使用頻繁的數(shù)據(jù),這樣減少訪問數(shù)據(jù)庫的次數(shù),提高運(yùn)行效率。

單線程避免線程切換

多線程在執(zhí)行過程中需要進(jìn)行CPU的上下文切換,需要完成一系列工作,這是非常消耗資源的操作,Redis又是基于內(nèi)存實(shí)現(xiàn)的,對(duì)于內(nèi)存來說,沒有上下文切換效率就是最高的。

IO多路復(fù)?

Redis采用網(wǎng)絡(luò)IO多路復(fù)用技術(shù),來保證在多連接的時(shí)候系統(tǒng)的高吞吐量。

C語?實(shí)現(xiàn)高效的數(shù)據(jù)結(jié)構(gòu)

Redis底層數(shù)據(jù)結(jié)構(gòu)一共有6種:簡(jiǎn)單動(dòng)態(tài)字符串,雙向鏈表,壓縮列表,哈希表,跳表和整數(shù)數(shù)組。它們和數(shù)據(jù)類型的對(duì)應(yīng)關(guān)系如下圖所示:

十三、能解釋一下I/O多路復(fù)用模型?

多路指的是多個(gè)socket網(wǎng)絡(luò)連接,復(fù)用指的是復(fù)用一個(gè)線程。多路復(fù)用主要有三種技術(shù):select,poll,epoll。epoll是最新的、也是目前最好的多路復(fù)用技術(shù)。采用多路I/O復(fù)用技術(shù),可以讓單個(gè)線程高效處理多個(gè)連接請(qǐng)求。

Redis內(nèi)部使用文件事件處理器(File Event Handler),這個(gè)文件事件處理器是單線程的,類似于Netty的Reactor反應(yīng)器模型。 它采用 IO 多路復(fù)用機(jī)制同時(shí)監(jiān)聽多個(gè) socket,將產(chǎn)生事件的 socket 壓入內(nèi)存隊(duì)列中,事件分派器根據(jù) socket 上的事件類型來選擇對(duì)應(yīng)的事件處理器進(jìn)行處理。 文件事件處理器的結(jié)構(gòu)包含4個(gè)部分:

l? 多個(gè)socket

l? IO多路復(fù)用程序

l? 文件事件分派器

l? 事件處理器(連接應(yīng)答處理器、命令請(qǐng)求處理器、命令回復(fù)處理器)

多個(gè)socket可能會(huì)并發(fā)產(chǎn)生不同的操作,每個(gè)操作對(duì)應(yīng)不同的文件事件,但是 IO 多路復(fù)用程序會(huì)監(jiān)聽多個(gè)socket,會(huì)將產(chǎn)生事件的 socket 放入隊(duì)列中排隊(duì),事件分派器每次從隊(duì)列中取出一個(gè) socket,根據(jù)socket的事件類型交給對(duì)應(yīng)的事件處理器進(jìn)行處理。

在Redis6.0之后,為了提升更好的性能,在命令回復(fù)處理器(請(qǐng)求后的數(shù)據(jù)通過網(wǎng)絡(luò)返回)使用了多線程來處理回復(fù)事件,在命令請(qǐng)求處理器中(網(wǎng)絡(luò)請(qǐng)求的接收和解析),將命令的轉(zhuǎn)換使用了多線程,增加命令轉(zhuǎn)換速度,在命令執(zhí)行的時(shí)候,依然是單線程。

第一部分:Redis篇的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
六盘水市| 如东县| 定西市| 华亭县| 永吉县| 高淳县| 从化市| 曲水县| 泾阳县| 东乌珠穆沁旗| 河北区| 玛曲县| 临汾市| 云南省| 普兰县| 吴堡县| 天全县| 宁夏| 渭南市| 石柱| 宁河县| 襄垣县| 库车县| 鞍山市| 集安市| 迁安市| 延川县| 逊克县| 镇巴县| 勐海县| 奉新县| 雷波县| 措勤县| 波密县| 阿城市| 平利县| 霍林郭勒市| 定州市| 公安县| 黄大仙区| 洪湖市|