Redis 總結(jié)

[TOC]

一锁右、Redis 基礎(chǔ)常問(wèn)

1.1疏旨、Redis 有哪些數(shù)據(jù)結(jié)構(gòu)

  • 基礎(chǔ):字符串String很魂、字典Hash、列表List檐涝、集合Set遏匆、有序集合SortedSet
  • 加分:HyperLogLog、Geo骤铃、Pub/Sub
  • 高級(jí):BloomFilter、RedisSearch坷剧、Redis-ML

1.2惰爬、Redis 大量 key 設(shè)置同一時(shí)間過(guò)期

電商首頁(yè)經(jīng)常會(huì)使用定時(shí)任務(wù)刷新緩存,可能大量的數(shù)據(jù)失效時(shí)間都十分集中惫企,如果失效時(shí)間一樣撕瞧,又剛好在失效的時(shí)間點(diǎn)大量用戶涌入,就有可能造成緩存雪崩狞尔,一般需要在時(shí)間上加一個(gè)隨機(jī)值丛版,使得過(guò)期時(shí)間分散一些。

1.3偏序、Redis分布式鎖

先拿 setnx 來(lái)爭(zhēng)搶鎖页畦,搶到之后,再用 expire 給鎖加一個(gè)過(guò)期時(shí)間防止鎖忘記了釋放研儒。

但 setnx 不能同時(shí)完成 expire 設(shè)置失效時(shí)長(zhǎng)豫缨,不能保證 setnx 和 expire 的原子性,可以使用 set 命令完成 setnx 和 expire 的操作端朵,并且這種操作是原子操作好芭。

set key value [EX seconds] [PX milliseconds] [NX|XX]
EX seconds:設(shè)置失效時(shí)長(zhǎng),單位秒
PX milliseconds:設(shè)置失效時(shí)長(zhǎng)冲呢,單位毫秒
NX:key不存在時(shí)設(shè)置value舍败,成功返回OK,失敗返回(nil)
XX:key存在時(shí)設(shè)置value,成功返回OK邻薯,失敗返回(nil)

案例:設(shè)置name=p7+裙戏,失效時(shí)長(zhǎng)100s,不存在時(shí)設(shè)置
set name p7+ ex 100 nx

1.4弛说、Redis keys 和 scan

Redis 是單線程的挽懦。

keys 指令會(huì)導(dǎo)致線程阻塞一段時(shí)間,線上服務(wù)會(huì)停頓木人,直到指令執(zhí)行完畢信柿,服務(wù)才能恢復(fù)。

這個(gè)時(shí)候可以使用 scan 指令醒第, scan 指令可以無(wú)阻塞的提取出指定模式的 key 列表渔嚷,但是會(huì)有一定的重復(fù)概率,在客戶端做一次去重就可以了稠曼,但是整體所花費(fèi)的時(shí)間會(huì)比直接用 keys 指令長(zhǎng)形病。

不過(guò),增量式迭代命令也不是沒(méi)有缺點(diǎn)的: 舉個(gè)例子霞幅, 使用 SMEMBERS 命令可以返回集合鍵當(dāng)前包含的所有元素漠吻, 但是對(duì)于 SCAN 這類增量式迭代命令來(lái)說(shuō), 因?yàn)樵趯?duì)鍵進(jìn)行增量式迭代的過(guò)程中司恳, 鍵可能會(huì)被修改途乃, 所以增量式迭代命令只能對(duì)被返回的元素提供有限的保證 。

1.5扔傅、Redis 當(dāng)做異步隊(duì)列

一般使用 list 結(jié)構(gòu)作為隊(duì)列耍共, rpush 生產(chǎn)消息, lpop 消費(fèi)消息猎塞。當(dāng) lpop 沒(méi)有消息的時(shí)候试读,要適當(dāng) sleep 一會(huì)再重試。

不用 sleep 的話:list 還有個(gè)指令叫 blpop 荠耽,在沒(méi)有消息的時(shí)候钩骇,它會(huì)阻塞住直到消息到來(lái)。

1.6铝量、Redis 發(fā)布訂閱

使用 pub/sub 主題訂閱者模式伊履,可以實(shí)現(xiàn) 1:N 的消息隊(duì)列。

# 訂閱頻道名為 redisChat
SUBSCRIBE redisChat

# 在同一個(gè)頻道 redisChat 發(fā)布消息
PUBLISH redisChat "Redis is a great caching technique"

pub/sub 有什么缺點(diǎn)款违?

在消費(fèi)者下線的情況下唐瀑,生產(chǎn)的消息會(huì)丟失,得使用專業(yè)的消息隊(duì)列插爹。

1.7哄辣、Redis 實(shí)現(xiàn)延時(shí)隊(duì)列

Redis 實(shí)現(xiàn)延時(shí)任務(wù)请梢,是通過(guò)其數(shù)據(jù)結(jié)構(gòu) ZSET(sortedset) 來(lái)實(shí)現(xiàn)的。ZSET 會(huì)儲(chǔ)存一個(gè) score 和一個(gè) value力穗,可以將 value按照 score 進(jìn)行排序毅弧,而 SET 是無(wú)序的。

延時(shí)任務(wù)的實(shí)現(xiàn)分為以下幾步來(lái)實(shí)現(xiàn):

  1. 將任務(wù)的執(zhí)行時(shí)間作為score当窗,要執(zhí)行的任務(wù)數(shù)據(jù)作為value够坐,存放在zset中;
  2. 用一個(gè)進(jìn)程定時(shí)查詢zset的score分?jǐn)?shù)最小的元素崖面,可以用ZRANGEBYSCORE key -inf +inf limit 0 1 withscores命令來(lái)實(shí)現(xiàn);
  3. 如果最小的分?jǐn)?shù)小于等于當(dāng)前時(shí)間戳元咙,就將該任務(wù)取出來(lái)執(zhí)行,否則休眠一段時(shí)間后再查詢

1.8巫员、Redis 怎么持久化庶香?主從數(shù)據(jù)怎么交互?

RDB 做鏡像全量持久化简识,AOF 做增量持久化赶掖。

因?yàn)镽DB 會(huì)耗費(fèi)較長(zhǎng)時(shí)間,不夠?qū)崟r(shí)七扰,在停機(jī)的時(shí)候會(huì)導(dǎo)致大量丟失數(shù)據(jù)奢赂,所以需要AOF 來(lái)配合使用。在 redis 實(shí)例重啟時(shí)颈走,會(huì)使用 RDB 持久化文件重新構(gòu)建內(nèi)存膳灶,再使用 AOF 重放近期的操作指令來(lái)實(shí)現(xiàn)完整恢復(fù)重啟之前的狀態(tài)。

突然機(jī)器掉電會(huì)怎樣疫鹊?

AOF 日志 sync 屬性的配置袖瞻,如果不要求性能鲫惶,在每條寫指令時(shí)都 sync 一下磁盤百揭,就不會(huì)丟失數(shù)據(jù)骗村。但是在高性能的要求下每次都 sync 是不現(xiàn)實(shí)的,一般都使用定時(shí) sync枣耀,比如1s1次,這個(gè)時(shí)候最多就會(huì)丟失1s的數(shù)據(jù)庭再。

RDB的原理

fork 是指 redis 通過(guò)創(chuàng)建子進(jìn)程來(lái)進(jìn)行 RDB 操作捞奕,cow 指的是 copy on write,子進(jìn)程創(chuàng)建后拄轻,父子進(jìn)程共享數(shù)據(jù)段颅围,父進(jìn)程繼續(xù)提供讀寫服務(wù),逐漸和子進(jìn)程分離開(kāi)來(lái)恨搓。

1.9院促、Redis 同步機(jī)制

第一次同步時(shí)筏养,主節(jié)點(diǎn)做一次 bgsave,并同時(shí)將后續(xù)修改操作記錄到內(nèi)存 buffer常拓,待完成后將 RDB 文件全量同步到復(fù)制節(jié)點(diǎn)渐溶,復(fù)制節(jié)點(diǎn)接受完成后將 RDB 鏡像加載到內(nèi)存。加載完成后弄抬,再通知主節(jié)點(diǎn)將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過(guò)程茎辐。

后續(xù)的增量數(shù)據(jù)通過(guò) AOF日志同步即可,有點(diǎn)類似數(shù)據(jù)庫(kù)的 binlog掂恕。

1.10拖陆、Redis 高可用

Redis Sentinal 著眼于高可用,在 master 宕機(jī)時(shí)會(huì)自動(dòng)將 slave 提升為master竹海,繼續(xù)提供服務(wù)慕蔚。

Redis Cluster 著眼于擴(kuò)展性,在單個(gè) redis 內(nèi)存不足時(shí)斋配,使用 Cluster 進(jìn)行分片存儲(chǔ)孔飒。

1.11、Redis 緩存雪崩

目前電商首頁(yè)以及熱點(diǎn)數(shù)據(jù)都會(huì)去做緩存 艰争,一般緩存都是定時(shí)任務(wù)去刷新坏瞄,或者是查不到之后去更新的,定時(shí)任務(wù)刷新就有一個(gè)問(wèn)題甩卓。緩存同一時(shí)間大面積失效鸠匀,那一瞬間 Redis 跟沒(méi)有一樣,那這個(gè)數(shù)量級(jí)別的請(qǐng)求直接打到數(shù)據(jù)庫(kù)造成數(shù)據(jù)庫(kù) down逾柿。這就是緩存雪崩缀棍。

舉個(gè)例子:如果所有首頁(yè)的 Key 失效時(shí)間都是12小時(shí),中午12點(diǎn)刷新的机错,零點(diǎn)有個(gè)秒殺活動(dòng)大量用戶涌入爬范,假設(shè)當(dāng)時(shí)每秒 6000 個(gè)請(qǐng)求,本來(lái)緩存在可以扛住每秒 5000 個(gè)請(qǐng)求弱匪,但是緩存當(dāng)時(shí)所有的 Key 都失效了青瀑。此時(shí) 1 秒 6000 個(gè)請(qǐng)求全部落數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)必然扛不住萧诫,它會(huì)報(bào)一下警斥难,真實(shí)情況可能 DBA 都沒(méi)反應(yīng)過(guò)來(lái)就直接掛了。此時(shí)帘饶,如果沒(méi)用什么特別的方案來(lái)處理這個(gè)故障哑诊,DBA 很著急,重啟數(shù)據(jù)庫(kù)及刻,但是數(shù)據(jù)庫(kù)立馬又被新的流量給打死了镀裤。

