
純純的知識點,史上最全面的Redis面試題(含答案):哨兵+復(fù)制+事務(wù)+集群+持久化,轉(zhuǎn)發(fā)+關(guān)注是對小編最大的支持,更多面試題解見文末!
Redis支持哪幾種數(shù)據(jù)類型?
支持多種類型的數(shù)據(jù)結(jié)構(gòu)
1.string:最基本的數(shù)據(jù)類型,二進(jìn)制安全的字符串,最大512M。
2.list:按照添加順序保持順序的字符串列表。
3.set:無序的字符串集合,不存在重復(fù)的元素。
4.sorted set:已排序的字符串集合。
5.hash:key-value對的一種集合。
Redis主要有哪些功能?
1.哨兵(Sentinel)和復(fù)制(Replication)
Redis服務(wù)器毫無征兆的罷工是個麻煩事,如何保證備份的機(jī)器是原始服務(wù)器的完整備份呢?這時候就需要哨兵和復(fù)制。
哨兵Sentinel可以管理多個Redis服務(wù)器,它提供了監(jiān)控,提醒以及自動的故障轉(zhuǎn)移的功能,Replication則是負(fù)責(zé)讓一個Redis服務(wù)器可以配備多個備份的服務(wù)器。
Redis也是利用這兩個功能來保證Redis的高可用的。
2.事務(wù)
很多情況下我們需要一次執(zhí)行不止一個命令,而且需要其同時成功或者失敗。redis對事務(wù)的支持也是源自于這部分需求,即支持一次性按順序執(zhí)行多個命令的能力,并保證其原子性。
3.LUA腳本
在事務(wù)的基礎(chǔ)上,如果我們需要在服務(wù)端一次性的執(zhí)行更復(fù)雜的操作(包含一些邏輯判斷),則lua就可以排上用場了。
4.持久化
redis的持久化指的是redis會把內(nèi)存的中的數(shù)據(jù)寫入到硬盤中,在redis重新啟動的時候加載這些數(shù)據(jù),從而最大限度的降低緩存丟失帶來的影響。
5.集群(Cluster)
單臺服務(wù)器資源的總是有上限的,CPU資源和IO資源我們可以通過主從復(fù)制,進(jìn)行讀寫分離,把一部分CPU和IO的壓力轉(zhuǎn)移到從服務(wù)器上,這也有點類似mysql數(shù)據(jù)庫的主從同步。
在Redis官方的分布式方案出來之前,有twemproxy和codis兩種方案,這兩個方案總體上來說都是依賴proxy來進(jìn)行分布式的,下面的內(nèi)容有具體集群方案詳解。
Redis是單進(jìn)程單線程的?
Redis是單進(jìn)程單線程的,Redis利用隊列技術(shù)將并發(fā)訪問變?yōu)榇性L問,消除了傳統(tǒng)數(shù)據(jù)庫串行控制的開銷。
Redis為什么是單線程的?
多線程處理會涉及到鎖,而且多線程處理會涉及到線程切換而消耗CPU。因為CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機(jī)器內(nèi)存或者網(wǎng)絡(luò)帶寬。單線程無法發(fā)揮多核CPU性能,不過可以通過在單機(jī)開多個Redis實例來解決。
其它開源軟件采用的模型
Nginx:多進(jìn)程單線程模型
Memcached:單進(jìn)程多線程模型
使用Redis的優(yōu)勢?
- 速度快,因為數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢就是查找和操作的時間復(fù)雜度都是O(1)
- 支持豐富數(shù)據(jù)類型,支持string,list,set,sorted set,hash
- 支持事務(wù),操作都是原子性,所謂的原子性就是對數(shù)據(jù)的更改要么全部執(zhí)行,要么全部不執(zhí)行
- 豐富的特性:可用于緩存,消息,按key設(shè)置過期時間,過期后將會自動刪除
Redis單點吞吐量
單點TPS達(dá)到8萬/秒,QPS達(dá)到10萬/秒,補(bǔ)充下TPS和QPS的概念
1.QPS: 應(yīng)用系統(tǒng)每秒鐘最大能接受的用戶訪問量
每秒鐘處理完請求的次數(shù),注意這里是處理完,具體是指發(fā)出請求到服務(wù)器處理完成功返回結(jié)果??梢岳斫庠趕erver中有個counter,每處理一個請求加1,1秒后counter=QPS。
2.TPS: 每秒鐘最大能處理的請求數(shù)
每秒鐘處理完的事務(wù)次數(shù),一個應(yīng)用系統(tǒng)1s能完成多少事務(wù)處理,一個事務(wù)在分布式處理中,可能會對應(yīng)多個請求,對于衡量單個接口服務(wù)的處理能力,用QPS比較合理。
Redis相比memcached有哪些優(yōu)勢?
1.memcached所有的值均是簡單的字符串,Redis作為其替代者,支持更為豐富的數(shù)據(jù)類型
2.Redis的速度比memcached快很多
3.Redis可以持久化其數(shù)據(jù)
4.Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。
Redis有哪幾種數(shù)據(jù)淘汰策略?
在Redis中,允許用戶設(shè)置最大使用內(nèi)存大小server.maxmemory,當(dāng)Redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時候,就會施行數(shù)據(jù)淘汰策略。
1.volatile-lru:從已設(shè)置過期的數(shù)據(jù)集中挑選最近最少使用的淘汰
2.volatile-ttr:從已設(shè)置過期的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰
3.volatile-random:從已設(shè)置過期的數(shù)據(jù)集中任意挑選數(shù)據(jù)淘汰
4.allkeys-lru:從數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰
5.allkeys-random:從數(shù)據(jù)集中任意挑選數(shù)據(jù)淘汰
6.noenviction:禁止淘汰數(shù)據(jù)
redis淘汰數(shù)據(jù)時還會同步到aof
Redis集群方案應(yīng)該怎么做?都有哪些方案?
1.twemproxy
2.codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在 節(jié)點數(shù)量改變情況下,舊節(jié)點數(shù)據(jù)可恢復(fù)到新hash節(jié)點。
3.Redis cluster3.0自帶的集,特點在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持節(jié)點設(shè)置從節(jié)點。
具體請查看:高并發(fā)架構(gòu)系列:詳解Redis的存儲類型、集群架構(gòu)、以及應(yīng)用場景
Redis讀寫分離模型
通過增加Slave DB的數(shù)量,讀的性能可以線性增長。為了避免Master DB的單點故障,集群一般都會采用兩臺Master DB做雙機(jī)熱備,所以整個集群的讀和寫的可用性都非常高。
讀寫分離架構(gòu)的缺陷在于,不管是Master還是Slave,每個節(jié)點都必須保存完整的數(shù)據(jù),如果在數(shù)據(jù)量很大的情況下,集群的擴(kuò)展能力還是受限于單個節(jié)點的存儲能力,而且對于Write-intensive類型的應(yīng)用,讀寫分離架構(gòu)并不適合。
Redis數(shù)據(jù)分片模型
為了解決讀寫分離模型的缺陷,可以將數(shù)據(jù)分片模型應(yīng)用進(jìn)來。
可以將每個節(jié)點看成都是獨立的master,然后通過業(yè)務(wù)實現(xiàn)數(shù)據(jù)分片。
結(jié)合上面兩種模型,可以將每個master設(shè)計成由一個master和多個slave組成的模型。
Redis提供了哪幾種持久化方式?
RDB持久化方式能夠在指定的時間間隔能對你的數(shù)據(jù)進(jìn)行快照存儲
AOF持久化方式記錄每次對服務(wù)器寫的操作,當(dāng)服務(wù)器重啟的時候會重新執(zhí)行這些命令來恢復(fù)原始的數(shù)據(jù),AOF命令以Redis協(xié)議追加保存每次寫的操作到文件末尾.Redis還能對AOF文件進(jìn)行后臺重寫,使得AOF文件的體積不至于過大.
如果你只希望你的數(shù)據(jù)在服務(wù)器運行的時候存在,你也可以不使用任何持久化方式.
你也可以同時開啟兩種持久化方式, 在這種情況下, 當(dāng)Redis重啟的時候會優(yōu)先載入AOF文件來恢復(fù)原始的數(shù)據(jù),因為在通常情況下AOF文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集要完整.
最重要的事情是了解RDB和AOF持久化方式的不同,讓我們以RDB持久化方式開始。
如何選擇合適的持久化方式?
- Redis主要提供了兩種持久化機(jī)制:RDB和AOF
- RDB默認(rèn)開啟,會按照配置的指定時間將內(nèi)存中的數(shù)據(jù)快照到磁盤中,創(chuàng)建一個dump.rdb文件,Redis啟動時再恢復(fù)到內(nèi)存中。
Redis會單獨創(chuàng)建fork()一個子進(jìn)程,將當(dāng)前父進(jìn)程的數(shù)據(jù)庫數(shù)據(jù)復(fù)制到子進(jìn)程的內(nèi)存中,然后由子進(jìn)程寫入到臨時文件中,持久化的過程結(jié)束了,再用這個臨時文件替換上次的快照文件,然后子進(jìn)程退出,內(nèi)存釋放。
需要注意的是,每次快照持久化都會將主進(jìn)程的數(shù)據(jù)庫數(shù)據(jù)復(fù)制一遍,導(dǎo)致內(nèi)存開銷加倍,若此時內(nèi)存不足,則會阻塞服務(wù)器運行,直到復(fù)制結(jié)束釋放內(nèi)存;都會將內(nèi)存數(shù)據(jù)完整寫入磁盤一次,所以如果數(shù)據(jù)量大的話,而且寫操作頻繁,必然會引起大量的磁盤I/O操作,嚴(yán)重影響性能,并且最后一次持久化后的數(shù)據(jù)可能會丟失;
3.AOF以日志的形式記錄每個寫操作(讀操作不記錄),只需追加文件但不可以改寫文件,Redis啟動時會根據(jù)日志從頭到尾全部執(zhí)行一遍以完成數(shù)據(jù)的恢復(fù)工作。包括flushDB也會執(zhí)行。
主要有兩種方式觸發(fā):有寫操作就寫、每秒定時寫(也會丟數(shù)據(jù))。
因為AOF采用追加的方式,所以文件會越來越大,針對這個問題,新增了重寫機(jī)制,就是當(dāng)日志文件大到一定程度的時候,會fork出一條新進(jìn)程來遍歷進(jìn)程內(nèi)存中的數(shù)據(jù),每條記錄對應(yīng)一條set語句,寫到臨時文件中,然后再替換到舊的日志文件(類似rdb的操作方式)。默認(rèn)觸發(fā)是當(dāng)aof文件大小是上次重寫后大小的一倍且文件大于64M時觸發(fā)。
當(dāng)兩種方式同時開啟時,數(shù)據(jù)恢復(fù)Redis會優(yōu)先選擇AOF恢復(fù)。一般情況下,只要使用默認(rèn)開啟的RDB即可,因為相對于AOF,RDB便于進(jìn)行數(shù)據(jù)庫備份,并且恢復(fù)數(shù)據(jù)集的速度也要快很多。
開啟持久化緩存機(jī)制,對性能會有一定的影響,特別是當(dāng)設(shè)置的內(nèi)存滿了的時候,更是下降到幾百reqs/s。所以如果只是用來做緩存的話,可以關(guān)掉持久化。
Redis常見性能問題和解決方案?
(1) Master最好不要做任何持久化工作,如RDB內(nèi)存快照和AOF日志文件
(2) 如果數(shù)據(jù)比較重要,某個Slave開啟AOF備份數(shù)據(jù),策略設(shè)置為每秒同步一次
(3) 為了主從復(fù)制的速度和連接的穩(wěn)定性,Master和Slave最好在同一個局域網(wǎng)內(nèi)
(4) 盡量避免在壓力很大的主庫上增加從庫
(5) 主從復(fù)制不要用圖狀結(jié)構(gòu),用單向鏈表結(jié)構(gòu)更為穩(wěn)定,即:Master <- Slave1 <- Slave2 <- Slave3...
這樣的結(jié)構(gòu)方便解決單點故障問題,實現(xiàn)Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他不變。
Redis支持的Java客戶端都有哪些?官方推薦用哪個?
Redisson、Jedis、lettuce等等,官方推薦使用Redisson。
Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,當(dāng)需要在 Redis 集群中放置一個 key-value 時,根據(jù) CRC16(key) mod 16384的值,決定將一個key放到哪個桶中。
Redis集群最大節(jié)點個數(shù)是多少?
Redis集群預(yù)分好16384個桶(哈希槽)
Redis集群的主從復(fù)制模型是怎樣的?
為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,每個節(jié)點都會有N-1個復(fù)制品.
Redis集群會有寫操作丟失嗎?為什么?
Redis并不能保證數(shù)據(jù)的強(qiáng)一致性,這意味這在實際中集群在特定的條件下可能會丟失寫操作。
Redis集群之間是如何復(fù)制的?
異步復(fù)制
Redis如何做內(nèi)存優(yōu)化?
盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個散列表里面。比如你的web系統(tǒng)中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設(shè)置單獨的key,而是應(yīng)該把這個用戶的所有信息存儲到一張散列表里面.
Redis回收進(jìn)程如何工作的?
一個客戶端運行了新的命令,添加了新的數(shù)據(jù)。
Redi檢查內(nèi)存使用情況,如果大于maxmemory的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。
Redis回收使用的是什么算法?
LRU算法
Redis有哪些適合的場景?
1)Session共享(單點登錄)
2)頁面緩存
3)隊列
4)排行榜/計數(shù)器
5)發(fā)布/訂閱
最后
小編整理了一份Java核心知識點。覆蓋了Java入門、數(shù)據(jù)類型和運算符、控制語句、Java面向?qū)ο缶幊袒A(chǔ)、進(jìn)階、異常機(jī)制、多線程等大量知識點。加群:219571750 ,即可免費獲??!
干貨視頻,高級架構(gòu)師最新java、spring、Redis、JVM、分布式、高并發(fā)。