問(wèn)題:怎么讓一個(gè)原來(lái)的 slave 節(jié)點(diǎn)成為主節(jié)點(diǎn)揽碘?
選出 Sentinel Leader 之后居兆,由 Sentinel Leader 向某個(gè)節(jié)點(diǎn)發(fā)送 slaveof no one命令,讓它成為獨(dú)立節(jié)點(diǎn)州邢。
然后向其他節(jié)點(diǎn)發(fā)送 slaveof x.x.x.x xxxx(本機(jī)服務(wù))曾沈,讓它們成為這個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)迷扇,故障轉(zhuǎn)移完成。
問(wèn)題:這么多從節(jié)點(diǎn)存和,選誰(shuí)成為主節(jié)點(diǎn)奕剃?
關(guān)于從節(jié)點(diǎn)選舉,一共有四個(gè)因素影響選舉的結(jié)果哑姚,分別是斷開(kāi)連接時(shí)長(zhǎng)祭饭、優(yōu)先級(jí)排序、復(fù)制數(shù)量叙量、進(jìn)程 id倡蝙。
如果與哨兵連接斷開(kāi)的比較久,超過(guò)了某個(gè)閾值绞佩,就直接失去了選舉權(quán)寺鸥。如果擁有選舉權(quán),那就看誰(shuí)的優(yōu)先級(jí)高品山,這個(gè)在配置文件里可以設(shè)置(replica-priority 100)胆建,數(shù)值越小優(yōu)先級(jí)越高。
如果優(yōu)先級(jí)相同肘交,就看誰(shuí)從 master 中復(fù)制的數(shù)據(jù)最多(復(fù)制偏移量最大)笆载,選最多的那個(gè),如果復(fù)制數(shù)量也相同涯呻,就選擇進(jìn)程 id 最小的那個(gè)
1. 什么是Redis數(shù)據(jù)庫(kù)凉驻?
Redis 是完全開(kāi)源免費(fèi)的,是一個(gè)高性能的 key-value 數(shù)據(jù)庫(kù)复罐。
它的特點(diǎn)有:
(1)Redis 支持?jǐn)?shù)據(jù)的持久化涝登,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行使用效诅。
(2)Redis 不僅僅支持簡(jiǎn)單的 key-value 類型的數(shù)據(jù)胀滚,同時(shí)還提供 list趟济,set,zset咽笼,hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)顷编。
(3)Redis 支持?jǐn)?shù)據(jù)的備份,即 master-slave 模式的數(shù)據(jù)備份褐荷。
Redis 優(yōu)勢(shì):
- 性能極高勾效,2. 豐富數(shù)據(jù)類型,3. 原子 4. 運(yùn)行在內(nèi)存但可以保存在磁盤(pán)叛甫。
2. Redis 的數(shù)據(jù)類型层宫?
答:Redis 支持五種數(shù)據(jù)類型:string(字符串),hash(哈希)其监,list(列表)萌腿,set(集合)及 zsetsorted set:有序集合)。
我們實(shí)際項(xiàng)目中比較常用的是 string抖苦,hash
3. 使用Redis的好處毁菱?
(1)速度快,因?yàn)閿?shù)據(jù)存在內(nèi)存中锌历,類似于 HashMap贮庞,HashMap 的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是 O1)
(2)支持豐富數(shù)據(jù)類型,支持 string究西,list窗慎,set,Zset卤材,hash 等
(3)支持事務(wù)遮斥,操作都是原子性,所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行扇丛,要么全部不執(zhí)行
(4)豐富的特性:可用于緩存术吗,消息,按 key 設(shè)置過(guò)期時(shí)間帆精,過(guò)期后將會(huì)自動(dòng)刪除
4. Memcache 與 Redis 的區(qū)別都有哪些较屿?
(1)存儲(chǔ)方式 Memecache 把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會(huì)掛掉卓练,數(shù)據(jù)不能超過(guò)內(nèi)存大小隘蝎。 Redis 有部份存在硬盤(pán)上,這樣能保證數(shù)據(jù)的持久性昆庇。
(2)數(shù)據(jù)支持類型 Memcache 對(duì)數(shù)據(jù)類型支持相對(duì)簡(jiǎn)單末贾。 Redis 有復(fù)雜的數(shù)據(jù)類型闸溃。
(3)使用底層模型不同 它們之間底層實(shí)現(xiàn)方式 以及與客戶端之間通信的應(yīng)用協(xié)議不一樣整吆。 Redis 直接自己構(gòu)建了 VM 機(jī)制 拱撵,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求表蝙。
5.Redis 是單進(jìn)程單線程的拴测?
答:Redis 是單進(jìn)程單線程的,redis 利用隊(duì)列技術(shù)將并發(fā)訪問(wèn)變?yōu)榇性L問(wèn)府蛇,消除了傳統(tǒng)數(shù)據(jù)庫(kù)串行控制的開(kāi)銷集索。
6. 一個(gè)字符串類型的值能存儲(chǔ)最大容量是多少?
答:512M
7. Redis 的持久化機(jī)制是什么汇跨?各自的優(yōu)缺點(diǎn)务荆?
Redis提供兩種持久化機(jī)制 RDB 和 AOF 機(jī)制:
1、RDBRedis DataBase)持久化方式:
是指用數(shù)據(jù)集快照的方式半持久化模式)記錄 redis 數(shù)據(jù)庫(kù)的所有鍵值對(duì),在某個(gè)時(shí)間點(diǎn)將數(shù)據(jù)寫(xiě)入一個(gè)臨時(shí)文件穷遂,持久化結(jié)束后函匕,用這個(gè)臨時(shí)文件替換上次持久化的文件,達(dá)到數(shù)據(jù)恢復(fù)蚪黑。
優(yōu)點(diǎn):
(1)只有一個(gè)文件 dump.rdb盅惜,方便持久化。
(2)容災(zāi)性好忌穿,一個(gè)文件可以保存到安全的磁盤(pán)抒寂。
(3)性能最大化,fork 子進(jìn)程來(lái)完成寫(xiě)操作掠剑,讓主進(jìn)程繼續(xù)處理命令屈芜,所以是 IO最大化。使用單獨(dú)子進(jìn)程來(lái)進(jìn)行持久化澡腾,主進(jìn)程不會(huì)進(jìn)行任何 IO 操作沸伏,保證了 redis的高性能)
(4)相對(duì)于數(shù)據(jù)集大時(shí),比 AOF 的啟動(dòng)效率更高动分。
缺點(diǎn):
數(shù)據(jù)安全性低毅糟。RDB 是間隔一段時(shí)間進(jìn)行持久化,如果持久化之間 redis 發(fā)生故障澜公,會(huì)發(fā)生數(shù)據(jù)丟失姆另。所以這種方式更適合數(shù)據(jù)要求不嚴(yán)謹(jǐn)?shù)臅r(shí)候
2、AOFAppend-only file)持久化方式:
是指所有的命令行記錄以 redis 命令請(qǐng)求協(xié)議的格式完全持久化存儲(chǔ))保存為 aof 文件坟乾。
優(yōu)點(diǎn):
(1)數(shù)據(jù)安全迹辐,aof 持久化可以配置 appendfsync 屬性,有 always甚侣,每進(jìn)行一次命令操作就記錄到 aof 文件中一次明吩。
(2)通過(guò) append 模式寫(xiě)文件,即使中途服務(wù)器宕機(jī)殷费,可以通過(guò) redis-check-aof工具解決數(shù)據(jù)一致性問(wèn)題印荔。
(3)AOF 機(jī)制的 rewrite 模式低葫。AOF 文件沒(méi)被 rewrite 之前(文件過(guò)大時(shí)會(huì)對(duì)命令進(jìn)行合并重寫(xiě)),可以刪除其中的某些命令(比如誤操作的 flushall))
缺點(diǎn):
(1)AOF 文件比 RDB 文件大仍律,且恢復(fù)速度慢嘿悬。
(2)數(shù)據(jù)集大的時(shí)候,比 rdb 啟動(dòng)效率低水泉。
8.Redis為什么是單線程的善涨?
多線程處理會(huì)涉及到鎖,而且多線程處理會(huì)涉及到線程切換而消耗CPU草则。因?yàn)镃PU不是Redis的瓶頸钢拧,Redis的瓶頸最有可能是機(jī)器內(nèi)存或者網(wǎng)絡(luò)帶寬。單線程無(wú)法發(fā)揮多核CPU性能炕横,不過(guò)可以通過(guò)在單機(jī)開(kāi)多個(gè)Redis實(shí)例來(lái)解決娶靡。
9. Redis 常見(jiàn)性能問(wèn)題和解決方案:
(1)Master 最好不要寫(xiě)內(nèi)存快照,如果 Master 寫(xiě)內(nèi)存快照看锉,save 命令調(diào)度 rdbSave函數(shù)姿锭,會(huì)阻塞主線程的工作,當(dāng)快照比較大時(shí)對(duì)性能影響是非常大的伯铣,會(huì)間斷性暫停服務(wù)
(2)如果數(shù)據(jù)比較重要呻此,某個(gè) Slave 開(kāi)啟 AOF 備份數(shù)據(jù),策略設(shè)置為每秒同步一
(3)為了主從復(fù)制的速度和連接的穩(wěn)定性腔寡,Master 和 Slave 最好在同一個(gè)局域網(wǎng)
(4)盡量避免在壓力很大的主庫(kù)上增加從
(5)主從復(fù)制不要用圖狀結(jié)構(gòu)焚鲜,用單向鏈表結(jié)構(gòu)更為穩(wěn)定,即:Master <- Slave1<- Slave2 <- Slave3…這樣的結(jié)構(gòu)方便解決單點(diǎn)故障問(wèn)題放前,實(shí)現(xiàn) Slave 對(duì) Master的替換忿磅。如果 Master 掛了,可以立刻啟用 Slave1 做 Master凭语,其他不變葱她。
10. redis 過(guò)期鍵的刪除策略?
(1)定時(shí)刪除:在設(shè)置鍵的過(guò)期時(shí)間的同時(shí)似扔,創(chuàng)建一個(gè)定時(shí)器 timer). 讓定時(shí)器在鍵的過(guò)期時(shí)間來(lái)臨時(shí)吨些,立即執(zhí)行對(duì)鍵的刪除操作。
(2)惰性刪除:放任鍵過(guò)期不管炒辉,但是每次從鍵空間中獲取鍵時(shí)豪墅,都檢查取得的鍵是否過(guò)期,如果過(guò)期的話黔寇,就刪除該鍵;如果沒(méi)有過(guò)期偶器,就返回該鍵。
(3)定期刪除:每隔一段時(shí)間程序就對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次檢查,刪除里面的過(guò)期鍵屏轰。至于要?jiǎng)h除多少過(guò)期鍵术裸,以及要檢查多少個(gè)數(shù)據(jù)庫(kù),則由算法決定亭枷。
11、Redis 的回收策略(淘汰策略)?
volatile-lru:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過(guò)期的數(shù)據(jù)淘汰
volatile-random:從已設(shè)置過(guò)期時(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ù)
注意這里的 6 種機(jī)制搀崭,volatile 和 allkeys 規(guī)定了是對(duì)已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集淘汰數(shù)據(jù)還是從全部數(shù)據(jù)集淘汰數(shù)據(jù)叨粘,后面的 lru、ttl 以及 random 是三種不同的淘汰策略瘤睹,再加上一種 no-enviction 永不回收的策略升敲。
使用策略規(guī)則:
(1)如果數(shù)據(jù)呈現(xiàn)冪律分布,也就是一部分?jǐn)?shù)據(jù)訪問(wèn)頻率高轰传,一部分?jǐn)?shù)據(jù)訪問(wèn)頻率低驴党,則使用 allkeys-lru
(2)如果數(shù)據(jù)呈現(xiàn)平等分布,也就是所有的數(shù)據(jù)訪問(wèn)頻率都相同获茬,則使用allkeys-random
12港庄、為什么 edis 需要把所有數(shù)據(jù)放到內(nèi)存中?
答 :Redis 為了達(dá)到最快的讀寫(xiě)速度將數(shù)據(jù)都讀到內(nèi)存中恕曲,并通過(guò)異步的方式將數(shù)據(jù)寫(xiě)入磁盤(pán)鹏氧。所以 redis 具有快速和數(shù)據(jù)持久化的特征。如果不將數(shù)據(jù)放在內(nèi)存中佩谣,磁盤(pán) I/O 速度為嚴(yán)重影響 redis 的性能把还。在內(nèi)存越來(lái)越便宜的今天,redis 將會(huì)越來(lái)越受歡迎颓影。如果設(shè)置了最大使用的內(nèi)存褒颈,則數(shù)據(jù)已有記錄數(shù)達(dá)到內(nèi)存限值后不能繼續(xù)插入新值耀盗。
13、Redis 的同步機(jī)制了解么艇炎?
答:Redis 可以使用主從同步,從從同步腾窝。第一次同步時(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ò)程托慨。
14、Pipeline 有什么好處暇榴,為什么要用 pipeline厚棵?
答:可以將多次 IO 往返的時(shí)間縮減為一次蕉世,前提是 pipeline 執(zhí)行的指令之間沒(méi)有因果相關(guān)性。使用 redis-benchmark 進(jìn)行壓測(cè)的時(shí)候可以發(fā)現(xiàn)影響 redis 的 QPS峰值的一個(gè)重要因素是 pipeline 批次指令的數(shù)目婆硬。
15狠轻、是否使用過(guò) Redis 集群,集群的原理是什么彬犯?
(1)Redis Sentinal 著眼于高可用向楼,在 master 宕機(jī)時(shí)會(huì)自動(dòng)將 slave 提升為master,繼續(xù)提供服務(wù)谐区。
(2)Redis Cluster 著眼于擴(kuò)展性湖蜕,在單個(gè) redis 內(nèi)存不足時(shí),使用 Cluster 進(jìn)行分片存儲(chǔ)宋列。
16昭抒、Redis 如何設(shè)置密碼及驗(yàn)證密碼?
設(shè)置密碼:config set requirepass 123456
授權(quán)密碼:auth 123456
17炼杖、說(shuō)說(shuō) Redis 哈希槽的概念灭返?
答:Redis 集群沒(méi)有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有16384 個(gè)哈希槽坤邪,每個(gè) key 通過(guò) CRC16 校驗(yàn)后對(duì) 16384 取模來(lái)決定放置哪個(gè)槽婆殿,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分 hash 槽。
18罩扇、Redis 集群的主從復(fù)制模型是怎樣的婆芦?
答:為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無(wú)法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,每個(gè)節(jié)點(diǎn)都會(huì)有 N-1 個(gè)復(fù)制品.
19喂饥、Redis 集群會(huì)有寫(xiě)操作丟失嗎消约?為什么?
答 :Redis 并不能保證數(shù)據(jù)的強(qiáng)一致性员帮,這意味這在實(shí)際中集群在特定的條件下可能會(huì)丟失寫(xiě)操作或粮。
20、Redis 集群之間是如何復(fù)制的捞高?
答:異步復(fù)制
21氯材、Redis 集群最大節(jié)點(diǎn)個(gè)數(shù)是多少?
答:16384 個(gè)硝岗。
22氢哮、怎么測(cè)試 Redis 的連通性?
答:使用 ping 命令型檀。
23冗尤、怎么理解 Redis 事務(wù)?
答:
(1)事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會(huì)序列化、按順序地執(zhí)行裂七。事務(wù)在執(zhí)行的過(guò)程中皆看,不會(huì)被其他客戶端發(fā)送來(lái)的命令請(qǐng)求所打斷。
(2)事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行背零,要么全部都不執(zhí)行腰吟。
24、Redis key 的過(guò)期時(shí)間和永久有效分別怎么設(shè)置徙瓶?
答:EXPIRE 和 PERSIST 命令毛雇。
25、Redis 如何做內(nèi)存優(yōu)化倍啥?
答:盡可能使用散列表(hashes),散列表(是說(shuō)散列表里面存儲(chǔ)的數(shù)少)使用的內(nèi)存非常小澎埠,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面虽缕。比如你的 web 系統(tǒng)中有一個(gè)用戶對(duì)象,不要為這個(gè)用戶的名稱蒲稳,姓氏氮趋,郵箱,密碼設(shè)置單獨(dú)的 key,而是應(yīng)該把這個(gè)用戶的所有信息存儲(chǔ)到一張散列表里面江耀。
26剩胁、Redis 回收進(jìn)程如何工作的?
答:一個(gè)客戶端運(yùn)行了新的命令祥国,添加了新的數(shù)據(jù)昵观。Redi 檢查內(nèi)存使用情況,如果大于 maxmemory 的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收舌稀。一個(gè)新的命令被執(zhí)行啊犬,等等。所以我們不斷地穿越內(nèi)存限制的邊界壁查,通過(guò)不斷達(dá)到邊界然后不斷地回收回到邊界以下觉至。如果一個(gè)命令的結(jié)果導(dǎo)致大量?jī)?nèi)存被使用(例如很大的集合的交集保存到一個(gè)新的鍵),不用多久內(nèi)存限制就會(huì)被這個(gè)內(nèi)存使用量超越睡腿。
LRU算法.
27语御、Redis 的內(nèi)存用完了會(huì)發(fā)生什么?
答:如果達(dá)到設(shè)置的上限席怪,Redis 的寫(xiě)命令會(huì)返回錯(cuò)誤信息(但是讀命令還可以正常返回应闯。)或者你可以將 Redis 當(dāng)緩存來(lái)使用配置淘汰機(jī)制,當(dāng) Redis 達(dá)到內(nèi)存上限時(shí)會(huì)沖刷掉舊的內(nèi)容挂捻。
28孽锥、一個(gè) Redis 實(shí)例最多能存放多少的 keys?List、Set惜辑、Sorted Set 他們最多能存放多少元素唬涧?
答:理論上 Redis 可以處理多達(dá) 232 的 keys,并且在實(shí)際中進(jìn)行了測(cè)試盛撑,換句話說(shuō)碎节,Redis 的存儲(chǔ)極限是系統(tǒng)中的可用內(nèi)存值。
29抵卫、MySQL 里有 2000w 數(shù)據(jù)狮荔,redis 中只存 20w 的數(shù)據(jù),如何保證 redis 中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)介粘?
答:Redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時(shí)候殖氏,就會(huì)施行數(shù)據(jù)淘汰策略。
相關(guān)知識(shí):Redis 提供 6 種數(shù)據(jù)淘汰策略:
volatile-lru:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過(guò)期的數(shù)據(jù)淘汰
volatile-random:從已設(shè)置過(guò)期時(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ù)
30姻采、Redis 最適合的場(chǎng)景雅采?
1、會(huì)話緩存(Session Cache)
最常用的一種使用 Redis 的情景是會(huì)話緩存(session cache)慨亲。用 Redis 緩存會(huì)話比其他存儲(chǔ)(如 Memcached)的優(yōu)勢(shì)在于:Redis 提供持久化婚瓜。當(dāng)維護(hù)一個(gè)不是嚴(yán)格要求一致性的緩存時(shí),如果用戶的購(gòu)物車信息全部丟失刑棵,大部分人都會(huì)不高興的巴刻,現(xiàn)在,他們還會(huì)這樣嗎蛉签? 幸運(yùn)的是胡陪,隨著 Redis 這些年的改進(jìn),很容易找到怎么恰當(dāng)?shù)氖褂?Redis 來(lái)緩存會(huì)話的文檔碍舍。甚至廣為人知的商業(yè)平臺(tái)Magento 也提供 Redis 的插件督弓。
2、全頁(yè)緩存(FPC)
除基本的會(huì)話 token 之外乒验,Redis 還提供很簡(jiǎn)便的 FPC 平臺(tái)愚隧。回到一致性問(wèn)題锻全,即使重啟了 Redis 實(shí)例狂塘,因?yàn)橛写疟P(pán)的持久化,用戶也不會(huì)看到頁(yè)面加載速度的下降鳄厌,這是一個(gè)極大改進(jìn)荞胡,類似 PHP 本地 FPC。 再次以 Magento 為例了嚎,Magento提供一個(gè)插件來(lái)使用 Redis 作為全頁(yè)緩存后端泪漂。 此外廊营,對(duì) WordPress 的用戶來(lái)說(shuō),Pantheon 有一個(gè)非常好的插件 wp-redis萝勤,這個(gè)插件能幫助你以最快速度加載你曾瀏覽過(guò)的頁(yè)面露筒。
3、隊(duì)列
Reids 在內(nèi)存存儲(chǔ)引擎領(lǐng)域的一大優(yōu)點(diǎn)是提供 list 和 set 操作敌卓,這使得 Redis能作為一個(gè)很好的消息隊(duì)列平臺(tái)來(lái)使用慎式。Redis 作為隊(duì)列使用的操作,就類似于本地程序語(yǔ)言(如 Python)對(duì) list 的 push/pop 操作趟径。 如果你快速的在 Google中搜索“Redis queues”瘪吏,你馬上就能找到大量的開(kāi)源項(xiàng)目,這些項(xiàng)目的目的就是利用 Redis 創(chuàng)建非常好的后端工具蜗巧,以滿足各種隊(duì)列需求掌眠。例如,Celery 有一個(gè)后臺(tái)就是使用 Redis 作為 broker幕屹,你可以從這里去查看蓝丙。
4,排行榜/計(jì)數(shù)器
Redis 在內(nèi)存中對(duì)數(shù)字進(jìn)行遞增或遞減的操作實(shí)現(xiàn)的非常好香嗓。集合(Set)和有序集合(Sorted Set)也使得我們?cè)趫?zhí)行這些操作的時(shí)候變的非常簡(jiǎn)單迅腔,Redis 只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu)装畅。所以靠娱,我們要從排序集合中獲取到排名最靠前的 10個(gè)用戶–我們稱之為“user_scores”,我們只需要像下面一樣執(zhí)行即可: 當(dāng)然掠兄,這是假定你是根據(jù)你用戶的分?jǐn)?shù)做遞增的排序像云。如果你想返回用戶及用戶的分?jǐn)?shù),你需要這樣執(zhí)行: ZRANGE user_scores 0 10 WITHSCORES Agora Games 就是一個(gè)很好的例子蚂夕,用 Ruby 實(shí)現(xiàn)的迅诬,它的排行榜就是使用 Redis 來(lái)存儲(chǔ)數(shù)據(jù)的,你可以在這里看到婿牍。
5侈贷、發(fā)布/訂閱
最后(但肯定不是最不重要的)是 Redis 的發(fā)布/訂閱功能。發(fā)布/訂閱的使用場(chǎng)景確實(shí)非常多等脂。我已看見(jiàn)人們?cè)谏缃痪W(wǎng)絡(luò)連接中使用俏蛮,還可作為基于發(fā)布/訂閱的腳本觸發(fā)器,甚至用 Redis 的發(fā)布/訂閱功能來(lái)建立聊天系統(tǒng)上遥!
31搏屑、假如 Redis 里面有 1 億個(gè) key,其中有 10w 個(gè) key 是以某個(gè)固定的已知的前綴開(kāi)頭的粉楚,如果將它們?nèi)空页鰜?lái)辣恋?
答:使用 keys 指令可以掃出指定模式的 key 列表亮垫。
對(duì)方接著追問(wèn):如果這個(gè) redis 正在給線上的業(yè)務(wù)提供服務(wù),那使用 keys 指令會(huì)有什么問(wèn)題伟骨?
這個(gè)時(shí)候你要回答 redis 關(guān)鍵的一個(gè)特性: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)稻轨。
32、如果有大量的 key 需要設(shè)置同一時(shí)間過(guò)期雕凹,一般需要注意什么殴俱?
答:如果大量的 key 過(guò)期時(shí)間設(shè)置的過(guò)于集中,到過(guò)期的那個(gè)時(shí)間點(diǎn)枚抵,redis 可能會(huì)出現(xiàn)短暫的卡頓現(xiàn)象线欲。一般需要在時(shí)間上加一個(gè)隨機(jī)值,使得過(guò)期時(shí)間分散一些汽摹。
33李丰、使用過(guò) Redis 做異步隊(duì)列么,你是怎么用的逼泣?
答:一般使用 list 結(jié)構(gòu)作為隊(duì)列趴泌,rpush 生產(chǎn)消息,lpop 消費(fèi)消息拉庶。當(dāng) lpop 沒(méi)有消息的時(shí)候嗜憔,要適當(dāng) sleep 一會(huì)再重試。如果對(duì)方追問(wèn)可不可以不用 sleep 呢氏仗?list 還有個(gè)指令叫 blpop吉捶,在沒(méi)有消息的時(shí)候,它會(huì)阻塞住直到消息到來(lái)皆尔。如果對(duì)方追問(wèn)能不能生產(chǎn)一次消費(fèi)多次呢呐舔?使用 pub/sub 主題訂閱者模式,可以實(shí)現(xiàn)1:N 的消息隊(duì)列床佳。
如果對(duì)方追問(wèn) pub/sub 有什么缺點(diǎn)滋早?
在消費(fèi)者下線的情況下,生產(chǎn)的消息會(huì)丟失砌们,得使用專業(yè)的消息隊(duì)列如 RabbitMQ等杆麸。
如果對(duì)方追問(wèn) redis 如何實(shí)現(xiàn)延時(shí)隊(duì)列搁进?
我估計(jì)現(xiàn)在你很想把面試官一棒打死如果你手上有一根棒球棍的話,怎么問(wèn)的這么詳細(xì)昔头。但是你很克制饼问,然后神態(tài)自若的回答道:使用 sortedset,拿時(shí)間戳作為score揭斧,消息內(nèi)容作為 key 調(diào)用 zadd 來(lái)生產(chǎn)消息莱革,消費(fèi)者用 zrangebyscore 指令獲取 N 秒之前的數(shù)據(jù)輪詢進(jìn)行處理。到這里讹开,面試官暗地里已經(jīng)對(duì)你豎起了大拇指盅视。但是他不知道的是此刻你卻豎起了中指,在椅子背后旦万。
34闹击、使用過(guò) Redis 分布式鎖么,它是什么回事成艘?
先拿 setnx 來(lái)爭(zhēng)搶鎖赏半,搶到之后,再用 expire 給鎖加一個(gè)過(guò)期時(shí)間防止鎖忘記了釋放淆两。
這時(shí)候?qū)Ψ綍?huì)告訴你說(shuō)你回答得不錯(cuò)断箫,然后接著問(wèn)如果在 setnx 之后執(zhí)行 expire之前進(jìn)程意外 crash 或者要重啟維護(hù)了,那會(huì)怎么樣秋冰?這時(shí)候你要給予驚訝的反饋:唉仲义,是喔,這個(gè)鎖就永遠(yuǎn)得不到釋放了丹莲。緊接著你需要抓一抓自己得腦袋光坝,故作思考片刻尸诽,好像接下來(lái)的結(jié)果是你主動(dòng)思考出來(lái)的甥材,然后回答:我記得 set 指令有非常復(fù)雜的參數(shù),這個(gè)應(yīng)該是可以同時(shí)把 setnx 和expire 合成一條指令來(lái)用的性含!對(duì)方這時(shí)會(huì)顯露笑容洲赵,心里開(kāi)始默念:摁,這小子還不錯(cuò)商蕴。
35. redis 實(shí)現(xiàn)高并發(fā)高可用叠萍?
redis 實(shí)現(xiàn)高并發(fā)主要依靠主從架構(gòu),一主多從.
對(duì)于性能來(lái)說(shuō)绪商,單主用來(lái)寫(xiě)入數(shù)據(jù)苛谷,單機(jī)幾萬(wàn)QPS,多從用來(lái)查詢數(shù)據(jù)格郁,多個(gè)從實(shí)例可以提供每秒 10w 的 QPS腹殿。
如果想要在實(shí)現(xiàn)高并發(fā)的同時(shí)独悴,容納大量的數(shù)據(jù),那么就需要 redis 集群锣尉,
使用 redis cluster 模式刻炒,可以提供每秒幾十萬(wàn)的讀寫(xiě)并發(fā)。
redis 高可用自沧,如果是做主從架構(gòu)部署坟奥,那么加上哨兵就可以了,就可以實(shí)現(xiàn)拇厢,任何一個(gè)實(shí)例宕機(jī)爱谁,可以進(jìn)行主備切換。
所以就有了幾個(gè)問(wèn)題孝偎?
什么是主從架構(gòu)管行,主從如何備份?
什么是redis cluster模式邪媳?
什么是哨兵集群?
36. redis 什么是主從架構(gòu)捐顷,主從如何備份?
主從(master-slave)架構(gòu)雨效,一主多從迅涮,主負(fù)責(zé)寫(xiě),并且將數(shù)據(jù)復(fù)制到其它的 slave 節(jié)點(diǎn)徽龟,從節(jié)點(diǎn)負(fù)責(zé)讀叮姑。所有的讀請(qǐng)求全部走從節(jié)點(diǎn)。這樣也可以很輕松實(shí)現(xiàn)水平擴(kuò)容据悔,支撐讀高并發(fā)传透。
Redis雖然讀取寫(xiě)入的速度都特別快,但是也會(huì)產(chǎn)生讀壓力特別大的情況极颓,所以為了緩解讀的壓力朱盐,所以進(jìn)行讀寫(xiě)分類,并對(duì)讀進(jìn)行擴(kuò)展菠隆。
優(yōu)點(diǎn):
1兵琳、解決數(shù)據(jù)備份問(wèn)題
2、做到讀寫(xiě)分離骇径,提高服務(wù)器性能
缺點(diǎn):
1躯肌、每個(gè)客戶端連接redis實(shí)例的時(shí)候都是指定了ip和端口號(hào)的,如果所連接的redis實(shí)例因?yàn)楣收舷戮€了破衔,而主從模式也沒(méi)有提供一定的手段通知客戶端另外可連接的客戶端地址清女,因而需要手動(dòng)更改客戶端配置重新連接
2、主從模式下晰筛,如果主節(jié)點(diǎn)由于故障下線了嫡丙,那么從節(jié)點(diǎn)因?yàn)闆](méi)有主節(jié)點(diǎn)而同步中斷忠售,因而需要人工進(jìn)行故障轉(zhuǎn)移工作
3、無(wú)法實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容
主從架構(gòu)就涉及到一個(gè)數(shù)據(jù)從主節(jié)點(diǎn)同步到從節(jié)點(diǎn)的問(wèn)題迄沫。涉及redis replication問(wèn)題
37. redis replication 的核心機(jī)制
當(dāng)啟動(dòng)一個(gè) slave node 的時(shí)候稻扬,它會(huì)發(fā)送一個(gè) PSYNC 命令給 master node,如果這是第一次連接master node 那么會(huì)觸發(fā)一次 full resynchronization 全量復(fù)制.全量復(fù)制的時(shí)候,master 會(huì)啟動(dòng)一個(gè)后臺(tái)線程羊瘩,開(kāi)始生成一份 RDB 快照文件泰佳,同時(shí)還會(huì)將從客戶端新收到的所有寫(xiě)命令緩存在內(nèi)存中。最后將生成的RDB文件發(fā)送給slave,slave會(huì)先寫(xiě)入本地磁盤(pán)尘吗,然后再?gòu)谋镜卮疟P(pán)加載到內(nèi)存中逝她,接著 master 會(huì)將內(nèi)存中緩存的寫(xiě)命令發(fā)送到 slave,slave 也會(huì)同步這些數(shù)據(jù)睬捶。
如果是連接之后 master node 僅會(huì)復(fù)制給 slave 部分缺少的數(shù)據(jù)黔宛。master 如果發(fā)現(xiàn)有多個(gè)slave node都來(lái)重新連接,僅僅會(huì)啟動(dòng)一個(gè)rdb save操作擒贸,用一份數(shù)據(jù)服務(wù)所有slave node臀晃。
注:redis2.8 開(kāi)始,就支持主從復(fù)制的斷點(diǎn)續(xù)傳介劫,如果主從復(fù)制過(guò)程中徽惋,斷掉了,那么可以接著上次復(fù)制的地方座韵,繼續(xù)復(fù)制下去险绘,而不是從頭開(kāi)始復(fù)制一份。
master node 會(huì)在內(nèi)存中維護(hù)一個(gè) backlog誉碴,master 和 slave 都會(huì)保存一個(gè) replica offset 還有一個(gè) master run id宦棺,offset 就是保存在 backlog 中的。如果 master 和 slave 網(wǎng)絡(luò)連接斷掉了黔帕,slave 會(huì)讓 master 從上次 replica offset 開(kāi)始繼續(xù)復(fù)制代咸,如果沒(méi)有找到對(duì)應(yīng)的 offset,那么就會(huì)執(zhí)行一次 resynchronization蹬屹。
38. redis保證數(shù)據(jù)同步機(jī)制
- master和slave都會(huì)維護(hù)一個(gè)offset
master會(huì)在自身不斷累加offset侣背,slave也會(huì)在自身不斷累加offset
slave每秒都會(huì)上報(bào)自己的offset給master白华,同時(shí)master也會(huì)保存每個(gè)slave的offset慨默,檢測(cè)offset來(lái)保證數(shù)據(jù)的一致性
- backlog
master node有一個(gè)backlog,默認(rèn)是1MB大小
master node給slave node復(fù)制數(shù)據(jù)時(shí)弧腥,也會(huì)將數(shù)據(jù)在backlog中同步寫(xiě)一份
backlog主要是用來(lái)做全量復(fù)制中斷候的增量復(fù)制的
- master run id
如果根據(jù)host+ip定位master node厦取,是不靠譜的,如果master node重啟或者數(shù)據(jù)出現(xiàn)了變化管搪,那么slave node應(yīng)該根據(jù)不同的run id區(qū)分虾攻,run id不同就做全量復(fù)制
如果需要不更改run id重啟redis铡买,可以使用redis-cli debug reload命令
- psync
從節(jié)點(diǎn)使用psync從master node進(jìn)行復(fù)制,psync runid offset霎箍。master node會(huì)根據(jù)自身的情況返回響應(yīng)信息奇钞,可能是FULLRESYNC runid offset觸發(fā)全量復(fù)制,可能是CONTINUE觸發(fā)增量復(fù)制
39. redis cluster 模式
redis 服務(wù)節(jié)點(diǎn)中任何兩個(gè)節(jié)點(diǎn)之間都是相互連通的漂坏【鞍#客戶端可以與任何一個(gè)節(jié)點(diǎn)相連接,然后就可以訪問(wèn)集群中的任何一個(gè)節(jié)點(diǎn)顶别。對(duì)其進(jìn)行存取和其他操作谷徙。
一般集群建議搭建三主三從架構(gòu),三主提供服務(wù)驯绎,三從提供備份功能完慧。
每一個(gè)節(jié)點(diǎn)都存有這個(gè)集群所有主節(jié)點(diǎn)以及從節(jié)點(diǎn)的信息。
Redis集群數(shù)據(jù)分片
在redis的每一個(gè)節(jié)點(diǎn)上剩失,都有這么兩個(gè)東西屈尼,一個(gè)是插槽(slot)可以理解為是一個(gè)可以存儲(chǔ)兩個(gè)數(shù)值的一個(gè)變量這個(gè)變量的取值范圍是:0-16383。還有一個(gè)就是cluster我個(gè)人把這個(gè)cluster理解為是一個(gè)集群管理的插件拴孤。當(dāng)我們的存取的key到達(dá)的時(shí)候鸿染,redis會(huì)根據(jù)crc16的算法得出一個(gè)結(jié)果,然后把結(jié)果對(duì) 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)行存取操作蚕冬。
投票過(guò)程是集群中所有master參與,如果半數(shù)以上master節(jié)點(diǎn)與master節(jié)點(diǎn)通信超時(shí)(cluster-node-timeout),認(rèn)為當(dāng)前master節(jié)點(diǎn)掛掉.
什么時(shí)候整個(gè)集群不可用(cluster_state:fail)?
如果集群任意master掛掉,且當(dāng)前master沒(méi)有slave.集群進(jìn)入fail狀態(tài),也可以理解成集群的slot映射[0-16383]不完整時(shí)進(jìn)入fail狀態(tài).
一個(gè)Redis實(shí)例具備了“數(shù)據(jù)存儲(chǔ)”和“路由重定向”,完全去中心化的設(shè)計(jì)是辕。這帶來(lái)的好處是部署非常簡(jiǎn)單囤热,直接部署Redis就行,不像Codis有那么多的組件和依賴获三。但帶來(lái)的問(wèn)題是很難對(duì)業(yè)務(wù)進(jìn)行無(wú)痛的升級(jí)旁蔼,如果哪天Redis集群出了什么嚴(yán)重的Bug,就只能回滾整個(gè)Redis集群疙教。
優(yōu)點(diǎn):
1棺聊、有效的解決了redis在分布式方面的需求
2、遇到單機(jī)內(nèi)存贞谓,并發(fā)和流量瓶頸等問(wèn)題時(shí)限佩,可采用Cluster方案達(dá)到負(fù)載均衡的目的
3、可實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容
4、P2P模式祟同,無(wú)中心化
5作喘、通過(guò)Gossip協(xié)議同步節(jié)點(diǎn)信息
6、自動(dòng)故障轉(zhuǎn)移晕城、Slot遷移中數(shù)據(jù)可用
缺點(diǎn):
1泞坦、架構(gòu)比較新,最佳實(shí)踐較少
2砖顷、為了性能提升暇矫,客戶端需要緩存路由表信息
3、節(jié)點(diǎn)發(fā)現(xiàn)择吊、reshard操作不夠自動(dòng)化
40. redis 什么是哨兵李根?
哨兵的功能:
集群監(jiān)控:負(fù)責(zé)監(jiān)控 redis master 和 slave 進(jìn)程是否正常工作。
消息通知:如果某個(gè) redis 實(shí)例有故障几睛,那么哨兵負(fù)責(zé)發(fā)送消息作為報(bào)警通知給管理員房轿。
故障轉(zhuǎn)移:如果 master node 掛掉了,會(huì)自動(dòng)轉(zhuǎn)移到 slave node 上所森。
配置中心:如果故障轉(zhuǎn)移發(fā)生了囱持,通知 client 客戶端新的 master 地址。
哨兵用于實(shí)現(xiàn) redis 集群的高可用焕济,本身也是分布式的纷妆,作為一個(gè)哨兵集群去運(yùn)行,互相協(xié)同工作晴弃。
故障轉(zhuǎn)移時(shí)掩幢,判斷一個(gè) master node 是否宕機(jī)了,需要大部分的哨兵都同意才行上鞠,涉及到了分布式選舉的問(wèn)題际邻。
即使部分哨兵節(jié)點(diǎn)掛掉了,哨兵集群還是能正常工作的芍阎。
哨兵的核心知識(shí)
哨兵至少需要 3 個(gè)實(shí)例世曾,來(lái)保證自己的健壯性。
哨兵 + redis 主從的部署架構(gòu)谴咸,是不保證數(shù)據(jù)零丟失的轮听,只能保證 redis 集群的高可用性。
對(duì)于哨兵 + redis 主從這種復(fù)雜的部署架構(gòu)岭佳,盡量在測(cè)試環(huán)境和生產(chǎn)環(huán)境血巍,都進(jìn)行充足的測(cè)試和演練。
41. 數(shù)據(jù)丟失問(wèn)題的解決方案驼唱?
進(jìn)行如下配置:
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有 1 個(gè) slave藻茂,數(shù)據(jù)復(fù)制和同步的延遲不能超過(guò) 10 秒。如果說(shuō)一旦所有的 slave玫恳,數(shù)據(jù)復(fù)制和同步的延遲都超過(guò)了 10 秒鐘辨赐,那么這個(gè)時(shí)候,master 就不會(huì)再接收任何請(qǐng)求了京办。
減少異步復(fù)制數(shù)據(jù)的丟失
有了 min-slaves-max-lag 這個(gè)配置掀序,就可以確保說(shuō),一旦 slave 復(fù)制數(shù)據(jù)和 ack 延時(shí)太長(zhǎng)惭婿,就認(rèn)為可能 master 宕機(jī)后損失的數(shù)據(jù)太多了不恭,那么就拒絕寫(xiě)請(qǐng)求,這樣可以把 master 宕機(jī)時(shí)由于部分?jǐn)?shù)據(jù)未同步到 slave 導(dǎo)致的數(shù)據(jù)丟失降低的可控范圍內(nèi)财饥。
減少腦裂的數(shù)據(jù)丟失
如果一個(gè) master 出現(xiàn)了腦裂换吧,跟其他 slave 丟了連接,那么上面兩個(gè)配置可以確保說(shuō)钥星,如果不能繼續(xù)給指定數(shù)量的 slave 發(fā)送數(shù)據(jù)沾瓦,而且 slave 超過(guò) 10 秒沒(méi)有給自己 ack 消息,那么就直接拒絕客戶端的寫(xiě)請(qǐng)求谦炒。
42. 怎么保證redis是高并發(fā)以及高可用的贯莺?
- sdown 和 odown 轉(zhuǎn)換機(jī)制
sdown 是主觀宕機(jī),就一個(gè)哨兵如果自己覺(jué)得一個(gè) master 宕機(jī)了宁改,那么就是主觀宕機(jī)缕探。odown 是客觀宕機(jī),如果 quorum 數(shù)量的哨兵都覺(jué)得一個(gè) master 宕機(jī)了还蹲,那么就是客觀宕機(jī)爹耗。
??sdown 達(dá)成的條件很簡(jiǎn)單,如果一個(gè)哨兵 ping 一個(gè) master谜喊,超過(guò)了 is-master-down-after-milliseconds 指定的毫秒數(shù)之后鲸沮,就主觀認(rèn)為 master 宕機(jī)了。sdown到odown轉(zhuǎn)換的條件很簡(jiǎn)單锅论,如果一個(gè)哨兵在指定時(shí)間內(nèi)讼溺,收到了 quorum 數(shù)量的 其它哨兵也認(rèn)為那個(gè) master 是 sdown 的,那么就認(rèn)為是 odown 了最易,客觀認(rèn)為master宕機(jī)怒坯。
- 哨兵集群的自動(dòng)發(fā)現(xiàn)機(jī)制
哨兵互相之間的發(fā)現(xiàn),是通過(guò) redis 的 pub/sub 系統(tǒng)實(shí)現(xiàn)的藻懒,每個(gè)哨兵都會(huì)往sentinel:hello這個(gè) channel 里發(fā)送一個(gè)消息剔猿,這時(shí)候所有其他哨兵都可以消費(fèi)到這個(gè)消息,并感知到其他的哨兵的存在嬉荆。
??每隔兩秒鐘归敬,每個(gè)哨兵都會(huì)往自己監(jiān)控的某個(gè) master+slaves 對(duì)應(yīng)的sentinel:hello channel 里發(fā)送一個(gè)消息,內(nèi)容是自己的 host、ip 和 runid 還有對(duì)這個(gè) master 的監(jiān)控配置汪茧。
??每個(gè)哨兵也會(huì)去監(jiān)聽(tīng)自己監(jiān)控的每個(gè) master+slaves 對(duì)應(yīng)的sentinel:hello channel椅亚,然后去感知到同樣在監(jiān)聽(tīng)這個(gè) master+slaves 的其他哨兵的存在。
??每個(gè)哨兵還會(huì)跟其他哨兵交換對(duì) master 的監(jiān)控配置舱污,互相進(jìn)行監(jiān)控配置的同步呀舔。
- slave 配置的自動(dòng)糾正
哨兵會(huì)負(fù)責(zé)自動(dòng)糾正 slave 的一些配置,比如 slave 如果要成為潛在的 master 候選人扩灯,哨兵會(huì)確保 slave 復(fù)制現(xiàn)有 master 的數(shù)據(jù); 如果 slave 連接到了一個(gè)錯(cuò)誤的 master 上媚赖,比如故障轉(zhuǎn)移之后,那么哨兵會(huì)確保它們連接到正確的 master 上珠插。
- slave->master 選舉算法
如果一個(gè) master 被認(rèn)為 odown 了惧磺,而且 majority 數(shù)量的哨兵都允許主備切換,那么某個(gè)哨兵就會(huì)執(zhí)行主備切換操作捻撑,此時(shí)首先要選舉一個(gè) slave 來(lái)磨隘,會(huì)考慮 slave 的一些信息:
跟 master 斷開(kāi)連接的時(shí)長(zhǎng)
0slave 優(yōu)先級(jí)
復(fù)制 offset
run id
如果一個(gè) slave 跟 master 斷開(kāi)連接的時(shí)間已經(jīng)超過(guò)了down-after-milliseconds的 10 倍,外加 master 宕機(jī)的時(shí)長(zhǎng)布讹,那么 slave 就被認(rèn)為不適合選舉為 master琳拭。(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下來(lái)會(huì)對(duì) slave 進(jìn)行排序:
按照 slave 優(yōu)先級(jí)進(jìn)行排序,slave priority 越低描验,優(yōu)先級(jí)就越高白嘁。
如果 slave priority 相同,那么看 replica offset膘流,哪個(gè) slave 復(fù)制了越多的數(shù)據(jù)絮缅,offset 越靠后,優(yōu)先級(jí)就越高呼股。
如果上面兩個(gè)條件都相同耕魄,那么選擇一個(gè) run id 比較小的那個(gè) slave。
- quorum 和 majority
每次一個(gè)哨兵要做主備切換彭谁,首先需要 quorum 數(shù)量的哨兵認(rèn)為 odown吸奴,然后選舉出一個(gè)哨兵來(lái)做切換,這個(gè)哨兵還得得到 majority 哨兵的授權(quán)缠局,才能正式執(zhí)行切換则奥。
??如果 quorum < majority,比如 5 個(gè)哨兵狭园,majority 就是 3读处,quorum 設(shè)置為2,那么就 3 個(gè)哨兵授權(quán)就可以執(zhí)行切換唱矛。
??但是如果 quorum >= majority罚舱,那么必須 quorum 數(shù)量的哨兵都授權(quán)井辜,比如 5 個(gè)哨兵,quorum 是 5管闷,那么必須 5 個(gè)哨兵都同意授權(quán)粥脚,才能執(zhí)行切換。
- configuration epoch
哨兵會(huì)對(duì)一套 redis master+slaves 進(jìn)行監(jiān)控渐北,有相應(yīng)的監(jiān)控的配置阿逃。
??執(zhí)行切換的那個(gè)哨兵铭拧,會(huì)從要切換到的新 master(salve->master)那里得到一個(gè) configuration epoch赃蛛,這就是一個(gè) version 號(hào),每次切換的 version 號(hào)都必須是唯一的搀菩。
??如果第一個(gè)選舉出的哨兵切換失敗了呕臂,那么其他哨兵,會(huì)等待 failover-timeout 時(shí)間肪跋,然后接替繼續(xù)執(zhí)行切換歧蒋,此時(shí)會(huì)重新獲取一個(gè)新的 configuration epoch,作為新的 version 號(hào)州既。
- configuraiton 傳播
哨兵完成切換之后谜洽,會(huì)在自己本地更新生成最新的 master 配置,然后同步給其他的哨兵吴叶,就是通過(guò)之前說(shuō)的 pub/sub 消息機(jī)制阐虚。
??這里之前的 version 號(hào)就很重要了,因?yàn)楦鞣N消息都是通過(guò)一個(gè) channel 去發(fā)布和監(jiān)聽(tīng)的蚌卤,所以一個(gè)哨兵完成一次新的切換之后实束,新的 master 配置是跟著新的 version 號(hào)的。其他的哨兵都是根據(jù)版本號(hào)的大小來(lái)更新自己的 master 配置的逊彭。
43.redis 如何清理過(guò)期數(shù)據(jù)咸灿?
定期清理 + 惰性清理
定期刪除:redis數(shù)據(jù)庫(kù)默認(rèn)每隔100ms就會(huì)進(jìn)行隨機(jī)抽取一些設(shè)置過(guò)期時(shí)間的key進(jìn)行檢測(cè),過(guò)期則刪除侮叮。
惰性刪除:定期刪除還沒(méi)有來(lái)得及刪除避矢,就被程序請(qǐng)求到的一個(gè)過(guò)期key,redis會(huì)先檢測(cè)key是否囊榜,過(guò)期审胸,如果過(guò)期則刪除,不進(jìn)行返回锦聊。
但是前面兩種機(jī)制可能還導(dǎo)致一些問(wèn)題就是歹嘹,過(guò)期的key如果大量堆積,刪除的速度太慢孔庭,內(nèi)存爆滿怎么辦尺上?
內(nèi)存淘汰機(jī)制
1)noeviction:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)材蛛,新寫(xiě)入操作會(huì)報(bào)錯(cuò)。
2)allkeys-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)怎抛,在鍵空間中卑吭,移除最近最少使用的key(這個(gè)是最常用的)就是LRU算法。
3)allkeys-random:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)马绝,在鍵空間中博其,隨機(jī)移除某個(gè)key,一般沒(méi)人用顾瞪。
4)volatile-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)汪诉,在設(shè)置了過(guò)期時(shí)間的鍵空間中,移除最近最少使用的key(這個(gè)一般不太合適)
5)volatile-random:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)椭赋,在設(shè)置了過(guò)期時(shí)間的鍵空間中抚岗,隨機(jī)移除某個(gè)key
6)volatile-ttl:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),在設(shè)置了過(guò)期時(shí)間的鍵空間中哪怔,有更早過(guò)期時(shí)間的key優(yōu)先移除
44. redis和memcache的區(qū)別
- redis擁有更多的數(shù)據(jù)結(jié)構(gòu)支持更多的數(shù)據(jù)操作宣蔚。redis操作是在服務(wù)端進(jìn)行。
- memcache需要將數(shù)據(jù)拿到客戶端操作认境,再傳輸回去胚委,增加IO次數(shù)和數(shù)據(jù)體積。
- redis中對(duì)于復(fù)雜操作比較高效叉信。
- redis支持cluster模式亩冬,memcached沒(méi)有原生的集群模型,需要客戶端往集群中分片寫(xiě)數(shù)據(jù)茉盏。
45. redis的單線程模式
首先為什么說(shuō)采用單線程模型鉴未,有人說(shuō)是由于多線程競(jìng)爭(zhēng)所以單線程更快?鸠姨?铜秆?
多線程絕大數(shù)肯定比單線程快,不采用多線程不是說(shuō)單線程比較塊讶迁,而是單線程實(shí)現(xiàn)起來(lái)簡(jiǎn)單连茧。其次由于redis是基于內(nèi)存的,cpu不是瓶頸巍糯,內(nèi)存才是瓶頸啸驯,所以采用單線程就可以了,同時(shí)也簡(jiǎn)化了數(shù)據(jù)結(jié)構(gòu)和算法實(shí)現(xiàn)祟峦。
簡(jiǎn)要說(shuō)下redis單線程模型罚斗。
Redis客戶端對(duì)服務(wù)端的每次調(diào)用都經(jīng)歷了發(fā)送命令,執(zhí)行命令宅楞,返回結(jié)果三個(gè)過(guò)程针姿。
所有的客戶端對(duì)服務(wù)端請(qǐng)求socket連接袱吆,服務(wù)端都會(huì)專門(mén)建立一個(gè)socket與其連接。
IO多路復(fù)用程序是單線程的輪訓(xùn)監(jiān)控所有的socket,但是IO多路復(fù)用程序,只負(fù)責(zé)監(jiān)控socket接受命令所行成的AE_READABLE距淫,IO多路復(fù)用是基于非阻塞機(jī)制的绞绒,所以拿到的命令不直接執(zhí)行。
將其加入一個(gè)隊(duì)列中榕暇,然后逐個(gè)被執(zhí)行蓬衡。并且多個(gè)客戶端發(fā)送的命令的執(zhí)行順序是不確定的。執(zhí)行的時(shí)候是基于內(nèi)存的單線程執(zhí)行彤枢。
但是可以確定的是不會(huì)有兩條命令被同時(shí)執(zhí)行狰晚,不會(huì)產(chǎn)生并發(fā)問(wèn)題,這就是Redis的單線程基本模型堂污。
46.為什么redis單線程也可以做到每秒萬(wàn)級(jí)別處理能力
(1)純內(nèi)存訪問(wèn)家肯。數(shù)據(jù)存放在內(nèi)存中龄砰,內(nèi)存的響應(yīng)時(shí)間大約是100納秒盟猖,這是Redis每秒萬(wàn)億級(jí)別訪問(wèn)的重要基礎(chǔ)。
(2)非阻塞I/O换棚,Redis采用epoll做為I/O多路復(fù)用技術(shù)的實(shí)現(xiàn)式镐,再加上Redis自身的事件處理模型將epoll中的連接,讀寫(xiě)固蚤,關(guān)閉都轉(zhuǎn)換為了時(shí)間娘汞,不在I/O上浪費(fèi)過(guò)多的時(shí)間。
(3)單線程避免了線程切換和競(jìng)態(tài)產(chǎn)生的消耗夕玩。
47.如何保證消費(fèi)系統(tǒng)的冪等性你弦?
MQ都可能出現(xiàn)重復(fù)消費(fèi)的問(wèn)題,就一個(gè)數(shù)據(jù)燎孟,或者一個(gè)請(qǐng)求禽作,給你重復(fù)來(lái)多次,你得確保對(duì)應(yīng)的數(shù)據(jù)是不會(huì)改變的揩页,不能出錯(cuò)旷偿。
保證冪等性:
- 數(shù)據(jù)要寫(xiě)庫(kù),你先根據(jù)主鍵查一下爆侣,如果這數(shù)據(jù)都有了萍程,你就別插入了,update一下
- 寫(xiě)redis兔仰,那沒(méi)問(wèn)題了茫负,反正每次都是set,天然冪等性
- 創(chuàng)建內(nèi)存set或者redis乎赴,每次插入前先去內(nèi)存set中查一下忍法,需要讓生產(chǎn)者發(fā)送每條數(shù)據(jù)的時(shí)候置吓,里面加一個(gè)全局唯一的id。