解決方法:

在批量往Redis存數(shù)據(jù)的時(shí)候穷当,把每個(gè) Key 的失效時(shí)間都加個(gè)隨機(jī)值就好了,這樣可以保證數(shù)據(jù)不會(huì)在同一時(shí)間大面積失效:

setRedis(Key淹禾,value馁菜,time + Math.random() * 10000);

1.12铃岔、Redis 緩存穿透

緩存穿透是指緩存和數(shù)據(jù)庫(kù)中都沒(méi)有的數(shù)據(jù)汪疮,而用戶不斷發(fā)起請(qǐng)求,一般數(shù)據(jù)庫(kù)的 id 都是1開(kāi)始自增上去的毁习,如發(fā)起為 id值為 -1 的數(shù)據(jù)或 id 為特別大不存在的數(shù)據(jù)智嚷。像這種如果不對(duì)參數(shù)做校驗(yàn),數(shù)據(jù)庫(kù) id 都是大于0的纺且,一直用小于 0 的參數(shù)去請(qǐng)求盏道,每次都能繞開(kāi) Redis 直接打到數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)也查不到载碌,每次都這樣猜嘱,并發(fā)高點(diǎn)就容易崩掉了。

解決方法:

在接口層增加校驗(yàn)嫁艇,比如用戶鑒權(quán)校驗(yàn)朗伶,參數(shù)做校驗(yàn),不合法的參數(shù)直接代碼 Return步咪,比如:id 做基礎(chǔ)校驗(yàn)论皆,id <=0 的直接攔截等。

Redis 還有一個(gè)高級(jí)用法布隆過(guò)濾器(Bloom Filter)猾漫,這個(gè)也能很好的防止緩存穿透的發(fā)生点晴,原理是利用高效的數(shù)據(jù)結(jié)構(gòu)和算法快速判斷出你這個(gè) Key 是否在數(shù)據(jù)庫(kù)中存在,不存在 return 就好了悯周,存在就去查了DB 刷新 KV 再 return粒督。

1.13、Redis 緩存擊穿

緩存擊穿跟緩存雪崩有點(diǎn)像队橙,但是又有一點(diǎn)不一樣坠陈,緩存雪崩是因?yàn)榇竺娣e的緩存失效萨惑,打崩了 DB捐康,而緩存擊穿不同的是緩存擊穿是指一個(gè) Key 非常熱點(diǎn),在不停的扛著大并發(fā)庸蔼,大并發(fā)集中對(duì)這一個(gè)點(diǎn)進(jìn)行訪問(wèn)解总,當(dāng)這個(gè) Key 在失效的瞬間,持續(xù)的大并發(fā)就穿破緩存姐仅,直接請(qǐng)求數(shù)據(jù)庫(kù)花枫,就像在一個(gè)完好無(wú)損的桶上鑿開(kāi)了一個(gè)洞刻盐。

解決方法:

設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過(guò)期。

或者加上互斥鎖就能搞定了劳翰。

二敦锌、Redis 架構(gòu)

2.1、Redis 中常用的 5 種數(shù)據(jù)結(jié)構(gòu)和應(yīng)用場(chǎng)景

數(shù)據(jù)結(jié)構(gòu):

  • String:緩存佳簸、計(jì)數(shù)器乙墙、分布式鎖等。
  • List:鏈表生均、隊(duì)列听想、微博關(guān)注人時(shí)間軸列表等。
  • Hash:用戶信息马胧、Hash 表等汉买。
  • Set:去重、贊佩脊、踩蛙粘、共同好友等。
  • Zset:訪問(wèn)量排行榜威彰、點(diǎn)擊量排行榜等组题。

應(yīng)用場(chǎng)景:

  • 緩存
  • 排行榜系統(tǒng):Redis提供了列表和有序集合數(shù)據(jù)結(jié)構(gòu),合理地使用這些數(shù)據(jù)結(jié)構(gòu)可以很方便地構(gòu)建各種排行
    榜系統(tǒng)
  • 計(jì)數(shù)器應(yīng)用:Redis天然支持計(jì)數(shù)功能而且計(jì)數(shù)的性能也非常好抱冷,可以說(shuō)是計(jì)數(shù)器系統(tǒng)的重要選擇
  • 社交網(wǎng)絡(luò):贊/踩崔列、粉絲、共同好友/喜好旺遮、推送赵讯、下拉刷新等,Redis提供的數(shù)據(jù)結(jié)構(gòu)可以相對(duì)比較容易地實(shí)現(xiàn)這些
  • 消息隊(duì)列系統(tǒng)

2.2耿眉、Redis 為什么這么快

  • 純內(nèi)存訪問(wèn)边翼,Redis 將所有數(shù)據(jù)放在內(nèi)存中,內(nèi)存的響應(yīng)時(shí)長(zhǎng)大約為100 納秒
  • 數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單鸣剪,對(duì)數(shù)據(jù)操作也簡(jiǎn)單组底,Redis 中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行優(yōu)化設(shè)計(jì)的
  • 非阻塞 I/O,Redis 使用 epoll 作為 I/O 多路復(fù)用技術(shù)的實(shí)現(xiàn)筐骇,再加上 Redis 自身的事件處理模型將 epoll 中的連接债鸡、讀寫、關(guān)閉都轉(zhuǎn)換為事件铛纬,不在網(wǎng)絡(luò) I/O 上浪費(fèi)過(guò)多的時(shí)間
  • 采用單線程厌均,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗 CPU告唆,不用去考慮各種鎖的問(wèn)題棺弊,不存在加鎖釋放鎖操作晶密,沒(méi)有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗

2.3、Redis 阻塞

Redis是典型的單線程架構(gòu)模她,所有的讀寫操作都是在一條主線程中完成的稻艰。當(dāng) Redis 用于高并發(fā)場(chǎng)景時(shí),這條線程就變成了它的生命線侈净。如果出現(xiàn)阻塞连锯,哪怕是很短時(shí)間,對(duì)于應(yīng)用來(lái)說(shuō)都是噩夢(mèng)用狱。

導(dǎo)致阻塞問(wèn)題的原因:

  • 內(nèi)在原因:不合理地使用API或數(shù)據(jù)結(jié)構(gòu)运怖、CPU飽和、持久化阻塞等
  • 外在原因:CPU競(jìng)爭(zhēng)夏伊、內(nèi)存交換摇展、網(wǎng)絡(luò)問(wèn)題等

2.3.1、內(nèi)在原因

1)API 或數(shù)據(jù)結(jié)構(gòu)使用不合理

通常Redis執(zhí)行命令速度非衬缬牵快咏连,但是,如果對(duì)一個(gè)包含上萬(wàn)個(gè)元素的hash結(jié)構(gòu)執(zhí)行hgetall操作鲁森,由于數(shù)據(jù)量比較大且命令算法復(fù)雜度是O(n)祟滴,這條命令執(zhí)行速度必然很慢,或者使用 keys 命令從所有 key 中匹配歌溉。

對(duì)于高并發(fā)的場(chǎng)景應(yīng)該盡量避免在大對(duì)象上執(zhí)行算法復(fù)雜度超過(guò)O(n)的命令垄懂,可以:

  • 調(diào)整大對(duì)象:縮減大對(duì)象數(shù)據(jù)或把大對(duì)象拆分為多個(gè)小對(duì)象,防止一次命令操作過(guò)多的數(shù)據(jù)
  • SCAN cursor [MATCH pattern] [COUNT count]

2)CPU 飽和

單線程的Redis處理命令時(shí)只能使用一個(gè)CPU痛垛。而CPU飽和是指Redis把單核CPU使用率跑到接近100%草慧。使用top命令很容易識(shí)別出對(duì)應(yīng)Redis進(jìn)程的CPU使用率。CPU飽和是非常危險(xiǎn)的匙头,將導(dǎo)致Redis無(wú)法處理更多的命令漫谷,嚴(yán)重影響吞吐量和應(yīng)用方的穩(wěn)定性。

3)持久化阻塞

對(duì)于開(kāi)啟了持久化功能的Redis節(jié)點(diǎn)蹂析,需要排查是否是持久化導(dǎo)致的阻塞舔示。

  • fork阻塞:fork操作發(fā)生在RDB和AOF重寫時(shí),Redis主線程調(diào)用fork操作產(chǎn)生共享內(nèi)存的子進(jìn)程电抚,由子進(jìn)程完成持久化文件重寫工作惕稻。如果fork操作本身耗時(shí)過(guò)長(zhǎng),必然會(huì)導(dǎo)致主線程的阻塞喻频。
  • AOF刷盤阻塞:當(dāng)我們開(kāi)啟AOF持久化功能時(shí)缩宜,文件刷盤的方式一般采用每秒一次肘迎,后臺(tái)線程每秒對(duì)AOF文件做fsync操作甥温。當(dāng)硬盤壓力過(guò)大時(shí)锻煌,fsync操作需要等待,直到寫入完成姻蚓。如果主線程發(fā)現(xiàn)距離上一次的fsync成功超過(guò)2秒宋梧,為了數(shù)據(jù)安全性它會(huì)阻塞直到后臺(tái)線程執(zhí)行fsync操作完成。這種阻塞行為主要是硬盤壓力引起狰挡。
  • HugePage寫操作阻塞:子進(jìn)程在執(zhí)行重寫期間利用Linux寫時(shí)復(fù)制技術(shù)降低內(nèi)存開(kāi)銷捂龄,因此只有寫操作時(shí)Redis才復(fù)制要修改的內(nèi)存頁(yè)。對(duì)于開(kāi)啟Transparent HugePages的操作系統(tǒng)加叁,每次寫命令引起的復(fù)制內(nèi)存頁(yè)單位由4K變?yōu)?MB倦沧,放大了512倍,會(huì)拖慢寫操作的執(zhí)行時(shí)間它匕,導(dǎo)致大量寫操作慢查詢展融。

2.3.2、外在原因

1)CPU競(jìng)爭(zhēng)

  • 進(jìn)程競(jìng)爭(zhēng):Redis是典型的CPU密集型應(yīng)用豫柬,不建議和其他多核CPU密集型服務(wù)部署在一起告希。當(dāng)其他進(jìn)程過(guò)度消耗CPU時(shí),將嚴(yán)重影響Redis吞吐量烧给⊙嗯迹可以通過(guò)top、sar等命令定位到CPU消耗的時(shí)間點(diǎn)和具體進(jìn)程础嫡,這個(gè)問(wèn)題比較容易發(fā)現(xiàn)指么,需要調(diào)整服務(wù)之間部署結(jié)構(gòu)。
  • 綁定CPU:部署Redis時(shí)為了充分利用多核CPU榴鼎,通常一臺(tái)機(jī)器部署多個(gè)實(shí)例涧尿。常見(jiàn)的一種優(yōu)化是把Redis進(jìn)程綁定到CPU上,用于降低CPU頻繁上下文切換的開(kāi)銷檬贰。這個(gè)優(yōu)化技巧正常情況下沒(méi)有問(wèn)題姑廉,但是存在例外情況,當(dāng)Redis父進(jìn)程創(chuàng)建子進(jìn)程進(jìn)行RDB/AOF重寫時(shí)翁涤,如果做了CPU綁定桥言,會(huì)與父進(jìn)程共享使用一個(gè)CPU。子進(jìn)程重寫時(shí)對(duì)單核CPU使用率通常在90%以上葵礼,父進(jìn)程與子進(jìn)程將產(chǎn)生激烈CPU競(jìng)爭(zhēng)号阿,極大影響Redis穩(wěn)定性。因此對(duì)于開(kāi)啟了持久化或參與復(fù)制的主節(jié)點(diǎn)不建議綁定CPU鸳粉。

2)內(nèi)存交換

內(nèi)存交換(swap)對(duì)于Redis來(lái)說(shuō)是非常致命的扔涧,Redis保證高性能的一個(gè)重要前提是所有的數(shù)據(jù)在內(nèi)存中。如果操作系統(tǒng)把Redis使用的部分內(nèi)存換出到硬盤,由于內(nèi)存與硬盤讀寫速度差幾個(gè)數(shù)量級(jí)枯夜,會(huì)導(dǎo)致發(fā)生交換后的Redis性能急劇下降弯汰。

預(yù)防內(nèi)存交換:

  • 保證機(jī)器充足的可用內(nèi)存。
  • 確保所有Redis實(shí)例設(shè)置最大可用內(nèi)存(maxmemory)湖雹,防止極端情況下Redis內(nèi)存不可控的增長(zhǎng)咏闪。
  • 降低系統(tǒng)使用swap優(yōu)先級(jí)。

3)網(wǎng)絡(luò)問(wèn)題

連接拒絕:

  • 網(wǎng)絡(luò)閃斷(網(wǎng)絡(luò)割接或者帶寬耗盡)
  • Redis連接拒絕(超過(guò)客戶端最大連接數(shù))
  • 連接溢出(進(jìn)程限制或backlog隊(duì)列溢出)

網(wǎng)絡(luò)延遲:

網(wǎng)絡(luò)延遲取決于客戶端到Redis服務(wù)器之間的網(wǎng)絡(luò)環(huán)境摔吏。主要包括它們之間的物理拓?fù)浜蛶捳加们闆r鸽嫂。常見(jiàn)的物理拓?fù)浒淳W(wǎng)絡(luò)延遲由快到慢可分為:同物理機(jī)>同機(jī)架>跨機(jī)架>同機(jī)房>同城機(jī)房>異地機(jī)房。但它們?nèi)轂?zāi)性正好相反征讲,同物理機(jī)容災(zāi)性最低而異地機(jī)房容災(zāi)性最高据某。

網(wǎng)卡軟中斷:

網(wǎng)卡軟中斷是指由于單個(gè)網(wǎng)卡隊(duì)列只能使用一個(gè)CPU,高并發(fā)下網(wǎng)卡數(shù)據(jù)交互都集中在同一個(gè)CPU诗箍,導(dǎo)致無(wú)法充分利用多核CPU的情況哗脖。網(wǎng)卡軟中斷瓶頸一般出現(xiàn)在網(wǎng)絡(luò)高流量吞吐的場(chǎng)景。

2.4扳还、redis 和 memcached 有啥區(qū)別

Memcache

  • Memcache可以利用多核優(yōu)勢(shì)才避,單實(shí)例吞吐量極高,可以達(dá)到幾十萬(wàn)QPS,適用于最大程度扛量
  • 只支持簡(jiǎn)單的key/value數(shù)據(jù)結(jié)構(gòu)氨距,不像Redis可以支持豐富的數(shù)據(jù)類型桑逝。
  • 無(wú)法進(jìn)行持久化,數(shù)據(jù)不能備份俏让,只能用于緩存使用楞遏,且重啟后數(shù)據(jù)全部丟失

Redis

  • 支持多種數(shù)據(jù)結(jié)構(gòu),如string,list,dict,set,zset,hyperloglog
  • 單線程請(qǐng)求首昔,所有命令串行執(zhí)行寡喝,并發(fā)情況下不需要考慮數(shù)據(jù)一致性問(wèn)題
  • 支持持久化操作,可以進(jìn)行aof及rdb數(shù)據(jù)持久化到磁盤勒奇,從而進(jìn)行數(shù)據(jù)備份或數(shù)據(jù)恢復(fù)等操作预鬓,較好的防止數(shù)據(jù)丟失的手段
  • 支持通過(guò)Replication進(jìn)行數(shù)據(jù)復(fù)制,通過(guò)master-slave機(jī)制赊颠,可以實(shí)時(shí)進(jìn)行數(shù)據(jù)的同步復(fù)制格二,支持多級(jí)復(fù)制和增量復(fù)制

三、Redis 持久化

3.1竣蹦、RDB

RDB是一種快照存儲(chǔ)持久化方式顶猜,具體就是將Redis某一時(shí)刻的內(nèi)存數(shù)據(jù)保存到硬盤的文件當(dāng)中,默認(rèn)保存的文件名為dump.rdb痘括,而在Redis服務(wù)器啟動(dòng)時(shí)长窄,會(huì)重新加載dump.rdb文件的數(shù)據(jù)到內(nèi)存當(dāng)中恢復(fù)數(shù)據(jù)滔吠。

3.1.1、開(kāi)啟RDB持久化方式

開(kāi)啟RDB持久化方式很簡(jiǎn)單挠日,客戶端可以通過(guò)向Redis服務(wù)器發(fā)送save或bgsave命令讓服務(wù)器生成rdb文件疮绷,或者通過(guò)服務(wù)器配置文件指定觸發(fā)RDB條件。

1)save:

save命令是一個(gè)同步操作肆资。當(dāng)客戶端向服務(wù)器發(fā)送save命令請(qǐng)求進(jìn)行持久化時(shí)矗愧,服務(wù)器會(huì)阻塞save命令之后的其他客戶端的請(qǐng)求灶芝,直到數(shù)據(jù)同步完成郑原。

如果數(shù)據(jù)量太大,同步數(shù)據(jù)會(huì)執(zhí)行很久夜涕,而這期間Redis服務(wù)器也無(wú)法接收其他請(qǐng)求犯犁,所以,最好不要在生產(chǎn)環(huán)境使用save命令女器。

2)bgsave:

與save命令不同酸役,bgsave命令是一個(gè)異步操作。當(dāng)客戶端發(fā)服務(wù)發(fā)出bgsave命令時(shí)驾胆,Redis服務(wù)器主進(jìn)程會(huì)forks一個(gè)子進(jìn)程來(lái)數(shù)據(jù)同步問(wèn)題涣澡,在將數(shù)據(jù)保存到rdb文件之后,子進(jìn)程會(huì)退出丧诺。

與save命令相比入桂,Redis服務(wù)器在處理bgsave采用子線程進(jìn)行IO寫入,而主進(jìn)程仍然可以接收其他請(qǐng)求驳阎,但forks子進(jìn)程是同步的抗愁,所以forks子進(jìn)程時(shí),一樣不能接收其他請(qǐng)求呵晚,這意味著蜘腌,如果forks一個(gè)子進(jìn)程花費(fèi)的時(shí)間太久(一般是很快的),bgsave命令仍然有阻塞其他客戶的請(qǐng)求的情況發(fā)生饵隙。

3)服務(wù)器配置自動(dòng)觸發(fā):

除了通過(guò)客戶端發(fā)送命令外撮珠,還有一種方式,就是在Redis配置文件中的save指定到達(dá)觸發(fā)RDB持久化的條件金矛,比如【多少秒內(nèi)至少達(dá)到多少寫操作】就開(kāi)啟RDB數(shù)據(jù)同步劫瞳。

例如可以在配置文件redis.conf指定如下的選項(xiàng):

# 900s內(nèi)至少達(dá)到一條寫命令
save 900 1
# 300s內(nèi)至少達(dá)到10條寫命令
save 300 10
# 60s內(nèi)至少達(dá)到10000條寫命令
save 60 10000

之后在啟動(dòng)服務(wù)器時(shí)加載配置文件。

# 啟動(dòng)服務(wù)器加載配置文件
redis-server redis.conf

這種通過(guò)服務(wù)器配置文件觸發(fā)RDB的方式绷柒,與bgsave命令類似志于,達(dá)到觸發(fā)條件時(shí),會(huì)forks一個(gè)子進(jìn)程進(jìn)行數(shù)據(jù)同步废睦。

3.1.2伺绽、RDB的優(yōu)缺點(diǎn)

RDB的幾個(gè)優(yōu)點(diǎn)

  • 與AOF方式相比,通過(guò)rdb文件恢復(fù)數(shù)據(jù)比較快
  • rdb文件非常緊湊,適合于數(shù)據(jù)備份
  • 通過(guò)RDB進(jìn)行數(shù)據(jù)備奈应,由于使用子進(jìn)程生成澜掩,所以對(duì)Redis服務(wù)器性能影響較小

RDB的幾個(gè)缺點(diǎn)

  • 如果服務(wù)器宕機(jī)的話,采用RDB的方式會(huì)造成某個(gè)時(shí)段內(nèi)數(shù)據(jù)的丟失杖挣,比如我們?cè)O(shè)置10分鐘同步一次或5分鐘達(dá)到1000次寫入就同步一次肩榕,那么如果還沒(méi)達(dá)到觸發(fā)條件服務(wù)器就死機(jī)了,那么這個(gè)時(shí)間段的數(shù)據(jù)會(huì)丟失
  • 使用save命令會(huì)造成服務(wù)器阻塞惩妇,直接數(shù)據(jù)同步完成才能接收后續(xù)請(qǐng)求
  • 使用bgsave命令在forks子進(jìn)程時(shí)株汉,如果數(shù)據(jù)量太大,forks的過(guò)程也會(huì)發(fā)生阻塞歌殃,另外乔妈,forks子進(jìn)程會(huì)耗費(fèi)內(nèi)存

3.2、AOF(Append-only file)

與RDB存儲(chǔ)某個(gè)時(shí)刻的快照不同氓皱,AOF持久化方式會(huì)記錄客戶端對(duì)服務(wù)器的每一次寫操作命令路召,并將這些寫操作以Redis協(xié)議追加保存到以后綴為aof文件末尾,在Redis服務(wù)器重啟時(shí)波材,會(huì)加載并運(yùn)行aof文件的命令股淡,以達(dá)到恢復(fù)數(shù)據(jù)的目的。

3.2.1廷区、開(kāi)啟AOF持久化方式

Redis默認(rèn)不開(kāi)啟AOF持久化方式唯灵,可以在配置文件中開(kāi)啟并進(jìn)行更加詳細(xì)的配置,如下面的redis.conf文件:

# 開(kāi)啟aof機(jī)制
appendonly yes

# aof文件名
appendfilename "appendonly.aof"

# 寫入策略,always表示每個(gè)寫操作都保存到aof文件中,也可以是everysec或no
appendfsync always

# 默認(rèn)不重寫aof文件
no-appendfsync-on-rewrite no

# 保存目錄
dir ~/redis/

三種寫入策略

在上面的配置文件中躲因,可以通過(guò)appendfsync選項(xiàng)指定寫入策略早敬,有三個(gè)選項(xiàng)

appendfsync always
# appendfsync everysec
# appendfsync no
  • always:客戶端的每一個(gè)寫操作都保存到aof文件當(dāng),這種策略很安全大脉,但是每個(gè)寫請(qǐng)注都有IO操作搞监,所以也很慢
  • everysec:appendfsync的默認(rèn)寫入策略,每秒寫入一次aof文件镰矿,因此琐驴,最多可能會(huì)丟失1s的數(shù)據(jù)
  • no:Redis服務(wù)器不負(fù)責(zé)寫入aof,而是交由操作系統(tǒng)來(lái)處理什么時(shí)候?qū)懭隺of文件秤标,更快绝淡,但也是最不安全的選擇,不推薦使用

3.2.2苍姜、AOF文件重寫

AOF將客戶端的每一個(gè)寫操作都追加到aof文件末尾牢酵,比如對(duì)一個(gè)key多次執(zhí)行incr命令,這時(shí)候衙猪,aof保存每一次命令到aof文件中馍乙,aof文件會(huì)變得非常大布近。

incr num 1
incr num 2
incr num 3
incr num 4
incr num 5
incr num 6
...
incr num 100000

aof文件太大,加載aof文件恢復(fù)數(shù)據(jù)時(shí)丝格,就會(huì)非常慢撑瞧,為了解決這個(gè)問(wèn)題,Redis支持aof文件重寫显蝌,通過(guò)重寫aof预伺,可以生成一個(gè)恢復(fù)當(dāng)前數(shù)據(jù)的最少命令集,比如上面的例子中那么多條命令曼尊,可以重寫為:

set num 100000

aof文件是一個(gè)二進(jìn)制文件酬诀,并不是像上面的例子一樣,直接保存每個(gè)命令涩禀,而使用Redis自己的格式料滥,上面只是方便演示然眼。

3.2.3艾船、兩種重寫方式

通過(guò)在redis.conf配置文件中的選項(xiàng)no-appendfsync-on-rewrite可以設(shè)置是否開(kāi)啟重寫,這種方式會(huì)在每次fsync時(shí)都重寫高每,影響服務(wù)器性以屿岂,因此默認(rèn)值為no,不推薦使用鲸匿。

# 默認(rèn)不重寫aof文件
no-appendfsync-on-rewrite no

客戶端向服務(wù)器發(fā)送bgrewriteaof命令爷怀,也可以讓服務(wù)器進(jìn)行AOF重寫。

# 讓服務(wù)器異步重寫追加aof文件命令
> bgrewriteaof

AOF重寫方式也是異步操作带欢,即如果要寫入aof文件运授,則Redis主進(jìn)程會(huì)forks一個(gè)子進(jìn)程來(lái)處理,如下所示:

重寫aof文件的好處

  • 壓縮aof文件乔煞,減少磁盤占用量吁朦。
  • 將aof的命令壓縮為最小命令集,加快了數(shù)據(jù)恢復(fù)的速度渡贾。

3.2.4逗宜、AOF文件損壞

在寫入aof日志文件時(shí),如果Redis服務(wù)器宕機(jī)空骚,則aof日志文件文件會(huì)出格式錯(cuò)誤纺讲,在重啟Redis服務(wù)器時(shí),Redis服務(wù)器會(huì)拒絕載入這個(gè)aof文件囤屹,可以通過(guò)以下步驟修復(fù)aof并恢復(fù)數(shù)據(jù)熬甚。

1、備份現(xiàn)在aof文件肋坚,以防萬(wàn)一乡括。

2复局、使用redis-check-aof命令修復(fù)aof文件,該命令格式如下:

# 修復(fù)aof日志文件
$ redis-check-aof -fix file.aof

3粟判、重啟Redis服務(wù)器亿昏,加載已經(jīng)修復(fù)的aof文件,恢復(fù)數(shù)據(jù)档礁。

3.2.5角钩、AOF的優(yōu)缺點(diǎn)

AOF的優(yōu)點(diǎn):

  • AOF只是追加日志文件,因此對(duì)服務(wù)器性能影響較小呻澜,速度比RDB要快递礼,消耗的內(nèi)存較少。

AOF的缺點(diǎn):

  • AOF方式生成的日志文件太大羹幸,即使通過(guò)AFO重寫脊髓,文件體積仍然很大。
  • 恢復(fù)數(shù)據(jù)的速度比RDB慢栅受。

四将硝、Redis Key 過(guò)期策略和內(nèi)存淘汰機(jī)制

4.1、Redis設(shè)置過(guò)期時(shí)間

  • expire key time(以秒為單位)–這是最常用的方式
  • setex(String key, int seconds, String value)–字符串獨(dú)有的方式

注:除了字符串自己獨(dú)有設(shè)置過(guò)期時(shí)間的方法外屏镊,其他方法都需要依靠expire方法來(lái)設(shè)置時(shí)間依疼,如果沒(méi)有設(shè)置時(shí)間,那緩存就是永不過(guò)期而芥,如果設(shè)置了過(guò)期時(shí)間律罢,之后又想讓緩存永不過(guò)期,使用persist key棍丐。

4.2仍劈、過(guò)期策略

定時(shí)刪除

  • 含義:在設(shè)置key的過(guò)期時(shí)間的同時(shí)绍填,為該key創(chuàng)建一個(gè)定時(shí)器脆淹,讓定時(shí)器在key的過(guò)期時(shí)間來(lái)臨時(shí)规脸,對(duì)key進(jìn)行刪除
  • 優(yōu)點(diǎn):保證內(nèi)存被盡快釋放
  • 缺點(diǎn):
    • 若過(guò)期key很多,刪除這些key會(huì)占用很多的CPU時(shí)間趋翻,在CPU時(shí)間緊張的情況下睛琳,CPU不能把所有的時(shí)間用來(lái)做要緊的事兒,還需要去花時(shí)間刪除這些key
    • 定時(shí)器的創(chuàng)建耗時(shí)踏烙,若為每一個(gè)設(shè)置過(guò)期時(shí)間的key創(chuàng)建一個(gè)定時(shí)器(將會(huì)有大量的定時(shí)器產(chǎn)生)师骗,性能影響嚴(yán)重
    • 沒(méi)人用

惰性刪除

  • 含義:key過(guò)期的時(shí)候不刪除,每次從數(shù)據(jù)庫(kù)獲取key的時(shí)候去檢查是否過(guò)期讨惩,若過(guò)期辟癌,則刪除,返回null荐捻。
  • 優(yōu)點(diǎn):刪除操作只發(fā)生在從數(shù)據(jù)庫(kù)取出key的時(shí)候發(fā)生黍少,而且只刪除當(dāng)前key寡夹,所以對(duì)CPU時(shí)間的占用是比較少的,而且此時(shí)的刪除是已經(jīng)到了非做不可的地步(如果此時(shí)還不刪除的話厂置,我們就會(huì)獲取到了已經(jīng)過(guò)期的key了)
  • 缺點(diǎn):若大量的key在超出超時(shí)時(shí)間后菩掏,很久一段時(shí)間內(nèi),都沒(méi)有被獲取過(guò)昵济,那么可能發(fā)生內(nèi)存泄露(無(wú)用的垃圾占用了大量的內(nèi)存)

定期刪除

  • 含義:每隔一段時(shí)間執(zhí)行一次刪除(在redis.conf配置文件設(shè)置hz智绸,1s刷新的頻率)過(guò)期key操作
  • 優(yōu)點(diǎn):
    • 通過(guò)限制刪除操作的時(shí)長(zhǎng)和頻率,來(lái)減少刪除操作對(duì)CPU時(shí)間的占用--處理"定時(shí)刪除"的缺點(diǎn)
    • 定期刪除過(guò)期key--處理"惰性刪除"的缺點(diǎn)
  • 缺點(diǎn)
    • 在內(nèi)存友好方面访忿,不如"定時(shí)刪除"
    • 在CPU時(shí)間友好方面瞧栗,不如"惰性刪除"
  • 難點(diǎn)
    • 合理設(shè)置刪除操作的執(zhí)行時(shí)長(zhǎng)(每次刪除執(zhí)行多長(zhǎng)時(shí)間)和執(zhí)行頻率(每隔多長(zhǎng)時(shí)間做一次刪除)(這個(gè)要根據(jù)服務(wù)器運(yùn)行情況來(lái)定了)

看完上面三種策略后可以得出以下結(jié)論:

  • 定時(shí)刪除和定期刪除為主動(dòng)刪除:Redis會(huì)定期主動(dòng)淘汰一批已過(guò)去的key
  • 惰性刪除為被動(dòng)刪除:用到的時(shí)候才會(huì)去檢驗(yàn)key是不是已過(guò)期,過(guò)期就刪除
  • 惰性刪除為redis服務(wù)器內(nèi)置策略

定期刪除可以通過(guò):

  • 第一海铆、配置redis.conf 的hz選項(xiàng)迹恐,默認(rèn)為10 (即1秒執(zhí)行10次,100ms一次卧斟,值越大說(shuō)明刷新頻率越快殴边,最Redis性能損耗也越大)
  • 第二、配置redis.conf的maxmemory最大值唆涝,當(dāng)已用內(nèi)存超過(guò)maxmemory限定時(shí)找都,就會(huì)觸發(fā)主動(dòng)清理策略

4.3唇辨、Redis 采用的過(guò)期策略

惰性刪除+定期刪除:

  • 惰性刪除流程
    • 在進(jìn)行g(shù)et或setnx等操作時(shí)廊酣,先檢查key是否過(guò)期
    • 若過(guò)期,刪除key赏枚,然后執(zhí)行相應(yīng)操作
    • 若沒(méi)過(guò)期亡驰,直接執(zhí)行相應(yīng)操作
  • 定期刪除流程(簡(jiǎn)單而言,對(duì)指定個(gè)數(shù)個(gè)庫(kù)的每一個(gè)庫(kù)隨機(jī)刪除小于等于指定個(gè)數(shù)個(gè)過(guò)期key)
    • 遍歷每個(gè)數(shù)據(jù)庫(kù)(就是redis.conf中配置的"database"數(shù)量饿幅,默認(rèn)為16)
      • 檢查當(dāng)前庫(kù)中的指定個(gè)數(shù)個(gè)key(默認(rèn)是每個(gè)庫(kù)檢查20個(gè)key凡辱,注意相當(dāng)于該循環(huán)執(zhí)行20次,循環(huán)體時(shí)下邊的描述)
        • 如果當(dāng)前庫(kù)中沒(méi)有一個(gè)key設(shè)置了過(guò)期時(shí)間栗恩,直接執(zhí)行下一個(gè)庫(kù)的遍歷
        • 隨機(jī)獲取一個(gè)設(shè)置了過(guò)期時(shí)間的key透乾,檢查該key是否過(guò)期,如果過(guò)期磕秤,刪除key
        • 判斷定期刪除操作是否已經(jīng)達(dá)到指定時(shí)長(zhǎng)乳乌,若已經(jīng)達(dá)到,直接退出定期刪除市咆。

4.4汉操、RDB 對(duì)過(guò)期 key 的處理

過(guò)期 key 對(duì) RDB 沒(méi)有任何影響

  • 從內(nèi)存數(shù)據(jù)庫(kù)持久化數(shù)據(jù)到 RDB 文件
    • 持久化 key 之前,會(huì)檢查是否過(guò)期蒙兰,過(guò)期的 key 不進(jìn)入 RDB 文件
  • 從 RDB 文件恢復(fù)數(shù)據(jù)到內(nèi)存數(shù)據(jù)庫(kù)
    • 數(shù)據(jù)載入數(shù)據(jù)庫(kù)之前磷瘤,會(huì)對(duì) key 先進(jìn)行過(guò)期檢查芒篷,如果過(guò)期,不導(dǎo)入數(shù)據(jù)庫(kù)(主庫(kù)情況)

4.5采缚、AOF 對(duì)過(guò)期 key 的處理

過(guò)期 key 對(duì) AOF 沒(méi)有任何影響

  • 從內(nèi)存數(shù)據(jù)庫(kù)持久化數(shù)據(jù)到 AOF 文件:
    • 當(dāng) key 過(guò)期后针炉,還沒(méi)有被刪除,此時(shí)進(jìn)行執(zhí)行持久化操作(該 key 是不會(huì)進(jìn)入 aof 文件的扳抽,因?yàn)闆](méi)有發(fā)生修改命令)
    • 當(dāng) key 過(guò)期后糊识,在發(fā)生刪除操作時(shí),程序會(huì)向 aof 文件追加一條 del 命令(在將來(lái)的以 aof 文件恢復(fù)數(shù)據(jù)的時(shí)候該過(guò)期的鍵就會(huì)被刪掉)
  • AOF 重寫
    • 重寫時(shí)摔蓝,會(huì)先判斷 key 是否過(guò)期赂苗,已過(guò)期的 key 不會(huì)重寫到 aof 文件

4.6、Redis 的內(nèi)存淘汰機(jī)制

Redis 定義了6 種 redis 內(nèi)存淘汰策略方案:

  • noeviction(默認(rèn)策略):對(duì)于寫請(qǐng)求不再提供服務(wù)贮尉,直接返回錯(cuò)誤(DEL 請(qǐng)求和部分特殊請(qǐng)求除外)
  • allkeys-lru:從所有 key 中使用 LRU 算法進(jìn)行淘汰
  • volatile-lru:從設(shè)置了過(guò)期時(shí)間的 key 中使用 LRU 算法進(jìn)行淘汰
  • allkeys-random:從所有 key 中隨機(jī)淘汰數(shù)據(jù)
  • volatile-random:從設(shè)置了過(guò)期時(shí)間的 key 中隨機(jī)淘汰
  • volatile-ttl:在設(shè)置了過(guò)期時(shí)間的 key 中拌滋,根據(jù) key 的過(guò)期時(shí)間進(jìn)行淘汰,越早過(guò)期的越優(yōu)先被淘汰

五猜谚、Redis 高可用

5.1败砂、Redis 主從復(fù)制

Redis 主從復(fù)制 可將 主節(jié)點(diǎn) 數(shù)據(jù)同步給 從節(jié)點(diǎn),從節(jié)點(diǎn)此時(shí)有兩個(gè)作用:

  1. 一旦 主節(jié)點(diǎn)宕機(jī)魏铅,從節(jié)點(diǎn) 作為 主節(jié)點(diǎn)備份 可以隨時(shí)頂上來(lái)昌犹。
  2. 擴(kuò)展 主節(jié)點(diǎn)讀能力,分擔(dān)主節(jié)點(diǎn)讀壓力览芳。

5.1.1斜姥、主從復(fù)制過(guò)程

主從復(fù)制過(guò)程大體可以分為3個(gè)階段:連接建立階段(即準(zhǔn)備階段)、數(shù)據(jù)同步階段沧竟、命令傳播階段铸敏。

5.1.1.1、連接建立階段

該階段的主要作用是在主從節(jié)點(diǎn)之間建立連接悟泵,為數(shù)據(jù)同步做好準(zhǔn)備杈笔。

  • 步驟1,保存主節(jié)點(diǎn)信息:

    • 從節(jié)點(diǎn)服務(wù)器內(nèi)部維護(hù)了兩個(gè)字段糕非,即masterhost和masterport字段蒙具,用于存儲(chǔ)主節(jié)點(diǎn)的ip和port信息。
    • 需要注意的是朽肥,slaveof****是異步命令禁筏,從節(jié)點(diǎn)完成主節(jié)點(diǎn)ip和port的保存后,向發(fā)送slaveof命令的客戶端直接返回OK鞠呈,實(shí)際的復(fù)制操作在這之后才開(kāi)始進(jìn)行融师。
  • 步驟2,建立socket連接蚁吝,從節(jié)點(diǎn)每秒1次調(diào)用復(fù)制定時(shí)函數(shù)replicationCron()旱爆,如果發(fā)現(xiàn)了有主節(jié)點(diǎn)可以連接舀射,便會(huì)根據(jù)主節(jié)點(diǎn)的ip和port,創(chuàng)建socket連接怀伦。如果連接成功脆烟,則:

    • 從節(jié)點(diǎn):為該socket建立一個(gè)專門處理復(fù)制工作的文件事件處理器,負(fù)責(zé)后續(xù)的復(fù)制工作房待,如接收RDB文件邢羔、接收命令傳播等。
    • 主節(jié)點(diǎn):接收到從節(jié)點(diǎn)的socket連接后(即accept之后)桑孩,為該socket創(chuàng)建相應(yīng)的客戶端狀態(tài)拜鹤,并將從節(jié)點(diǎn)看做是連接到主節(jié)點(diǎn)的一個(gè)客戶端,后面的步驟會(huì)以從節(jié)點(diǎn)向主節(jié)點(diǎn)發(fā)送命令請(qǐng)求的形式來(lái)進(jìn)行流椒。
  • 步驟3敏簿,發(fā)送ping命令,從節(jié)點(diǎn)成為主節(jié)點(diǎn)的客戶端之后宣虾,發(fā)送ping命令進(jìn)行首次請(qǐng)求惯裕,目的是:檢查socket連接是否可用,以及主節(jié)點(diǎn)當(dāng)前是否能夠處理請(qǐng)求绣硝。從節(jié)點(diǎn)發(fā)送ping命令后蜻势,可能出現(xiàn)3種情況:

    • 返回pong:說(shuō)明socket連接正常,且主節(jié)點(diǎn)當(dāng)前可以處理請(qǐng)求鹉胖,復(fù)制過(guò)程繼續(xù)握玛。
    • 超時(shí):一定時(shí)間后從節(jié)點(diǎn)仍未收到主節(jié)點(diǎn)的回復(fù),說(shuō)明socket連接不可用次员,則從節(jié)點(diǎn)斷開(kāi)socket連接败许,并重連。
    • 返回pong以外的結(jié)果:如果主節(jié)點(diǎn)返回其他結(jié)果淑蔚,如正在處理超時(shí)運(yùn)行的腳本,說(shuō)明主節(jié)點(diǎn)當(dāng)前無(wú)法處理命令愕撰,則從節(jié)點(diǎn)斷開(kāi)socket連接刹衫,并重連。
  • 步驟4搞挣,身份驗(yàn)證:

    • 如果從節(jié)點(diǎn)中設(shè)置了masterauth選項(xiàng)带迟,則從節(jié)點(diǎn)需要向主節(jié)點(diǎn)進(jìn)行身份驗(yàn)證;沒(méi)有設(shè)置該選項(xiàng)囱桨,則不需要驗(yàn)證仓犬。從節(jié)點(diǎn)進(jìn)行身份驗(yàn)證是通過(guò)向主節(jié)點(diǎn)發(fā)送auth命令進(jìn)行的,auth命令的參數(shù)即為配置文件中的masterauth的值舍肠。
    • 如果主節(jié)點(diǎn)設(shè)置密碼的狀態(tài)搀继,與從節(jié)點(diǎn)masterauth的狀態(tài)一致(一致是指都存在窘面,且密碼相同,或者都不存在)叽躯,則身份驗(yàn)證通過(guò)财边,復(fù)制過(guò)程繼續(xù);如果不一致点骑,則從節(jié)點(diǎn)斷開(kāi)socket連接酣难,并重連。
  • 步驟5黑滴,發(fā)送從節(jié)點(diǎn)端口信息:

    • 身份驗(yàn)證之后憨募,從節(jié)點(diǎn)會(huì)向主節(jié)點(diǎn)發(fā)送其監(jiān)聽(tīng)的端口號(hào)(前述例子中為6380),主節(jié)點(diǎn)將該信息保存到該從節(jié)點(diǎn)對(duì)應(yīng)的客戶端的slave_listening_port字段中袁辈;該端口信息除了在主節(jié)點(diǎn)中執(zhí)行info Replication時(shí)顯示以外馋嗜,沒(méi)有其他作用。
5.1.1.2吵瞻、數(shù)據(jù)同步階段

主從節(jié)點(diǎn)之間的連接建立以后葛菇,便可以開(kāi)始進(jìn)行數(shù)據(jù)同步,該階段可以理解為從節(jié)點(diǎn)數(shù)據(jù)的初始化橡羞。具體執(zhí)行的方式是:從節(jié)點(diǎn)向主節(jié)點(diǎn)發(fā)送psync命令(Redis2.8以前是sync命令)眯停,開(kāi)始同步。

數(shù)據(jù)同步階段是主從復(fù)制最核心的階段卿泽,根據(jù)主從節(jié)點(diǎn)當(dāng)前狀態(tài)的不同莺债,可以分為全量復(fù)制和部分復(fù)制。

在Redis2.8 以前签夭,從節(jié)點(diǎn)向主節(jié)點(diǎn)發(fā)送sync命令請(qǐng)求同步數(shù)據(jù)齐邦,此時(shí)的同步方式是全量復(fù)制;在Redis2.8及以后第租,從節(jié)點(diǎn)可以發(fā)送psync命令請(qǐng)求同步數(shù)據(jù)措拇,此時(shí)根據(jù)主從節(jié)點(diǎn)當(dāng)前狀態(tài)的不同,同步方式可能是全量復(fù)制或部分復(fù)制慎宾。

  1. 全量復(fù)制:用于初次復(fù)制或其他無(wú)法進(jìn)行部分復(fù)制的情況丐吓,將主節(jié)點(diǎn)中的所有數(shù)據(jù)都發(fā)送給從節(jié)點(diǎn),是一個(gè)非常重型的操作趟据。
  2. 部分復(fù)制:用于網(wǎng)絡(luò)中斷等情況后的復(fù)制券犁,只將中斷期間主節(jié)點(diǎn)執(zhí)行的寫命令發(fā)送給從節(jié)點(diǎn),與全量復(fù)制相比更加高效汹碱。需要注意的是粘衬,如果網(wǎng)絡(luò)中斷時(shí)間過(guò)長(zhǎng),導(dǎo)致主節(jié)點(diǎn)沒(méi)有能夠完整地保存中斷期間執(zhí)行的寫命令,則無(wú)法進(jìn)行部分復(fù)制稚新,仍使用全量復(fù)制勘伺。

1)全量復(fù)制

Redis通過(guò) psync 命令進(jìn)行全量復(fù)制的過(guò)程如下:

  • 從節(jié)點(diǎn)判斷無(wú)法進(jìn)行部分復(fù)制,向主節(jié)點(diǎn)發(fā)送全量復(fù)制的請(qǐng)求枷莉;或從節(jié)點(diǎn)發(fā)送部分復(fù)制的請(qǐng)求娇昙,但主節(jié)點(diǎn)判斷無(wú)法進(jìn)行部分復(fù)制
  • 主節(jié)點(diǎn)收到全量復(fù)制的命令后,執(zhí)行 bgsave笤妙,在后臺(tái)生成 RDB 文件冒掌,并使用一個(gè)緩沖區(qū)(稱為復(fù)制緩沖區(qū))記錄從現(xiàn)在開(kāi)始執(zhí)行的所有寫命令
  • 主節(jié)點(diǎn)的 bgsave 執(zhí)行完成后,將 RDB 文件發(fā)送給從節(jié)點(diǎn)蹲盘;從節(jié)點(diǎn)首先清除自己的舊數(shù)據(jù)股毫,然后載入接收的RDB文件,將數(shù)據(jù)庫(kù)狀態(tài)更新至主節(jié)點(diǎn)執(zhí)行bgsave時(shí)的數(shù)據(jù)庫(kù)狀態(tài)
  • 主節(jié)點(diǎn)將前述復(fù)制緩沖區(qū)中的所有寫命令發(fā)送給從節(jié)點(diǎn)召衔,從節(jié)點(diǎn)執(zhí)行這些寫命令铃诬,將數(shù)據(jù)庫(kù)狀態(tài)更新至主節(jié)點(diǎn)的最新?tīng)顟B(tài)
  • 如果從節(jié)點(diǎn)開(kāi)啟了AOF,則會(huì)觸發(fā) bgrewriteaof 的執(zhí)行苍凛,從而保證AOF文件更新至主節(jié)點(diǎn)的最新?tīng)顟B(tài)

通過(guò)全量復(fù)制的過(guò)程可以看出趣席,全量復(fù)制是非常重型的操作:

  • 主節(jié)點(diǎn)通過(guò) bgsave 命令 fork 子進(jìn)程進(jìn)行 RDB 持久化,該過(guò)程是非常消耗 CPU醇蝴、內(nèi)存(頁(yè)表復(fù)制)宣肚、硬盤 IO 的;關(guān)于 bgsave 的性能問(wèn)題
  • 主節(jié)點(diǎn)通過(guò)網(wǎng)絡(luò)將 RDB 文件發(fā)送給從節(jié)點(diǎn)悠栓,對(duì)主從節(jié)點(diǎn)的帶寬都會(huì)帶來(lái)很大的消耗
  • 從節(jié)點(diǎn)清空老數(shù)據(jù)霉涨、載入新 RDB 文件的過(guò)程是阻塞的,無(wú)法響應(yīng)客戶端的命令惭适;如果從節(jié)點(diǎn)執(zhí)行 bgrewriteaof笙瑟,也會(huì)帶來(lái)額外的消耗

2)部分復(fù)制

由于全量復(fù)制在主節(jié)點(diǎn)數(shù)據(jù)量較大時(shí)效率太低,因此 Redis2.8 開(kāi)始提供部分復(fù)制癞志,用于處理網(wǎng)絡(luò)中斷時(shí)的數(shù)據(jù)同步往枷。

部分復(fù)制的實(shí)現(xiàn),依賴于三個(gè)重要的概念:

  • 復(fù)制偏移量

    • 主節(jié)點(diǎn)和從節(jié)點(diǎn)分別維護(hù)一個(gè)復(fù)制偏移量(offset)今阳,代表的是主節(jié)點(diǎn)向從節(jié)點(diǎn)傳遞的字節(jié)數(shù)师溅;主節(jié)點(diǎn)每次向從節(jié)點(diǎn)傳播N個(gè)字節(jié)數(shù)據(jù)時(shí),主節(jié)點(diǎn)的 offset 增加N盾舌;從節(jié)點(diǎn)每次收到主節(jié)點(diǎn)傳來(lái)的N個(gè)字節(jié)數(shù)據(jù)時(shí),從節(jié)點(diǎn)的 offset 增加N蘸鲸。
    • offset 用于判斷主從節(jié)點(diǎn)的數(shù)據(jù)庫(kù)狀態(tài)是否一致:如果二者 offset 相同妖谴,則一致;如果 offset 不同,則不一致膝舅,此時(shí)可以根據(jù)兩個(gè) offset 找出從節(jié)點(diǎn)缺少的那部分?jǐn)?shù)據(jù)嗡载。例如,如果主節(jié)點(diǎn)的 offset 是1000仍稀,而從節(jié)點(diǎn)的 offset 是500洼滚,那么部分復(fù)制就需要將 offset 為501-1000的數(shù)據(jù)傳遞給從節(jié)點(diǎn)。
  • 復(fù)制積壓緩沖區(qū)

    • 復(fù)制積壓緩沖區(qū)是由主節(jié)點(diǎn)維護(hù)的技潘、固定長(zhǎng)度的遥巴、先進(jìn)先出(FIFO)隊(duì)列,默認(rèn)大小1MB享幽;當(dāng)主節(jié)點(diǎn)開(kāi)始有從節(jié)點(diǎn)時(shí)創(chuàng)建铲掐,其作用是備份主節(jié)點(diǎn)最近發(fā)送給從節(jié)點(diǎn)的數(shù)據(jù)。注意值桩,無(wú)論主節(jié)點(diǎn)有一個(gè)還是多個(gè)從節(jié)點(diǎn)摆霉,都只需要一個(gè)復(fù)制積壓緩沖區(qū)。
    • 在命令傳播階段奔坟,主節(jié)點(diǎn)除了將寫命令發(fā)送給從節(jié)點(diǎn)携栋,還會(huì)發(fā)送一份給復(fù)制積壓緩沖區(qū),作為寫命令的備份咳秉;除了存儲(chǔ)寫命令婉支,復(fù)制積壓緩沖區(qū)中還存儲(chǔ)了其中的每個(gè)字節(jié)對(duì)應(yīng)的復(fù)制偏移量(offset)。由于復(fù)制積壓緩沖區(qū)定長(zhǎng)且是先進(jìn)先出滴某,所以它保存的是主節(jié)點(diǎn)最近執(zhí)行的寫命令磅摹;時(shí)間較早的寫命令會(huì)被擠出緩沖區(qū)。
    • 由于該緩沖區(qū)長(zhǎng)度固定且有限霎奢,因此可以備份的寫命令也有限户誓,當(dāng)主從節(jié)點(diǎn) offset 的差距過(guò)大超過(guò)緩沖區(qū)長(zhǎng)度時(shí),將無(wú)法執(zhí)行部分復(fù)制幕侠,只能執(zhí)行全量復(fù)制帝美。反過(guò)來(lái)說(shuō),為了提高網(wǎng)絡(luò)中斷時(shí)部分復(fù)制執(zhí)行的概率晤硕,可以根據(jù)需要增大復(fù)制積壓緩沖區(qū)的大小(通過(guò)配置 repl-backlog-size)悼潭;例如如果網(wǎng)絡(luò)中斷的平均時(shí)間是60s,而主節(jié)點(diǎn)平均每秒產(chǎn)生的寫命令(特定協(xié)議格式)所占的字節(jié)數(shù)為100KB舞箍,則復(fù)制積壓緩沖區(qū)的平均需求為 6MB舰褪,保險(xiǎn)起見(jiàn),可以設(shè)置為12MB疏橄,來(lái)保證絕大多數(shù)斷線情況都可以使用部分復(fù)制占拍。
    • 從節(jié)點(diǎn)將 offset 發(fā)送給主節(jié)點(diǎn)后略就,主節(jié)點(diǎn)根據(jù) offset 和緩沖區(qū)大小決定能否執(zhí)行部分復(fù)制:
      • 如果 offset 偏移量之后的數(shù)據(jù),仍然都在復(fù)制積壓緩沖區(qū)里晃酒,則執(zhí)行部分復(fù)制表牢;
      • 如果 offset 偏移量之后的數(shù)據(jù)已不在復(fù)制積壓緩沖區(qū)中(數(shù)據(jù)已被擠出),則執(zhí)行全量復(fù)制贝次。
  • 服務(wù)器運(yùn)行 ID(runid)

    • 每個(gè) Redis 節(jié)點(diǎn)(無(wú)論主從)崔兴,在啟動(dòng)時(shí)都會(huì)自動(dòng)生成一個(gè)隨機(jī)ID(每次啟動(dòng)都不一樣),由40個(gè)隨機(jī)的十六進(jìn)制字符組成蛔翅;runid 用來(lái)唯一識(shí)別一個(gè) Redis 節(jié)點(diǎn)敲茄。通過(guò) info Server 命令,可以查看節(jié)點(diǎn)的 runid
    • 主從節(jié)點(diǎn)初次復(fù)制時(shí)搁宾,主節(jié)點(diǎn)將自己的 runid 發(fā)送給從節(jié)點(diǎn)折汞,從節(jié)點(diǎn)將這個(gè) runid 保存起來(lái);當(dāng)斷線重連時(shí)盖腿,從節(jié)點(diǎn)會(huì)將這個(gè) runid 發(fā)送給主節(jié)點(diǎn)爽待;主節(jié)點(diǎn)根據(jù) runid 判斷能否進(jìn)行部分復(fù)制:
      • 如果從節(jié)點(diǎn)保存的 runid 與主節(jié)點(diǎn)現(xiàn)在的 runid 相同,說(shuō)明主從節(jié)點(diǎn)之前同步過(guò)翩腐,主節(jié)點(diǎn)會(huì)繼續(xù)嘗試使用部分復(fù)制(到底能不能部分復(fù)制還要看 offset 和復(fù)制積壓緩沖區(qū)的情況)鸟款;
      • 如果從節(jié)點(diǎn)保存的 runid 與主節(jié)點(diǎn)現(xiàn)在的 runid 不同,說(shuō)明從節(jié)點(diǎn)在斷線前同步的 Redis 節(jié)點(diǎn)并不是當(dāng)前的主節(jié)點(diǎn)茂卦,只能進(jìn)行全量復(fù)制何什。
5.1.1.3、命令傳播階段

數(shù)據(jù)同步階段完成后等龙,主從節(jié)點(diǎn)進(jìn)入命令傳播階段处渣;在這個(gè)階段主節(jié)點(diǎn)將自己執(zhí)行的寫命令發(fā)送給從節(jié)點(diǎn),從節(jié)點(diǎn)接收命令并執(zhí)行蛛砰,從而保證主從節(jié)點(diǎn)數(shù)據(jù)的一致性罐栈。

在命令傳播階段,除了發(fā)送寫命令泥畅,主從節(jié)點(diǎn)還維持著心跳機(jī)制:PING 和 REPLCONF ACK荠诬。

5.1.2、主從復(fù)制面臨的問(wèn)題

  • 一旦 主節(jié)點(diǎn)宕機(jī)位仁,從節(jié)點(diǎn) 晉升成 主節(jié)點(diǎn)柑贞,同時(shí)需要修改 應(yīng)用方主節(jié)點(diǎn)地址,還需要命令所有 從節(jié)點(diǎn)復(fù)制 新的主節(jié)點(diǎn)聂抢,整個(gè)過(guò)程需要 人工干預(yù)钧嘶。
  • 主節(jié)點(diǎn)寫能力 受到 單機(jī)的限制
  • 主節(jié)點(diǎn)存儲(chǔ)能力 受到 單機(jī)的限制琳疏。
  • 原生復(fù)制 的弊端在早期的版本中也會(huì)比較突出康辑,比如:Redis 復(fù)制中斷 后摄欲,從節(jié)點(diǎn) 會(huì)發(fā)起 psync轿亮。此時(shí)如果 同步不成功疮薇,則會(huì)進(jìn)行 全量同步主庫(kù) 執(zhí)行 全量備份 的同時(shí)我注,可能會(huì)造成毫秒或秒級(jí)的 卡頓按咒。

5.2、Redis Sentinel 的高可用

5.2.1但骨、Redis Sentinel的架構(gòu)

當(dāng)主節(jié)點(diǎn)出現(xiàn)故障時(shí)励七,Redis Sentinel 能自動(dòng)完成故障發(fā)現(xiàn)和故障轉(zhuǎn)移,并通知應(yīng)用方奔缠,從而實(shí)現(xiàn)真正的高可用掠抬。Redis Sentine 是一個(gè)分布式架構(gòu),其中包含若干個(gè) Sentinel 節(jié)點(diǎn)和 Redis 數(shù)據(jù)節(jié)點(diǎn)校哎,每個(gè) Sentinel 節(jié)點(diǎn)會(huì)對(duì)數(shù)據(jù)節(jié)點(diǎn)和其余Sentinel 節(jié)點(diǎn)進(jìn)行監(jiān)控两波,當(dāng)它發(fā)現(xiàn)節(jié)點(diǎn)不可達(dá)時(shí),會(huì)對(duì)節(jié)點(diǎn)做下線標(biāo)識(shí)闷哆。如果被標(biāo)識(shí)的是“主節(jié)點(diǎn)”腰奋,它還會(huì)和其他的Sentinel 節(jié)點(diǎn)進(jìn)行“協(xié)商”,當(dāng)大多數(shù) Sentinel 節(jié)點(diǎn)都認(rèn)為主節(jié)點(diǎn)不可達(dá)時(shí)抱怔,它們會(huì)選舉一個(gè) Sentinel 節(jié)點(diǎn)來(lái)完成自動(dòng)故障轉(zhuǎn)移的工作劣坊,同時(shí)會(huì)將這個(gè)變化實(shí)時(shí)通知給 Redis 應(yīng)用方。整個(gè)過(guò)程是自動(dòng)的屈留,不需要人工干預(yù)局冰,解決了 Redis 的高可用問(wèn)題。

5.2.2灌危、Redis Sentinel 功能

Sentinel 的主要功能包括 主節(jié)點(diǎn)存活檢測(cè)康二、主從運(yùn)行情況檢測(cè)自動(dòng)故障轉(zhuǎn)移failover)乍狐、主從切換赠摇。RedisSentinel 最小配置是 一主一從

RedisSentinel 系統(tǒng)可以用來(lái)管理多個(gè) Redis 服務(wù)器浅蚪,該系統(tǒng)可以執(zhí)行以下四個(gè)任務(wù):

  • 監(jiān)控

Sentinel 會(huì)不斷的檢查 主服務(wù)器從服務(wù)器 是否正常運(yùn)行藕帜。

  • 通知

當(dāng)被監(jiān)控的某個(gè) Redis 服務(wù)器出現(xiàn)問(wèn)題,Sentinel 通過(guò) API 腳本管理員 或者其他的 應(yīng)用程序 發(fā)送通知惜傲。

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

當(dāng) 主節(jié)點(diǎn) 不能正常工作時(shí)洽故,Sentinel 會(huì)開(kāi)始一次 自動(dòng)的 故障轉(zhuǎn)移操作,它會(huì)將與 失效主節(jié)點(diǎn)主從關(guān)系 的其中一個(gè) 從節(jié)點(diǎn) 升級(jí)為新的 主節(jié)點(diǎn)盗誊,并且將其他的 從節(jié)點(diǎn) 指向 新的主節(jié)點(diǎn)时甚。

  • 配置提供者

Redis Sentinel 模式下隘弊,客戶端應(yīng)用 在初始化時(shí)連接的是 Sentinel 節(jié)點(diǎn)集合,從中獲取 主節(jié)點(diǎn) 的信息荒适。

5.2.3梨熙、Redis Sentinel 核心知識(shí)

  • 哨兵至少需要3個(gè)實(shí)例,來(lái)保證自己的健壯性
  • 哨兵 + redis 主從的部署架構(gòu)刀诬,是不會(huì)保證數(shù)據(jù)零丟失的咽扇,只能保證 redis 集群的高可用性
  • 對(duì)于哨兵 + redis 主從這種復(fù)雜的部署架構(gòu),盡量在測(cè)試環(huán)境和生產(chǎn)環(huán)境陕壹,都進(jìn)行充足的測(cè)試和演練

5.2.4质欲、Redis Sentinel 的工作原理

Redis Sentinel 通過(guò)三個(gè)定時(shí)監(jiān)控任務(wù)完成對(duì)各個(gè)節(jié)點(diǎn)的發(fā)現(xiàn)和監(jiān)控:

  1. 每秒鐘,每個(gè) Sentinel 向它所知的 主服務(wù)器糠馆、從服務(wù)器 以及其他 Sentinel 實(shí)例 發(fā)送一次 PING 命令嘶伟。(這個(gè)定時(shí)任務(wù)是節(jié)點(diǎn)失敗判定的重要依據(jù),實(shí)現(xiàn)了對(duì)每個(gè)節(jié)點(diǎn)的監(jiān)控)
    • 如果一個(gè) 實(shí)例instance)距離 最后一次 有效回復(fù) PING 命令的時(shí)間超過(guò) down-after-milliseconds 所指定的值又碌,那么這個(gè)實(shí)例會(huì)被 Sentinel 標(biāo)記為 主觀下線九昧。
    • 如果一個(gè) 主服務(wù)器 被標(biāo)記為 主觀下線,那么正在 監(jiān)視 這個(gè) 主服務(wù)器 的所有 Sentinel 節(jié)點(diǎn)赠橙,要以 每秒一次的頻率確認(rèn) 主服務(wù)器 的確進(jìn)入了 主觀下線 狀態(tài)耽装。
    • 如果一個(gè) 主服務(wù)器 被標(biāo)記為 主觀下線,并且有 足夠數(shù)量Sentinel(至少要達(dá)到 配置文件 指定的數(shù)量)在指定的 時(shí)間范圍 內(nèi)同意這一判斷期揪,那么這個(gè) 主服務(wù)器 被標(biāo)記為 客觀下線掉奄。
  1. 每隔10秒,每個(gè) Sentinel 會(huì)向它已知的所有 主服務(wù)器 和 從服務(wù)器 發(fā)送一次 INFO 命令獲取最新的拓?fù)浣Y(jié)構(gòu)凤薛。當(dāng)一個(gè) 主服務(wù)器 被 Sentinel 標(biāo)記為 客觀下線 時(shí)姓建,Sentinel 向 下線主服務(wù)器 的所有 從服務(wù)器 發(fā)送 INFO 命令的頻率,會(huì)從 10 秒一次改為 每秒一次缤苫。
  1. 每隔2秒速兔,每個(gè) Sentinel 節(jié)點(diǎn)會(huì)向 Redis 數(shù)據(jù)節(jié)點(diǎn)的 sentinel:hello 頻道上發(fā)送該 Senitnel 節(jié)點(diǎn)對(duì)于主節(jié)點(diǎn)的判斷,以及當(dāng)前 Sentinel 節(jié)點(diǎn)的信息活玲,同時(shí)每個(gè) Sentinel 節(jié)點(diǎn)也會(huì)訂閱該頻道涣狗,來(lái)了解其他 Sentinel 節(jié)點(diǎn)以及他們對(duì)主節(jié)點(diǎn)的判斷。這個(gè)定時(shí)任務(wù)可以完成以下兩個(gè)工作:
    • 發(fā)現(xiàn)新的 Sentinel 節(jié)點(diǎn):通過(guò)訂閱主節(jié)點(diǎn)的 Sentinel:hello 了解其他 Sentinel 節(jié)點(diǎn)信息舒憾。如果是新加入的 Sentinel 節(jié)點(diǎn)镀钓,將該 Sentinel 節(jié)點(diǎn)信息保存起來(lái),并與該 Sentinel 節(jié)點(diǎn)創(chuàng)建連接
    • Sentinel 節(jié)點(diǎn)之間交換主節(jié)點(diǎn)狀態(tài)镀迂,作為后面客觀下線以及領(lǐng)導(dǎo)者選舉的依據(jù)丁溅。

5.3、Redis 集群

Redis 的哨兵模式基本已經(jīng)可以實(shí)現(xiàn)高可用探遵,讀寫分離 窟赏,但是在這種模式下每臺(tái) Redis 服務(wù)器都存儲(chǔ)相同的數(shù)據(jù)妓柜,很浪費(fèi)內(nèi)存,所以在redis3.0上加入了 Cluster 集群模式涯穷,實(shí)現(xiàn)了 Redis 的分布式存儲(chǔ)棍掐,對(duì)數(shù)據(jù)進(jìn)行分片,也就是說(shuō)每臺(tái) Redis 節(jié)點(diǎn)上存儲(chǔ)不同的內(nèi)容求豫;

在 Redis 的每一個(gè)節(jié)點(diǎn)上塌衰,都有這么兩個(gè)東西,一個(gè)是插槽(slot)蝠嘉,它的的取值范圍是:0-16383,還有一個(gè)就是cluster杯巨,可以理解為是一個(gè)集群管理的插件蚤告,類似哨兵。

當(dāng)我們的存取的 Key到達(dá)的時(shí)候服爷,Redis 會(huì)根據(jù) crc16的算法對(duì)計(jì)算后得出一個(gè)結(jié)果杜恰,然后把結(jié)果和16384 求余數(shù),這樣每個(gè) key 都會(huì)對(duì)應(yīng)一個(gè)編號(hào)在 0-16383 之間的哈希槽仍源,通過(guò)這個(gè)值心褐,去找到對(duì)應(yīng)的插槽所對(duì)應(yīng)的節(jié)點(diǎn),然后直接自動(dòng)跳轉(zhuǎn)到這個(gè)對(duì)應(yīng)的節(jié)點(diǎn)上進(jìn)行存取操作笼踩。

當(dāng)數(shù)據(jù)寫入到對(duì)應(yīng)的master節(jié)點(diǎn)后逗爹,這個(gè)數(shù)據(jù)會(huì)同步給這個(gè)master對(duì)應(yīng)的所有slave節(jié)點(diǎn)。

為了保證高可用嚎于,redis-cluster集群引入了主從模式掘而,一個(gè)主節(jié)點(diǎn)對(duì)應(yīng)一個(gè)或者多個(gè)從節(jié)點(diǎn)。當(dāng)其它主節(jié)點(diǎn)ping主節(jié)點(diǎn)master 1 時(shí)于购,如果半數(shù)以上的主節(jié)點(diǎn)與 master 1 通信超時(shí)袍睡,那么認(rèn)為master 1宕機(jī)了,就會(huì)啟用master 1的從節(jié)點(diǎn)slave 1肋僧,將slave 1變成主節(jié)點(diǎn)繼續(xù)提供服務(wù)斑胜。

如果master 1和它的從節(jié)點(diǎn)slave 1都宕機(jī)了,整個(gè)集群就會(huì)進(jìn)入fail狀態(tài)嫌吠,因?yàn)榧旱膕lot映射不完整止潘。如果集群超過(guò)半數(shù)以上的master掛掉,無(wú)論是否有slave居兆,集群都會(huì)進(jìn)入fail狀態(tài)覆山。

redis-cluster采用去中心化的思想,沒(méi)有中心節(jié)點(diǎn)的說(shuō)法泥栖,客戶端與Redis節(jié)點(diǎn)直連簇宽,不需要中間代理層勋篓,客戶端不需要連接集群所有節(jié)點(diǎn),連接集群中任何一個(gè)可用節(jié)點(diǎn)即可魏割。

5.4譬嚣、總結(jié)

主從模式:master節(jié)點(diǎn)掛掉后,需要手動(dòng)指定新的master钞它,可用性不高拜银,基本不用。

哨兵模式:master節(jié)點(diǎn)掛掉后遭垛,哨兵進(jìn)程會(huì)主動(dòng)選舉新的master尼桶,可用性高,但是每個(gè)節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)是一樣的锯仪,浪費(fèi)內(nèi)存空間泵督。數(shù)據(jù)量不是很多,集群規(guī)模不是很大庶喜,需要自動(dòng)容錯(cuò)容災(zāi)的時(shí)候使用小腊。

集群模式:數(shù)據(jù)量比較大,QPS要求較高的時(shí)候使用久窟。 Redis Cluster是Redis 3.0以后才正式推出秩冈,時(shí)間較晚,目前能證明在大規(guī)模生產(chǎn)環(huán)境下成功的案例還不是很多斥扛,需要時(shí)間檢驗(yàn)入问。

六、參考來(lái)源

redis 系列之——高可用(主從犹赖、哨兵队他、集群)
深入剖析Redis系列(二) - Redis哨兵模式與高可用集群

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市峻村,隨后出現(xiàn)的幾起案子麸折,更是在濱河造成了極大的恐慌,老刑警劉巖粘昨,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垢啼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡张肾,警方通過(guò)查閱死者的電腦和手機(jī)芭析,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吞瞪,“玉大人馁启,你說(shuō)我怎么就攤上這事。” “怎么了惯疙?”我有些...
    開(kāi)封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵翠勉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我霉颠,道長(zhǎng)对碌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任蒿偎,我火速辦了婚禮朽们,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诉位。我一直安慰自己骑脱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布不从。 她就那樣靜靜地躺著惜姐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪椿息。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天坷衍,我揣著相機(jī)與錄音寝优,去河邊找鬼。 笑死枫耳,一個(gè)胖子當(dāng)著我的面吹牛乏矾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迁杨,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钻心,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼倚舀!你這毒婦竟也來(lái)了蜻牢?” 一聲冷哼從身側(cè)響起垄开,我...
    開(kāi)封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蒲讯,失蹤者是張志新(化名)和其女友劉穎室琢,沒(méi)想到半個(gè)月后恳蹲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贪薪,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡璃饱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年骏全,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苍柏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姜贡,死狀恐怖试吁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情楼咳,我是刑警寧澤熄捍,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布烛恤,位于F島的核電站,受9級(jí)特大地震影響治唤,放射性物質(zhì)發(fā)生泄漏棒动。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一宾添、第九天 我趴在偏房一處隱蔽的房頂上張望船惨。 院中可真熱鬧,春花似錦缕陕、人聲如沸粱锐。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)怜浅。三九已至,卻和暖如春蔬崩,著一層夾襖步出監(jiān)牢的瞬間恶座,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工沥阳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留跨琳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓桐罕,卻偏偏與公主長(zhǎng)得像脉让,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子功炮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345