溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Redis高頻面試題有哪些

發(fā)布時(shí)間:2021-04-16 10:41:44 來源:億速云 閱讀:147 作者:小新 欄目:關(guān)系型數(shù)據(jù)庫

這篇文章將為大家詳細(xì)講解有關(guān)Redis高頻面試題有哪些,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

什么是Redis


Redis(Remote Dictionary Server) 是一個(gè)使用 C 語言編寫的,開源的(BSD許可)高性能非關(guān)系型(NoSQL)的鍵值對(duì)數(shù)據(jù)庫。

Redis 可以存儲(chǔ)鍵和五種不同類型的值之間的映射。鍵的類型只能為字符串,值支持五種數(shù)據(jù)類型:字符串、列表、集合、散列表、有序集合。

與傳統(tǒng)數(shù)據(jù)庫不同的是 Redis 的數(shù)據(jù)是存在內(nèi)存中的,所以讀寫速度非??欤虼?redis 被廣泛應(yīng)用于緩存方向,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB。另外,Redis 也經(jīng)常用來做分布式鎖。除此之外,Redis 支持事務(wù) 、持久化、LUA腳本、LRU驅(qū)動(dòng)事件、多種集群方案。

Redis有哪些優(yōu)缺點(diǎn)


優(yōu)點(diǎn)

讀寫性能優(yōu)異, Redis能讀的速度是110000次/s,寫的速度是81000次/s。

支持?jǐn)?shù)據(jù)持久化,支持AOF和RDB兩種持久化方式。

支持事務(wù),Redis的所有操作都是原子性的,同時(shí)Redis還支持對(duì)幾個(gè)操作合并后的原子性執(zhí)行。

數(shù)據(jù)結(jié)構(gòu)豐富,除了支持string類型的value外還支持hash、set、zset、list等數(shù)據(jù)結(jié)構(gòu)。

支持主從復(fù)制,主機(jī)會(huì)自動(dòng)將數(shù)據(jù)同步到從機(jī),可以進(jìn)行讀寫分離。

缺點(diǎn)

數(shù)據(jù)庫容量受到物理內(nèi)存的限制,不能用作海量數(shù)據(jù)的高性能讀寫,因此Redis適合的場(chǎng)景主要局限在較小數(shù)據(jù)量的高性能操作和運(yùn)算上。

Redis 不具備自動(dòng)容錯(cuò)和恢復(fù)功能,主機(jī)從機(jī)的宕機(jī)都會(huì)導(dǎo)致前端部分讀寫請(qǐng)求失敗,需要等待機(jī)器重啟或者手動(dòng)切換前端的IP才能恢復(fù)。

主機(jī)宕機(jī),宕機(jī)前有部分?jǐn)?shù)據(jù)未能及時(shí)同步到從機(jī),切換IP后還會(huì)引入數(shù)據(jù)不一致的問題,降低了系統(tǒng)的可用性。

Redis 較難支持在線擴(kuò)容,在集群容量達(dá)到上限時(shí)在線擴(kuò)容會(huì)變得很復(fù)雜。為避免這一問題,運(yùn)維人員在系統(tǒng)上線時(shí)必須確保有足夠的空間,這對(duì)資源造成了很大的浪費(fèi)。

為什么要用緩存,為什么要用 Redis


主要從“高性能”和“高并發(fā)”這兩點(diǎn)來看待這個(gè)問題。

高性能:

假如用戶第一次訪問數(shù)據(jù)庫中的某些數(shù)據(jù)。這個(gè)過程會(huì)比較慢,因?yàn)槭菑挠脖P上讀取的。將該用戶訪問的數(shù)據(jù)存在數(shù)緩存中,這樣下一次再訪問這些數(shù)據(jù)的時(shí)候就可以直接從緩存中獲取了。操作緩存就是直接操作內(nèi)存,所以速度相當(dāng)快。如果數(shù)據(jù)庫中的對(duì)應(yīng)數(shù)據(jù)改變的之后,同步改變緩存中相應(yīng)的數(shù)據(jù)即可!

Redis高頻面試題有哪些

高并發(fā):

直接操作緩存能夠承受的請(qǐng)求是遠(yuǎn)遠(yuǎn)大于直接訪問數(shù)據(jù)庫的,所以我們可以考慮把數(shù)據(jù)庫中的部分?jǐn)?shù)據(jù)轉(zhuǎn)移到緩存中去,這樣用戶的一部分請(qǐng)求會(huì)直接到緩存這里而不用經(jīng)過數(shù)據(jù)庫。

Redis高頻面試題有哪些

為什么要用 Redis 而不用 map/guava 做緩存?


緩存分為本地緩存和分布式緩存。以 Java 為例,使用自帶的 map 或者 guava 實(shí)現(xiàn)的是本地緩存,最主要的特點(diǎn)是輕量以及快速,生命周期隨著 jvm 的銷毀而結(jié)束,并且在多實(shí)例的情況下,每個(gè)實(shí)例都需要各自保存一份緩存,緩存不具有一致性。

使用 redis 或 memcached 之類的稱為分布式緩存,在多實(shí)例的情況下,各實(shí)例共用一份緩存數(shù)據(jù),緩存具有一致性。缺點(diǎn)是需要保持 redis 或 memcached服務(wù)的高可用,整個(gè)程序架構(gòu)上較為復(fù)雜。

Redis為什么這么快


1、完全基于內(nèi)存,絕大部分請(qǐng)求是純粹的內(nèi)存操作,非??焖佟?shù)據(jù)存在內(nèi)存中,類似于 HashMap,HashMap 的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1);

2、數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也簡(jiǎn)單,Redis 中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行設(shè)計(jì)的;

3、采用單線程,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗;

4、使用多路 I/O 復(fù)用模型,非阻塞 IO;

5、使用底層模型不同,它們之間底層實(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)求;

Redis有哪些數(shù)據(jù)類型


Redis主要有5種數(shù)據(jù)類型,包括String,List,Set,Zset,Hash,滿足大部分的使用要求

類型
存儲(chǔ)值
操作
應(yīng)用場(chǎng)景
STRING
字符串、整數(shù)或者浮點(diǎn)數(shù)對(duì)整個(gè)字符串或者字符串的其中一部分執(zhí)行操作;
對(duì)整數(shù)和浮點(diǎn)數(shù)執(zhí)行自增或者自減操作
做簡(jiǎn)單的鍵值對(duì)緩存
LIST
列表從兩端壓入或者彈出元素;
對(duì)單個(gè)或者多個(gè)元素進(jìn)行修剪,只保留一個(gè)范圍內(nèi)的元素
存儲(chǔ)一些列表型的數(shù)據(jù)結(jié)構(gòu),類似粉絲列表、文章的評(píng)論列表之類的數(shù)據(jù)
SET
無序集合
添加、獲取、移除單個(gè)元素;
檢查一個(gè)元素是否存在于集合中;
計(jì)算交集、并集、差集;
從集合里面隨機(jī)獲取元素
交集、并集、差集的操作,比如交集,可以把兩個(gè)人的粉絲列表整一個(gè)交集
HASH
哈希
添加、獲取、移除單個(gè)鍵值對(duì);
獲取所有鍵值對(duì);
檢查某個(gè)鍵是否存在
結(jié)構(gòu)化的數(shù)據(jù),比如一個(gè)對(duì)象
ZSET有序集合
添加、獲取、刪除元素;
根據(jù)分值范圍或者成員來獲取元素;
計(jì)算一個(gè)鍵的排名
去重但可以排序,如獲取排名前幾名的用戶

Redis的應(yīng)用場(chǎng)景


總結(jié)一

1、計(jì)數(shù)器

可以對(duì) String 進(jìn)行自增自減運(yùn)算,從而實(shí)現(xiàn)計(jì)數(shù)器功能。Redis 這種內(nèi)存型數(shù)據(jù)庫的讀寫性能非常高,很適合存儲(chǔ)頻繁讀寫的計(jì)數(shù)量。

2、緩存

將熱點(diǎn)數(shù)據(jù)放到內(nèi)存中,設(shè)置內(nèi)存的最大使用量以及淘汰策略來保證緩存的命中率。

3、會(huì)話緩存

可以使用 Redis 來統(tǒng)一存儲(chǔ)多臺(tái)應(yīng)用服務(wù)器的會(huì)話信息。當(dāng)應(yīng)用服務(wù)器不再存儲(chǔ)用戶的會(huì)話信息,也就不再具有狀態(tài),一個(gè)用戶可以請(qǐng)求任意一個(gè)應(yīng)用服務(wù)器,從而更容易實(shí)現(xiàn)高可用性以及可伸縮性。

4、全頁緩存(FPC)

除基本的會(huì)話token之外,Redis還提供很簡(jiǎn)便的FPC平臺(tái)。以Magento為例,Magento提供一個(gè)插件來使用Redis作為全頁緩存后端。此外,對(duì)WordPress的用戶來說,Pantheon有一個(gè)非常好的插件 wp-redis,這個(gè)插件能幫助你以最快速度加載你曾瀏覽過的頁面。

5、查找表

例如 DNS 記錄就很適合使用 Redis 進(jìn)行存儲(chǔ)。查找表和緩存類似,也是利用了 Redis 快速的查找特性。但是查找表的內(nèi)容不能失效,而緩存的內(nèi)容可以失效,因?yàn)榫彺娌蛔鳛榭煽康臄?shù)據(jù)來源。

6、消息隊(duì)列(發(fā)布/訂閱功能)

List 是一個(gè)雙向鏈表,可以通過 lpush 和 rpop 寫入和讀取消息。不過最好使用 Kafka、RabbitMQ 等消息中間件。

7、分布式鎖實(shí)現(xiàn)

在分布式場(chǎng)景下,無法使用單機(jī)環(huán)境下的鎖來對(duì)多個(gè)節(jié)點(diǎn)上的進(jìn)程進(jìn)行同步??梢允褂?Redis 自帶的 SETNX 命令實(shí)現(xiàn)分布式鎖,除此之外,還可以使用官方提供的 RedLock 分布式鎖實(shí)現(xiàn)。

8、其它

Set 可以實(shí)現(xiàn)交集、并集等操作,從而實(shí)現(xiàn)共同好友等功能。ZSet 可以實(shí)現(xiàn)有序性操作,從而實(shí)現(xiàn)排行榜等功能。

總結(jié)二

Redis相比其他緩存,有一個(gè)非常大的優(yōu)勢(shì),就是支持多種數(shù)據(jù)類型。

數(shù)據(jù)類型說明string字符串,最簡(jiǎn)單的k-v存儲(chǔ)hashhash格式,value為field和value,適合ID-Detail這樣的場(chǎng)景。list簡(jiǎn)單的list,順序列表,支持首位或者末尾插入數(shù)據(jù)set無序list,查找速度快,適合交集、并集、差集處理sorted set有序的set

其實(shí),通過上面的數(shù)據(jù)類型的特性,基本就能想到合適的應(yīng)用場(chǎng)景了。

string——適合最簡(jiǎn)單的k-v存儲(chǔ),類似于memcached的存儲(chǔ)結(jié)構(gòu),短信驗(yàn)證碼,配置信息等,就用這種類型來存儲(chǔ)。

hash——一般key為ID或者唯一標(biāo)示,value對(duì)應(yīng)的就是詳情了。如商品詳情,個(gè)人信息詳情,新聞詳情等。

list——因?yàn)閘ist是有序的,比較適合存儲(chǔ)一些有序且數(shù)據(jù)相對(duì)固定的數(shù)據(jù)。如省市區(qū)表、字典表等。因?yàn)閘ist是有序的,適合根據(jù)寫入的時(shí)間來排序,如:最新的熱點(diǎn)新聞,消息隊(duì)列等。

set——可以簡(jiǎn)單的理解為ID-List的模式,如微博中一個(gè)人有哪些好友,set最牛的地方在于,可以對(duì)兩個(gè)set提供交集、并集、差集操作。例如:查找兩個(gè)人共同的好友等。

Sorted Set——是set的增強(qiáng)版本,增加了一個(gè)score參數(shù),自動(dòng)會(huì)根據(jù)score的值進(jìn)行排序。比較適合類似于top 10等不根據(jù)插入的時(shí)間來排序的數(shù)據(jù)。

如上所述,雖然Redis不像關(guān)系數(shù)據(jù)庫那么復(fù)雜的數(shù)據(jù)結(jié)構(gòu),但是,也能適合很多場(chǎng)景,比一般的緩存數(shù)據(jù)結(jié)構(gòu)要多。了解每種數(shù)據(jù)結(jié)構(gòu)適合的業(yè)務(wù)場(chǎng)景,不僅有利于提升開發(fā)效率,也能有效利用Redis的性能。

什么是Redis持久化?


持久化就是把內(nèi)存的數(shù)據(jù)寫到磁盤中去,防止服務(wù)宕機(jī)了內(nèi)存數(shù)據(jù)丟失。

Redis 的持久化機(jī)制是什么?各自的優(yōu)缺點(diǎn)?


Redis 提供兩種持久化機(jī)制 RDB(默認(rèn)) 和 AOF 機(jī)制;

RDB:是Redis DataBase縮寫快照

RDB是Redis默認(rèn)的持久化方式。按照一定的時(shí)間將內(nèi)存的數(shù)據(jù)以快照的形式保存到硬盤中,對(duì)應(yīng)產(chǎn)生的數(shù)據(jù)文件為dump.rdb。通過配置文件中的save參數(shù)來定義快照的周期。

Redis高頻面試題有哪些

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

1、只有一個(gè)文件 dump.rdb,方便持久化。

2、容災(zāi)性好,一個(gè)文件可以保存到安全的磁盤。

3、性能最大化,fork 子進(jìn)程來完成寫操作,讓主進(jìn)程繼續(xù)處理命令,所以是 IO 最大化。使用單獨(dú)子進(jìn)程來進(jìn)行持久化,主進(jìn)程不會(huì)進(jìn)行任何 IO 操作,保證了 redis 的高性能。

4、相對(duì)于數(shù)據(jù)集大時(shí),比 AOF 的啟動(dòng)效率更高。

缺點(diǎn):

1、數(shù)據(jù)安全性低。RDB 是間隔一段時(shí)間進(jìn)行持久化,如果持久化之間 redis 發(fā)生故障,會(huì)發(fā)生數(shù)據(jù)丟失。所以這種方式更適合數(shù)據(jù)要求不嚴(yán)謹(jǐn)?shù)臅r(shí)候)

2、AOF(Append-only file)持久化方式:是指所有的命令行記錄以 redis 命令請(qǐng) 求協(xié)議的格式完全持久化存儲(chǔ))保存為 aof 文件。

AOF:持久化


AOF持久化(即Append Only File持久化),則是將Redis執(zhí)行的每次寫命令記錄到單獨(dú)的日志文件中,當(dāng)重啟Redis會(huì)重新將持久化的日志中文件恢復(fù)數(shù)據(jù)。

當(dāng)兩種方式同時(shí)開啟時(shí),數(shù)據(jù)恢復(fù)Redis會(huì)優(yōu)先選擇AOF恢復(fù)。

Redis高頻面試題有哪些

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

1、數(shù)據(jù)安全,aof 持久化可以配置 appendfsync 屬性,有 always,每進(jìn)行一次 命令操作就記錄到 aof 文件中一次。

2、通過 append 模式寫文件,即使中途服務(wù)器宕機(jī),可以通過 redis-check-aof 工具解決數(shù)據(jù)一致性問題。

3、AOF 機(jī)制的 rewrite 模式。AOF 文件沒被 rewrite 之前(文件過大時(shí)會(huì)對(duì)命令 進(jìn)行合并重寫),可以刪除其中的某些命令(比如誤操作的 flushall)

缺點(diǎn):

1、AOF 文件比 RDB 文件大,且恢復(fù)速度慢。

2、數(shù)據(jù)集大的時(shí)候,比 rdb 啟動(dòng)效率低。

優(yōu)缺點(diǎn)是什么?

  • AOF文件比RDB更新頻率高,優(yōu)先使用AOF還原數(shù)據(jù)

  • AOF比RDB更安全也更大

  • RDB性能比AOF好

  • 如果兩個(gè)都配了優(yōu)先加載AOF

如何選擇合適的持久化方式?


一般來說, 如果想達(dá)到足以媲美PostgreSQL的數(shù)據(jù)安全性,你應(yīng)該同時(shí)使用兩種持久化功能。在這種情況下,當(dāng) Redis 重啟的時(shí)候會(huì)優(yōu)先載入AOF文件來恢復(fù)原始的數(shù)據(jù),因?yàn)樵谕ǔG闆r下AOF文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集要完整。

如果你非常關(guān)心你的數(shù)據(jù), 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失,那么你可以只使用RDB持久化。

有很多用戶都只使用AOF持久化,但并不推薦這種方式,因?yàn)槎〞r(shí)生成RDB快照(snapshot)非常便于進(jìn)行數(shù)據(jù)庫備份, 并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比AOF恢復(fù)的速度要快,除此之外,使用RDB還可以避免AOF程序的bug。

如果你只希望你的數(shù)據(jù)在服務(wù)器運(yùn)行的時(shí)候存在,你也可以不使用任何持久化方式。

Redis持久化數(shù)據(jù)和緩存怎么做擴(kuò)容?


如果Redis被當(dāng)做緩存使用,使用一致性哈希實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容縮容。

如果Redis被當(dāng)做一個(gè)持久化存儲(chǔ)使用,必須使用固定的keys-to-nodes映射關(guān)系,節(jié)點(diǎn)的數(shù)量一旦確定不能變化。否則的話(即Redis節(jié)點(diǎn)需要?jiǎng)討B(tài)變化的情況),必須使用可以在運(yùn)行時(shí)進(jìn)行數(shù)據(jù)再平衡的一套系統(tǒng),而當(dāng)前只有Redis集群可以做到這樣。

Redis的過期鍵的刪除策略


我們都知道,Redis是key-value數(shù)據(jù)庫,我們可以設(shè)置Redis中緩存的key的過期時(shí)間。Redis的過期策略就是指當(dāng)Redis中緩存的key過期了,Redis如何處理。

過期策略通常有以下三種:

定時(shí)過期:每個(gè)設(shè)置過期時(shí)間的key都需要?jiǎng)?chuàng)建一個(gè)定時(shí)器,到過期時(shí)間就會(huì)立即清除。該策略可以立即清除過期的數(shù)據(jù),對(duì)內(nèi)存很友好;但是會(huì)占用大量的CPU資源去處理過期的數(shù)據(jù),從而影響緩存的響應(yīng)時(shí)間和吞吐量。

惰性過期:只有當(dāng)訪問一個(gè)key時(shí),才會(huì)判斷該key是否已過期,過期則清除。該策略可以最大化地節(jié)省CPU資源,卻對(duì)內(nèi)存非常不友好。極端情況可能出現(xiàn)大量的過期key沒有再次被訪問,從而不會(huì)被清除,占用大量?jī)?nèi)存。

定期過期:每隔一定的時(shí)間,會(huì)掃描一定數(shù)量的數(shù)據(jù)庫的expires字典中一定數(shù)量的key,并清除其中已過期的key。該策略是前兩者的一個(gè)折中方案。通過調(diào)整定時(shí)掃描的時(shí)間間隔和每次掃描的限定耗時(shí),可以在不同情況下使得CPU和內(nèi)存資源達(dá)到最優(yōu)的平衡效果。

(expires字典會(huì)保存所有設(shè)置了過期時(shí)間的key的過期時(shí)間數(shù)據(jù),其中,key是指向鍵空間中的某個(gè)鍵的指針,value是該鍵的毫秒精度的UNIX時(shí)間戳表示的過期時(shí)間。鍵空間是指該Redis集群中保存的所有鍵。)

Redis中同時(shí)使用了惰性過期和定期過期兩種過期策略。

Redis key的過期時(shí)間和永久有效分別怎么設(shè)置?

EXPIRE和PERSIST命令。

我們知道通過expire來設(shè)置key 的過期時(shí)間,那么對(duì)過期的數(shù)據(jù)怎么處理呢?


除了緩存服務(wù)器自帶的緩存失效策略之外(Redis默認(rèn)的有6中策略可供選擇),我們還可以根據(jù)具體的業(yè)務(wù)需求進(jìn)行自定義的緩存淘汰,常見的策略有兩種:

1、定時(shí)去清理過期的緩存;

2、當(dāng)有用戶請(qǐng)求過來時(shí),再判斷這個(gè)請(qǐng)求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存。

兩者各有優(yōu)劣,第一種的缺點(diǎn)是維護(hù)大量緩存的key是比較麻煩的,第二種的缺點(diǎn)就是每次用戶請(qǐng)求過來都要判斷緩存失效,邏輯相對(duì)比較復(fù)雜!具體用哪種方案,大家可以根據(jù)自己的應(yīng)用場(chǎng)景來權(quán)衡。

MySQL里有2000w數(shù)據(jù),redis中只存20w的數(shù)據(jù),如何保證redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)?


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

Redis的內(nèi)存淘汰策略有哪些


Redis的內(nèi)存淘汰策略是指在Redis的用于緩存的內(nèi)存不足時(shí),怎么處理需要新寫入且需要申請(qǐng)額外空間的數(shù)據(jù)。

1、全局的鍵空間選擇性移除

noeviction:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),新寫入操作會(huì)報(bào)錯(cuò)。

allkeys-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在鍵空間中,移除最近最少使用的key。(這個(gè)是最常用的)

allkeys-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在鍵空間中,隨機(jī)移除某個(gè)key。

2、設(shè)置過期時(shí)間的鍵空間選擇性移除

volatile-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的鍵空間中,移除最近最少使用的key。

volatile-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的鍵空間中,隨機(jī)移除某個(gè)key。

volatile-ttl:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的鍵空間中,有更早過期時(shí)間的key優(yōu)先移除。

總結(jié)

Redis的內(nèi)存淘汰策略的選取并不會(huì)影響過期的key的處理。內(nèi)存淘汰策略用于處理內(nèi)存不足時(shí)的需要申請(qǐng)額外空間的數(shù)據(jù);過期策略用于處理過期的緩存數(shù)據(jù)。

Redis主要消耗什么物理資源?


內(nèi)存。

Redis的內(nèi)存用完了會(huì)發(fā)生什么?


如果達(dá)到設(shè)置的上限,Redis的寫命令會(huì)返回錯(cuò)誤信息(但是讀命令還可以正常返回。)或者你可以配置內(nèi)存淘汰機(jī)制,當(dāng)Redis達(dá)到內(nèi)存上限時(shí)會(huì)沖刷掉舊的內(nèi)容。

Redis如何做內(nèi)存優(yōu)化?


可以好好利用Hash,list,sorted set,set等集合類型數(shù)據(jù),因?yàn)橥ǔG闆r下很多小的Key-Value可以用更緊湊的方式存放到一起。盡可能使用散列表(hashes),散列表(是說散列表里面存儲(chǔ)的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面。比如你的web系統(tǒng)中有一個(gè)用戶對(duì)象,不要為這個(gè)用戶的名稱,姓氏,郵箱,密碼設(shè)置單獨(dú)的key,而是應(yīng)該把這個(gè)用戶的所有信息存儲(chǔ)到一張散列表里面。

Redis線程模型


Redis基于Reactor模式開發(fā)了網(wǎng)絡(luò)事件處理器,這個(gè)處理器被稱為文件事件處理器(file event handler)。它的組成結(jié)構(gòu)為4部分:多個(gè)套接字、IO多路復(fù)用程序、文件事件分派器、事件處理器。因?yàn)槲募录峙善麝?duì)列的消費(fèi)是單線程的,所以Redis才叫單線程模型。

1、文件事件處理器使用 I/O 多路復(fù)用(multiplexing)程序來同時(shí)監(jiān)聽多個(gè)套接字, 并根據(jù)套接字目前執(zhí)行的任務(wù)來為套接字關(guān)聯(lián)不同的事件處理器。

2、當(dāng)被監(jiān)聽的套接字準(zhǔn)備好執(zhí)行連接應(yīng)答(accept)、讀取(read)、寫入(write)、關(guān)閉(close)等操作時(shí), 與操作相對(duì)應(yīng)的文件事件就會(huì)產(chǎn)生, 這時(shí)文件事件處理器就會(huì)調(diào)用套接字之前關(guān)聯(lián)好的事件處理器來處理這些事件。

雖然文件事件處理器以單線程方式運(yùn)行, 但通過使用 I/O 多路復(fù)用程序來監(jiān)聽多個(gè)套接字, 文件事件處理器既實(shí)現(xiàn)了高性能的網(wǎng)絡(luò)通信模型, 又可以很好地與 redis 服務(wù)器中其他同樣以單線程方式運(yùn)行的模塊進(jìn)行對(duì)接, 這保持了 Redis 內(nèi)部單線程設(shè)計(jì)的簡(jiǎn)單性。

什么是事務(wù)?


事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會(huì)序列化、按順序地執(zhí)行。事務(wù)在執(zhí)行的過程中,不會(huì)被其他客戶端發(fā)送來的命令請(qǐng)求所打斷。

事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行。

Redis事務(wù)的概念

Redis 事務(wù)的本質(zhì)是通過MULTI、EXEC、WATCH等一組命令的集合。事務(wù)支持一次執(zhí)行多個(gè)命令,一個(gè)事務(wù)中所有命令都會(huì)被序列化。在事務(wù)執(zhí)行過程,會(huì)按照順序串行化執(zhí)行隊(duì)列中的命令,其他客戶端提交的命令請(qǐng)求不會(huì)插入到事務(wù)執(zhí)行命令序列中。

總結(jié)說:redis事務(wù)就是一次性、順序性、排他性的執(zhí)行一個(gè)隊(duì)列中的一系列命令。

Redis事務(wù)的三個(gè)階段

1、事務(wù)開始 MULTI

2、命令入隊(duì)

3、事務(wù)執(zhí)行 EXEC

事務(wù)執(zhí)行過程中,如果服務(wù)端收到有EXEC、DISCARD、WATCH、MULTI之外的請(qǐng)求,將會(huì)把請(qǐng)求放入隊(duì)列中排隊(duì)

Redis事務(wù)相關(guān)命令

Redis事務(wù)功能是通過MULTI、EXEC、DISCARD和WATCH 四個(gè)原語實(shí)現(xiàn)的

Redis會(huì)將一個(gè)事務(wù)中的所有命令序列化,然后按順序執(zhí)行。

1、redis 不支持回滾,“Redis 在事務(wù)失敗時(shí)不進(jìn)行回滾,而是繼續(xù)執(zhí)行余下的命令”, 所以 Redis 的內(nèi)部可以保持簡(jiǎn)單且快速。

2、如果在一個(gè)事務(wù)中的命令出現(xiàn)錯(cuò)誤,那么所有的命令都不會(huì)執(zhí)行;

3、如果在一個(gè)事務(wù)中出現(xiàn)運(yùn)行錯(cuò)誤,那么正確的命令會(huì)被執(zhí)行。

WATCH 命令是一個(gè)樂觀鎖,可以為 Redis 事務(wù)提供 check-and-set (CAS)行為。可以監(jiān)控一個(gè)或多個(gè)鍵,一旦其中有一個(gè)鍵被修改(或刪除),之后的事務(wù)就不會(huì)執(zhí)行,監(jiān)控一直持續(xù)到EXEC命令。

MULTI命令用于開啟一個(gè)事務(wù),它總是返回OK。MULTI執(zhí)行之后,客戶端可以繼續(xù)向服務(wù)器發(fā)送任意多條命令,這些命令不會(huì)立即被執(zhí)行,而是被放到一個(gè)隊(duì)列中,當(dāng)EXEC命令被調(diào)用時(shí),所有隊(duì)列中的命令才會(huì)被執(zhí)行。

EXEC:執(zhí)行所有事務(wù)塊內(nèi)的命令。返回事務(wù)塊內(nèi)所有命令的返回值,按命令執(zhí)行的先后順序排列。當(dāng)操作被打斷時(shí),返回空值 nil 。

通過調(diào)用DISCARD,客戶端可以清空事務(wù)隊(duì)列,并放棄執(zhí)行事務(wù), 并且客戶端會(huì)從事務(wù)狀態(tài)中退出。

UNWATCH命令可以取消watch對(duì)所有key的監(jiān)控。

事務(wù)管理(ACID)概述

  • 原子性(Atomicity)

    原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。

  • 一致性(Consistency)

    事務(wù)前后數(shù)據(jù)的完整性必須保持一致。

  • 隔離性(Isolation)

    多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行。

  • 持久性(Durability)

    持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對(duì)其有任何影響。

Redis的事務(wù)總是具有ACID中的一致性和隔離性,其他特性是不支持的。當(dāng)服務(wù)器運(yùn)行在AOF持久化模式下,并且appendfsync選項(xiàng)的值為always時(shí),事務(wù)也具有耐久性。

Redis事務(wù)支持隔離性嗎


Redis 是單進(jìn)程程序,并且它保證在執(zhí)行事務(wù)時(shí),不會(huì)對(duì)事務(wù)進(jìn)行中斷,事務(wù)可以運(yùn)行直到執(zhí)行完所有事務(wù)隊(duì)列中的命令為止。因此,Redis 的事務(wù)是總是帶有隔離性的。

Redis事務(wù)保證原子性嗎,支持回滾嗎


Redis中,單條命令是原子性執(zhí)行的,但事務(wù)不保證原子性,且沒有回滾。事務(wù)中任意命令執(zhí)行失敗,其余的命令仍會(huì)被執(zhí)行。

Redis事務(wù)其他實(shí)現(xiàn)


  • 基于Lua腳本,Redis可以保證腳本內(nèi)的命令一次性、按順序地執(zhí)行,其同時(shí)也不提供事務(wù)運(yùn)行錯(cuò)誤的回滾,執(zhí)行過程中如果部分命令運(yùn)行錯(cuò)誤,剩下的命令還是會(huì)繼續(xù)運(yùn)。

  • 基于中間標(biāo)記變量,通過另外的標(biāo)記變量來標(biāo)識(shí)事務(wù)是否執(zhí)行完成,讀取數(shù)據(jù)時(shí)先讀取該標(biāo)記變量判斷是否事務(wù)執(zhí)行完成。但這樣會(huì)需要額外寫代碼實(shí)現(xiàn),比較繁瑣。

哨兵模式


Redis高頻面試題有哪些

哨兵的介紹

sentinel,中文名是哨兵。哨兵是 redis 集群機(jī)構(gòu)中非常重要的一個(gè)組件,主要有以下功能:

集群監(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é)同工作。

1、故障轉(zhuǎn)移時(shí),判斷一個(gè) master node 是否宕機(jī)了,需要大部分的哨兵都同意才行,涉及到了分布式選舉的問題。

2、即使部分哨兵節(jié)點(diǎn)掛掉了,哨兵集群還是能正常工作的,因?yàn)槿绻粋€(gè)作為高可用機(jī)制重要組成部分的故障轉(zhuǎn)移系統(tǒng)本身是單點(diǎn)的,那就很坑爹了。

哨兵的核心知識(shí)

1、哨兵至少需要 3 個(gè)實(shí)例,來保證自己的健壯性。

2、哨兵 + redis 主從的部署架構(gòu),是不保證數(shù)據(jù)零丟失的,只能保證 redis 集群的高可用性。

3、對(duì)于哨兵 + redis 主從這種復(fù)雜的部署架構(gòu),盡量在測(cè)試環(huán)境和生產(chǎn)環(huán)境,都進(jìn)行充足的測(cè)試和演練。

官方Redis Cluster 方案(服務(wù)端路由查詢)

Redis高頻面試題有哪些

redis 集群模式的工作原理能說一下么?在集群模式下,redis 的 key 是如何尋址的?分布式尋址都有哪些算法?了解一致性 hash 算法嗎?

簡(jiǎn)介

Redis Cluster是一種服務(wù)端Sharding技術(shù),3.0版本開始正式提供。Redis Cluster并沒有使用一致性hash,而是采用slot(槽)的概念,一共分成16384個(gè)槽。將請(qǐng)求發(fā)送到任意節(jié)點(diǎn),接收到請(qǐng)求的節(jié)點(diǎn)會(huì)將查詢請(qǐng)求發(fā)送到正確的節(jié)點(diǎn)上執(zhí)行

方案說明

1、通過哈希的方式,將數(shù)據(jù)分片,每個(gè)節(jié)點(diǎn)均分存儲(chǔ)一定哈希槽(哈希值)區(qū)間的數(shù)據(jù),默認(rèn)分配了16384 個(gè)槽位

2、每份數(shù)據(jù)分片會(huì)存儲(chǔ)在多個(gè)互為主從的多節(jié)點(diǎn)上

3、數(shù)據(jù)寫入先寫主節(jié)點(diǎn),再同步到從節(jié)點(diǎn)(支持配置為阻塞同步)

4、同一分片多個(gè)節(jié)點(diǎn)間的數(shù)據(jù)不保持一致性

5、讀取數(shù)據(jù)時(shí),當(dāng)客戶端操作的key沒有分配在該節(jié)點(diǎn)上時(shí),redis會(huì)返回轉(zhuǎn)向指令,指向正確的節(jié)點(diǎn)

6、擴(kuò)容時(shí)時(shí)需要需要把舊節(jié)點(diǎn)的數(shù)據(jù)遷移一部分到新節(jié)點(diǎn)

在 redis cluster 架構(gòu)下,每個(gè) redis 要放開兩個(gè)端口號(hào),比如一個(gè)是 6379,另外一個(gè)就是 加1w 的端口號(hào),比如 16379。

16379 端口號(hào)是用來進(jìn)行節(jié)點(diǎn)間通信的,也就是 cluster bus 的東西,cluster bus 的通信,用來進(jìn)行故障檢測(cè)、配置更新、故障轉(zhuǎn)移授權(quán)。cluster bus 用了另外一種二進(jìn)制的協(xié)議,gossip 協(xié)議,用于節(jié)點(diǎn)間進(jìn)行高效的數(shù)據(jù)交換,占用更少的網(wǎng)絡(luò)帶寬和處理時(shí)間。

節(jié)點(diǎn)間的內(nèi)部通信機(jī)制

基本通信原理

集群元數(shù)據(jù)的維護(hù)有兩種方式:集中式、Gossip 協(xié)議。redis cluster 節(jié)點(diǎn)間采用 gossip 協(xié)議進(jìn)行通信。

分布式尋址算法

  • hash 算法(大量緩存重建)

  • 一致性 hash 算法(自動(dòng)緩存遷移)+ 虛擬節(jié)點(diǎn)(自動(dòng)負(fù)載均衡

  • redis cluster 的 hash slot 算法

優(yōu)點(diǎn)

1、無中心架構(gòu),支持動(dòng)態(tài)擴(kuò)容,對(duì)業(yè)務(wù)透明

2、具備Sentinel的監(jiān)控和自動(dòng)Failover(故障轉(zhuǎn)移)能力

3、客戶端不需要連接集群所有節(jié)點(diǎn),連接集群中任何一個(gè)可用節(jié)點(diǎn)即可

4、高性能,客戶端直連redis服務(wù),免去了proxy代理的損耗

缺點(diǎn)

1、運(yùn)維也很復(fù)雜,數(shù)據(jù)遷移需要人工干預(yù)

2、只能使用0號(hào)數(shù)據(jù)庫

3、不支持批量操作(pipeline管道操作)

4、分布式邏輯和存儲(chǔ)模塊耦合等

基于客戶端分配


Redis高頻面試題有哪些

簡(jiǎn)介

Redis Sharding是Redis Cluster出來之前,業(yè)界普遍使用的多Redis實(shí)例集群方法。其主要思想是采用哈希算法將Redis數(shù)據(jù)的key進(jìn)行散列,通過hash函數(shù),特定的key會(huì)映射到特定的Redis節(jié)點(diǎn)上。Java redis客戶端驅(qū)動(dòng)jedis,支持Redis Sharding功能,即ShardedJedis以及結(jié)合緩存池的ShardedJedisPool

優(yōu)點(diǎn)

優(yōu)勢(shì)在于非常簡(jiǎn)單,服務(wù)端的Redis實(shí)例彼此獨(dú)立,相互無關(guān)聯(lián),每個(gè)Redis實(shí)例像單服務(wù)器一樣運(yùn)行,非常容易線性擴(kuò)展,系統(tǒng)的靈活性很強(qiáng)

缺點(diǎn)

1、由于sharding處理放到客戶端,規(guī)模進(jìn)一步擴(kuò)大時(shí)給運(yùn)維帶來挑戰(zhàn)。

2、客戶端sharding不支持動(dòng)態(tài)增刪節(jié)點(diǎn)。服務(wù)端Redis實(shí)例群拓?fù)浣Y(jié)構(gòu)有變化時(shí),每個(gè)客戶端都需要更新調(diào)整。連接不能共享,當(dāng)應(yīng)用規(guī)模增大時(shí),資源浪費(fèi)制約優(yōu)化

基于代理服務(wù)器分片


Redis高頻面試題有哪些

簡(jiǎn)介

客戶端發(fā)送請(qǐng)求到一個(gè)代理組件,代理解析客戶端的數(shù)據(jù),并將請(qǐng)求轉(zhuǎn)發(fā)至正確的節(jié)點(diǎn),最后將結(jié)果回復(fù)給客戶端

特征

1、透明接入,業(yè)務(wù)程序不用關(guān)心后端Redis實(shí)例,切換成本低

2、Proxy 的邏輯和存儲(chǔ)的邏輯是隔離的

3、代理層多了一次轉(zhuǎn)發(fā),性能有所損耗

業(yè)界開源方案

1、Twtter開源的Twemproxy

2、豌豆莢開源的Codis

Redis 主從架構(gòu)


單機(jī)的 redis,能夠承載的 QPS 大概就在上萬到幾萬不等。對(duì)于緩存來說,一般都是用來支撐讀高并發(fā)的。因此架構(gòu)做成主從(master-slave)架構(gòu),一主多從,主負(fù)責(zé)寫,并且將數(shù)據(jù)復(fù)制到其它的 slave 節(jié)點(diǎn),從節(jié)點(diǎn)負(fù)責(zé)讀。所有的讀請(qǐng)求全部走從節(jié)點(diǎn)。這樣也可以很輕松實(shí)現(xiàn)水平擴(kuò)容,支撐讀高并發(fā)。

Redis高頻面試題有哪些

redis replication -> 主從架構(gòu) -> 讀寫分離 -> 水平擴(kuò)容支撐讀高并發(fā)

redis replication 的核心機(jī)制

1、redis 采用異步方式復(fù)制數(shù)據(jù)到 slave 節(jié)點(diǎn),不過 redis2.8 開始,slave node 會(huì)周期性地確認(rèn)自己每次復(fù)制的數(shù)據(jù)量;

2、一個(gè) master node 是可以配置多個(gè) slave node 的;

3、slave node 也可以連接其他的 slave node;

4、slave node 做復(fù)制的時(shí)候,不會(huì) block master node 的正常工作;

5、slave node 在做復(fù)制的時(shí)候,也不會(huì) block 對(duì)自己的查詢操作,它會(huì)用舊的數(shù)據(jù)集來提供服務(wù);但是復(fù)制完成的時(shí)候,需要?jiǎng)h除舊數(shù)據(jù)集,加載新數(shù)據(jù)集,這個(gè)時(shí)候就會(huì)暫停對(duì)外服務(wù)了;

6、slave node 主要用來進(jìn)行橫向擴(kuò)容,做讀寫分離,擴(kuò)容的 slave node 可以提高讀的吞吐量。

注意,如果采用了主從架構(gòu),那么建議必須開啟 master node 的持久化,不建議用 slave node 作為 master node 的數(shù)據(jù)熱備,因?yàn)槟菢拥脑?,如果你關(guān)掉 master 的持久化,可能在 master 宕機(jī)重啟的時(shí)候數(shù)據(jù)是空的,然后可能一經(jīng)過復(fù)制, slave node 的數(shù)據(jù)也丟了。

另外,master 的各種備份方案,也需要做。萬一本地的所有文件丟失了,從備份中挑選一份 rdb 去恢復(fù) master,這樣才能確保啟動(dòng)的時(shí)候,是有數(shù)據(jù)的,即使采用了后續(xù)講解的高可用機(jī)制,slave node 可以自動(dòng)接管 master node,但也可能 sentinel 還沒檢測(cè)到 master failure,master node 就自動(dòng)重啟了,還是可能導(dǎo)致上面所有的 slave node 數(shù)據(jù)被清空。

redis 主從復(fù)制的核心原理

當(dāng)啟動(dòng)一個(gè) slave node 的時(shí)候,它會(huì)發(fā)送一個(gè) PSYNC 命令給 master node。

如果這是 slave node 初次連接到 master node,那么會(huì)觸發(fā)一次 full resynchronization 全量復(fù)制。此時(shí) master 會(huì)啟動(dòng)一個(gè)后臺(tái)線程,開始生成一份 RDB 快照文件,

同時(shí)還會(huì)將從客戶端 client 新收到的所有寫命令緩存在內(nèi)存中。RDB 文件生成完畢后, master 會(huì)將這個(gè) RDB 發(fā)送給 slave,slave 會(huì)先寫入本地磁盤,然后再從本地磁盤加載到內(nèi)存中,

接著 master 會(huì)將內(nèi)存中緩存的寫命令發(fā)送到 slave,slave 也會(huì)同步這些數(shù)據(jù)。

slave node 如果跟 master node 有網(wǎng)絡(luò)故障,斷開了連接,會(huì)自動(dòng)重連,連接之后 master node 僅會(huì)復(fù)制給 slave 部分缺少的數(shù)據(jù)。

Redis高頻面試題有哪些

過程原理

1、當(dāng)從庫和主庫建立MS關(guān)系后,會(huì)向主數(shù)據(jù)庫發(fā)送SYNC命令

2、主庫接收到SYNC命令后會(huì)開始在后臺(tái)保存快照(RDB持久化過程),并將期間接收到的寫命令緩存起來

3、當(dāng)快照完成后,主Redis會(huì)將快照文件和所有緩存的寫命令發(fā)送給從Redis

4、從Redis接收到后,會(huì)載入快照文件并且執(zhí)行收到的緩存的命令

5、之后,主Redis每當(dāng)接收到寫命令時(shí)就會(huì)將命令發(fā)送從Redis,從而保證數(shù)據(jù)的一致

缺點(diǎn)

所有的slave節(jié)點(diǎn)數(shù)據(jù)的復(fù)制和同步都由master節(jié)點(diǎn)來處理,會(huì)照成master節(jié)點(diǎn)壓力太大,使用主從從結(jié)構(gòu)來解決

Redis集群的主從復(fù)制模型是怎樣的?

為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,每個(gè)節(jié)點(diǎn)都會(huì)有N-1個(gè)復(fù)制品

生產(chǎn)環(huán)境中的 redis 是怎么部署的?


redis cluster,10 臺(tái)機(jī)器,5 臺(tái)機(jī)器部署了 redis 主實(shí)例,另外 5 臺(tái)機(jī)器部署了 redis 的從實(shí)例,每個(gè)主實(shí)例掛了一個(gè)從實(shí)例,5 個(gè)節(jié)點(diǎn)對(duì)外提供讀寫服務(wù),每個(gè)節(jié)點(diǎn)的讀寫高峰qps可能可以達(dá)到每秒 5 萬,5 臺(tái)機(jī)器最多是 25 萬讀寫請(qǐng)求/s。

機(jī)器是什么配置?32G 內(nèi)存+ 8 核 CPU + 1T 磁盤,但是分配給 redis 進(jìn)程的是10g內(nèi)存,一般線上生產(chǎn)環(huán)境,redis 的內(nèi)存盡量不要超過 10g,超過 10g 可能會(huì)有問題。

5 臺(tái)機(jī)器對(duì)外提供讀寫,一共有 50g 內(nèi)存。

因?yàn)槊總€(gè)主實(shí)例都掛了一個(gè)從實(shí)例,所以是高可用的,任何一個(gè)主實(shí)例宕機(jī),都會(huì)自動(dòng)故障遷移,redis 從實(shí)例會(huì)自動(dòng)變成主實(shí)例繼續(xù)提供讀寫服務(wù)。

你往內(nèi)存里寫的是什么數(shù)據(jù)?每條數(shù)據(jù)的大小是多少?商品數(shù)據(jù),每條數(shù)據(jù)是 10kb。100 條數(shù)據(jù)是 1mb,10 萬條數(shù)據(jù)是 1g。常駐內(nèi)存的是 200 萬條商品數(shù)據(jù),占用內(nèi)存是 20g,僅僅不到總內(nèi)存的 50%。目前高峰期每秒就是 3500 左右的請(qǐng)求量。

其實(shí)大型的公司,會(huì)有基礎(chǔ)架構(gòu)的 team 負(fù)責(zé)緩存集群的運(yùn)維。

說說Redis哈希槽的概念?


Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個(gè)哈希槽,每個(gè)key通過CRC16校驗(yàn)后對(duì)16384取模來決定放置哪個(gè)槽,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分hash槽。

Redis集群會(huì)有寫操作丟失嗎?為什么?


Redis并不能保證數(shù)據(jù)的強(qiáng)一致性,這意味這在實(shí)際中集群在特定的條件下可能會(huì)丟失寫操作。

Redis集群之間是如何復(fù)制的?


異步復(fù)制

Redis集群最大節(jié)點(diǎn)個(gè)數(shù)是多少?


16384個(gè)

Redis集群如何選擇數(shù)據(jù)庫?


Redis集群目前無法做數(shù)據(jù)庫選擇,默認(rèn)在0數(shù)據(jù)庫。

Redis是單線程的,如何提高多核CPU的利用率?


可以在同一個(gè)服務(wù)器部署多個(gè)Redis的實(shí)例,并把他們當(dāng)作不同的服務(wù)器來使用,在某些時(shí)候,無論如何一個(gè)服務(wù)器是不夠的, 所以,如果你想使用多個(gè)CPU,你可以考慮一下分片(shard)。

為什么要做Redis分區(qū)?


分區(qū)可以讓Redis管理更大的內(nèi)存,Redis將可以使用所有機(jī)器的內(nèi)存。如果沒有分區(qū),你最多只能使用一臺(tái)機(jī)器的內(nèi)存。分區(qū)使Redis的計(jì)算能力通過簡(jiǎn)單地增加計(jì)算機(jī)得到成倍提升,Redis的網(wǎng)絡(luò)帶寬也會(huì)隨著計(jì)算機(jī)和網(wǎng)卡的增加而成倍增長。

你知道有哪些Redis分區(qū)實(shí)現(xiàn)方案?


1、客戶端分區(qū)就是在客戶端就已經(jīng)決定數(shù)據(jù)會(huì)被存儲(chǔ)到哪個(gè)redis節(jié)點(diǎn)或者從哪個(gè)redis節(jié)點(diǎn)讀取。大多數(shù)客戶端已經(jīng)實(shí)現(xiàn)了客戶端分區(qū)。

2、代理分區(qū) 意味著客戶端將請(qǐng)求發(fā)送給代理,然后代理決定去哪個(gè)節(jié)點(diǎn)寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請(qǐng)求哪些Redis實(shí)例,然后根據(jù)Redis的響應(yīng)結(jié)果返回給客戶端。redis和memcached的一種代理實(shí)現(xiàn)就是Twemproxy。

3、查詢路由(Query routing) 的意思是客戶端隨機(jī)地請(qǐng)求任意一個(gè)redis實(shí)例,然后由Redis將請(qǐng)求轉(zhuǎn)發(fā)給正確的Redis節(jié)點(diǎn)。Redis Cluster實(shí)現(xiàn)了一種混合形式的查詢路由,但并不是直接將請(qǐng)求從一個(gè)redis節(jié)點(diǎn)轉(zhuǎn)發(fā)到另一個(gè)redis節(jié)點(diǎn),而是在客戶端的幫助下直接redirected到正確的redis節(jié)點(diǎn)。

Redis分區(qū)有什么缺點(diǎn)?


1、涉及多個(gè)key的操作通常不會(huì)被支持。例如你不能對(duì)兩個(gè)集合求交集,因?yàn)樗麄兛赡鼙淮鎯?chǔ)到不同的Redis實(shí)例(實(shí)際上這種情況也有辦法,但是不能直接使用交集指令)。

2、同時(shí)操作多個(gè)key,則不能使用Redis事務(wù)。

3、分區(qū)使用的粒度是key,不能使用一個(gè)非常長的排序key存儲(chǔ)一個(gè)數(shù)據(jù)集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set)

4、當(dāng)使用分區(qū)的時(shí)候,數(shù)據(jù)處理會(huì)非常復(fù)雜,例如為了備份你必須從不同的Redis實(shí)例和主機(jī)同時(shí)收集RDB / AOF文件。

5、分區(qū)時(shí)動(dòng)態(tài)擴(kuò)容或縮容可能非常復(fù)雜。Redis集群在運(yùn)行時(shí)增加或者刪除Redis節(jié)點(diǎn),能做到最大程度對(duì)用戶透明地?cái)?shù)據(jù)再平衡,但其他一些客戶端分區(qū)或者代理分區(qū)方法則不支持這種特性。然而,有一種預(yù)分片的技術(shù)也可以較好的解決這個(gè)問題。

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


Redis為單進(jìn)程單線程模式,采用隊(duì)列模式將并發(fā)訪問變成串行訪問,且多客戶端對(duì)Redis的連接并不存在競(jìng)爭(zhēng)關(guān)系Redis中可以使用SETNX命令實(shí)現(xiàn)分布式鎖。

當(dāng)且僅當(dāng) key 不存在,將 key 的值設(shè)為 value。若給定的 key 已經(jīng)存在,則 SETNX 不做任何動(dòng)作

SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡(jiǎn)寫。

返回值:設(shè)置成功,返回 1 。設(shè)置失敗,返回 0 。

使用SETNX完成同步鎖的流程及事項(xiàng)如下:

使用SETNX命令獲取鎖,若返回0(key已存在,鎖已存在)則獲取失敗,反之獲取成功

為了防止獲取鎖后程序出現(xiàn)異常,導(dǎo)致其他線程/進(jìn)程調(diào)用SETNX命令總是返回0而進(jìn)入死鎖狀態(tài),需要為該key設(shè)置一個(gè)“合理”的過期時(shí)間

釋放鎖,使用DEL命令將鎖數(shù)據(jù)刪除

如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問題


所謂 Redis 的并發(fā)競(jìng)爭(zhēng) Key 的問題也就是多個(gè)系統(tǒng)同時(shí)對(duì)一個(gè) key 進(jìn)行操作,但是最后執(zhí)行的順序和我們期望的順序不同,這樣也就導(dǎo)致了結(jié)果的不同!

推薦一種方案:分布式鎖(zookeeper 和 redis 都可以實(shí)現(xiàn)分布式鎖)。(如果不存在 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問題,不要使用分布式鎖,這樣會(huì)影響性能)

基于zookeeper臨時(shí)有序節(jié)點(diǎn)可以實(shí)現(xiàn)的分布式鎖。大致思想為:每個(gè)客戶端對(duì)某個(gè)方法加鎖時(shí),在zookeeper上的與該方法對(duì)應(yīng)的指定節(jié)點(diǎn)的目錄下,生成一個(gè)唯一的瞬時(shí)有序節(jié)點(diǎn)。判斷是否獲取鎖的方式很簡(jiǎn)單,只需要判斷有序節(jié)點(diǎn)中序號(hào)最小的一個(gè)。當(dāng)釋放鎖的時(shí)候,只需將這個(gè)瞬時(shí)節(jié)點(diǎn)刪除即可。同時(shí),其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無法釋放,而產(chǎn)生的死鎖問題。完成業(yè)務(wù)流程后,刪除對(duì)應(yīng)的子節(jié)點(diǎn)釋放鎖。

在實(shí)踐中,當(dāng)然是從以可靠性為主。所以首推Zookeeper。

分布式Redis是前期做還是后期規(guī)模上來了再做好?為什么?


既然Redis是如此的輕量(單實(shí)例只使用1M內(nèi)存),為防止以后的擴(kuò)容,最好的辦法就是一開始就啟動(dòng)較多實(shí)例。即便你只有一臺(tái)服務(wù)器,你也可以一開始就讓Redis以分布式的方式運(yùn)行,使用分區(qū),在同一臺(tái)服務(wù)器上啟動(dòng)多個(gè)實(shí)例。

一開始就多設(shè)置幾個(gè)Redis實(shí)例,例如32或者64個(gè)實(shí)例,對(duì)大多數(shù)用戶來說這操作起來可能比較麻煩,但是從長久來看做這點(diǎn)犧牲是值得的。

這樣的話,當(dāng)你的數(shù)據(jù)不斷增長,需要更多的Redis服務(wù)器時(shí),你需要做的就是僅僅將Redis實(shí)例從一臺(tái)服務(wù)遷移到另外一臺(tái)服務(wù)器而已(而不用考慮重新分區(qū)的問題)。一旦你添加了另一臺(tái)服務(wù)器,你需要將你一半的Redis實(shí)例從第一臺(tái)機(jī)器遷移到第二臺(tái)機(jī)器。

什么是 RedLock


Redis 官方站提出了一種權(quán)威的基于 Redis 實(shí)現(xiàn)分布式鎖的方式名叫 Redlock,此種方式比原先的單節(jié)點(diǎn)的方法更安全。它可以保證以下特性:

1、安全特性:互斥訪問,即永遠(yuǎn)只有一個(gè) client 能拿到鎖

2、避免死鎖:最終 client 都可能拿到鎖,不會(huì)出現(xiàn)死鎖的情況,即使原本鎖住某資源的 client crash 了或者出現(xiàn)了網(wǎng)絡(luò)分區(qū)

3、容錯(cuò)性:只要大部分 Redis 節(jié)點(diǎn)存活就可以正常提供服務(wù)

緩存異常


緩存雪崩

緩存雪崩是指緩存同一時(shí)間大面積的失效,所以,后面的請(qǐng)求都會(huì)落到數(shù)據(jù)庫上,造成數(shù)據(jù)庫短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉。

解決方案

1、緩存數(shù)據(jù)的過期時(shí)間設(shè)置隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過期現(xiàn)象發(fā)生。

2、一般并發(fā)量不是特別多的時(shí)候,使用最多的解決方案是加鎖排隊(duì)。

3、給每一個(gè)緩存數(shù)據(jù)增加相應(yīng)的緩存標(biāo)記,記錄緩存的是否失效,如果緩存標(biāo)記失效,則更新數(shù)據(jù)緩存。

緩存穿透

緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù),導(dǎo)致所有的請(qǐng)求都落到數(shù)據(jù)庫上,造成數(shù)據(jù)庫短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉。

解決方案

1、接口層增加校驗(yàn),如用戶鑒權(quán)校驗(yàn),id做基礎(chǔ)校驗(yàn),id<=0的直接攔截;

2、從緩存取不到的數(shù)據(jù),在數(shù)據(jù)庫中也沒有取到,這時(shí)也可以將key-value對(duì)寫為key-null,緩存有效時(shí)間可以設(shè)置短點(diǎn),如30秒(設(shè)置太長會(huì)導(dǎo)致正常情況也沒法使用)。這樣可以防止攻擊用戶反復(fù)用同一個(gè)id暴力攻擊;

3、采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的 bitmap 中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè) bitmap 攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。

附加

對(duì)于空間的利用到達(dá)了一種極致,那就是Bitmap和布隆過濾器(Bloom Filter)。

Bitmap:典型的就是哈希表

缺點(diǎn)是,Bitmap對(duì)于每個(gè)元素只能記錄1bit信息,如果還想完成額外的功能,恐怕只能靠犧牲更多的空間、時(shí)間來完成了。

布隆過濾器(推薦)

就是引入了k(k>1)k(k>1)個(gè)相互獨(dú)立的哈希函數(shù),保證在給定的空間、誤判率下,完成元素判重的過程。

它的優(yōu)點(diǎn)是空間效率和查詢時(shí)間都遠(yuǎn)遠(yuǎn)超過一般的算法,缺點(diǎn)是有一定的誤識(shí)別率和刪除困難。

Bloom-Filter算法的核心思想就是利用多個(gè)不同的Hash函數(shù)來解決“沖突”。

Hash存在一個(gè)沖突(碰撞)的問題,用同一個(gè)Hash得到的兩個(gè)URL的值有可能相同。為了減少?zèng)_突,我們可以多引入幾個(gè)Hash,如果通過其中的一個(gè)Hash值我們得出某元素不在集合中,那么該元素肯定不在集合中。只有在所有的Hash函數(shù)告訴我們?cè)撛卦诩现袝r(shí),才能確定該元素存在于集合中。這便是Bloom-Filter的基本思想。

Bloom-Filter一般用于在大數(shù)據(jù)量的集合中判定某元素是否存在。

緩存擊穿

緩存擊穿是指緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù)(一般是緩存時(shí)間到期),這時(shí)由于并發(fā)用戶特別多,同時(shí)讀緩存沒讀到數(shù)據(jù),又同時(shí)去數(shù)據(jù)庫去取數(shù)據(jù),引起數(shù)據(jù)庫壓力瞬間增大,造成過大壓力。和緩存雪崩不同的是,緩存擊穿指并發(fā)查同一條數(shù)據(jù),緩存雪崩是不同數(shù)據(jù)都過期了,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫。

解決方案

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

2、加互斥鎖,互斥鎖

緩存預(yù)熱

緩存預(yù)熱就是系統(tǒng)上線后,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請(qǐng)求的時(shí)候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)!

解決方案

1、直接寫個(gè)緩存刷新頁面,上線時(shí)手工操作一下;

2、數(shù)據(jù)量不大,可以在項(xiàng)目啟動(dòng)的時(shí)候自動(dòng)進(jìn)行加載;

3、定時(shí)刷新緩存;

緩存降級(jí)

當(dāng)訪問量劇增、服務(wù)出現(xiàn)問題(如響應(yīng)時(shí)間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時(shí),仍然需要保證服務(wù)還是可用的,即使是有損服務(wù)。系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進(jìn)行自動(dòng)降級(jí),也可以配置開關(guān)實(shí)現(xiàn)人工降級(jí)。

緩存降級(jí)的最終目的是保證核心服務(wù)可用,即使是有損的。而且有些服務(wù)是無法降級(jí)的(如加入購物車、結(jié)算)。

在進(jìn)行降級(jí)之前要對(duì)系統(tǒng)進(jìn)行梳理,看看系統(tǒng)是不是可以丟卒保帥;從而梳理出哪些必須誓死保護(hù),哪些可降級(jí);比如可以參考日志級(jí)別設(shè)置預(yù)案:

1、一般:比如有些服務(wù)偶爾因?yàn)榫W(wǎng)絡(luò)抖動(dòng)或者服務(wù)正在上線而超時(shí),可以自動(dòng)降級(jí);

2、警告:有些服務(wù)在一段時(shí)間內(nèi)成功率有波動(dòng)(如在95~100%之間),可以自動(dòng)降級(jí)或人工降級(jí),并發(fā)送告警;

3、錯(cuò)誤:比如可用率低于90%,或者數(shù)據(jù)庫連接池被打爆了,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時(shí)可以根據(jù)情況自動(dòng)降級(jí)或者人工降級(jí);

4、嚴(yán)重錯(cuò)誤:比如因?yàn)樘厥庠驍?shù)據(jù)錯(cuò)誤了,此時(shí)需要緊急人工降級(jí)。

服務(wù)降級(jí)的目的,是為了防止Redis服務(wù)故障,導(dǎo)致數(shù)據(jù)庫跟著一起發(fā)生雪崩問題。因此,對(duì)于不重要的緩存數(shù)據(jù),可以采取服務(wù)降級(jí)策略,例如一個(gè)比較常見的做法就是,Redis出現(xiàn)問題,不去數(shù)據(jù)庫查詢,而是直接返回默認(rèn)值給用戶。

熱點(diǎn)數(shù)據(jù)和冷數(shù)據(jù)

熱點(diǎn)數(shù)據(jù),緩存才有價(jià)值

對(duì)于冷數(shù)據(jù)而言,大部分?jǐn)?shù)據(jù)可能還沒有再次訪問到就已經(jīng)被擠出內(nèi)存,不僅占用內(nèi)存,而且價(jià)值不大。頻繁修改的數(shù)據(jù),看情況考慮使用緩存

對(duì)于熱點(diǎn)數(shù)據(jù),比如我們的某IM產(chǎn)品,生日祝福模塊,當(dāng)天的壽星列表,緩存以后可能讀取數(shù)十萬次。再舉個(gè)例子,某導(dǎo)航產(chǎn)品,我們將導(dǎo)航信息,緩存以后可能讀取數(shù)百萬次。

數(shù)據(jù)更新前至少讀取兩次,緩存才有意義。這個(gè)是最基本的策略,如果緩存還沒有起作用就失效了,那就沒有太大價(jià)值了。

那存不存在,修改頻率很高,但是又不得不考慮緩存的場(chǎng)景呢?有!比如,這個(gè)讀取接口對(duì)數(shù)據(jù)庫的壓力很大,但是又是熱點(diǎn)數(shù)據(jù),這個(gè)時(shí)候就需要考慮通過緩存手段,減少數(shù)據(jù)庫的壓力,比如我們的某助手產(chǎn)品的,點(diǎn)贊數(shù),收藏?cái)?shù),分享數(shù)等是非常典型的熱點(diǎn)數(shù)據(jù),但是又不斷變化,此時(shí)就需要將數(shù)據(jù)同步保存到Redis緩存,減少數(shù)據(jù)庫壓力。

緩存熱點(diǎn)key

緩存中的一個(gè)Key(比如一個(gè)促銷商品),在某個(gè)時(shí)間點(diǎn)過期的時(shí)候,恰好在這個(gè)時(shí)間點(diǎn)對(duì)這個(gè)Key有大量的并發(fā)請(qǐng)求過來,這些請(qǐng)求發(fā)現(xiàn)緩存過期一般都會(huì)從后端DB加載數(shù)據(jù)并回設(shè)到緩存,這個(gè)時(shí)候大并發(fā)的請(qǐng)求可能會(huì)瞬間把后端DB壓垮。

解決方案

對(duì)緩存查詢加鎖,如果KEY不存在,就加鎖,然后查DB入緩存,然后解鎖;其他進(jìn)程如果發(fā)現(xiàn)有鎖就等待,然后等解鎖后返回?cái)?shù)據(jù)或者進(jìn)入DB查詢

常用工具


Redis支持的Java客戶端都有哪些?官方推薦用哪個(gè)?

Redisson、Jedis、lettuce等等,官方推薦使用Redisson。

Redis和Redisson有什么關(guān)系?

Redisson是一個(gè)高級(jí)的分布式協(xié)調(diào)Redis客服端,能幫助用戶在分布式環(huán)境中輕松實(shí)現(xiàn)一些Java的對(duì)象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。

Jedis與Redisson對(duì)比有什么優(yōu)缺點(diǎn)?

Jedis是Redis的Java實(shí)現(xiàn)的客戶端,其API提供了比較全面的Redis命令的支持;Redisson實(shí)現(xiàn)了分布式和可擴(kuò)展的Java數(shù)據(jù)結(jié)構(gòu),和Jedis相比,功能較為簡(jiǎn)單,不支持字符串操作,不支持排序、事務(wù)、管道、分區(qū)等Redis特性。Redisson的宗旨是促進(jìn)使用者對(duì)Redis的關(guān)注分離,從而讓使用者能夠?qū)⒕Ω械胤旁谔幚順I(yè)務(wù)邏輯上。

其他問題


Redis與Memcached的區(qū)別

兩者都是非關(guān)系型內(nèi)存鍵值數(shù)據(jù)庫,現(xiàn)在公司一般都是用 Redis 來實(shí)現(xiàn)緩存,而且 Redis 自身也越來越強(qiáng)大了!Redis 與 Memcached 主要有以下不同:

對(duì)比參數(shù)
redismemcached
類型1. 支持內(nèi)存 2. 非關(guān)系型數(shù)據(jù)庫1. 支持內(nèi)存 2. 鍵值對(duì)形式 3. 緩存形式
數(shù)據(jù)存儲(chǔ)類型1. String 2. List 3. Set 4. Hash 5. Sort Set 【俗稱ZSet】1. 文本型 2. 二進(jìn)制類型
查詢【操作】類型1. 批量操作 2. 事務(wù)支持 3. 每個(gè)類型不同的CRUD1.常用的CRUD 2. 少量的其他命令
附加功能1. 發(fā)布/訂閱模式 2. 主從分區(qū) 3. 序列化支持 4. 腳本支持【Lua腳本】1. 多線程服務(wù)支持
網(wǎng)絡(luò)IO模型單線程的多路IO復(fù)用模型
1. 多線程,非阻塞IO模式
事件庫
AeEventLibEvent
持久化支持
1. RDB 2. AOF不支持
集群模式
原生支持cluster模式,可以實(shí)現(xiàn)主從復(fù)制,讀寫分離
沒有原生的集群模式,需要依靠客戶端來實(shí)現(xiàn)往集群中分片寫入數(shù)據(jù)
內(nèi)存管理機(jī)制
在 Redis 中,并不是所有數(shù)據(jù)都一直存儲(chǔ)在內(nèi)存中,可以將一些很久沒用的 value 交換到磁盤Memcached 的數(shù)據(jù)則會(huì)一直在內(nèi)存中,Memcached 將內(nèi)存分割成特定長度的塊來存儲(chǔ)數(shù)據(jù),以完全解決內(nèi)存碎片的問題。但是這種方式會(huì)使得內(nèi)存的利用率不高,例如塊的大小為 128 bytes,只存儲(chǔ) 100 bytes 的數(shù)據(jù),那么剩下的 28 bytes 就浪費(fèi)掉了。
適用場(chǎng)景
復(fù)雜數(shù)據(jù)結(jié)構(gòu),有持久化,高可用需求,value存儲(chǔ)內(nèi)容較大
純key-value,數(shù)據(jù)量非常大,并發(fā)量非常大的業(yè)務(wù)

(1) memcached所有的值均是簡(jiǎn)單的字符串,redis作為其替代者,支持更為豐富的數(shù)據(jù)類型

(2) redis的速度比memcached快很多

(3) redis可以持久化其數(shù)據(jù)

如何保證緩存與數(shù)據(jù)庫雙寫時(shí)的數(shù)據(jù)一致性?

你只要用緩存,就可能會(huì)涉及到緩存與數(shù)據(jù)庫雙存儲(chǔ)雙寫,你只要是雙寫,就一定會(huì)有數(shù)據(jù)一致性的問題,那么你如何解決一致性問題?

一般來說,就是如果你的系統(tǒng)不是嚴(yán)格要求緩存+數(shù)據(jù)庫必須一致性的話,緩存可以稍微的跟數(shù)據(jù)庫偶爾有不一致的情況,最好不要做這個(gè)方案,讀請(qǐng)求和寫請(qǐng)求串行化,串到一個(gè)內(nèi)存隊(duì)列里去,這樣就可以保證一定不會(huì)出現(xiàn)不一致的情況

串行化之后,就會(huì)導(dǎo)致系統(tǒng)的吞吐量會(huì)大幅度的降低,用比正常情況下多幾倍的機(jī)器去支撐線上的一個(gè)請(qǐng)求。

還有一種方式就是可能會(huì)暫時(shí)產(chǎn)生不一致的情況,但是發(fā)生的幾率特別小,就是先更新數(shù)據(jù)庫,然后再刪除緩存

問題場(chǎng)景
描述解決
先寫緩存,再寫數(shù)據(jù)庫,緩存寫成功,數(shù)據(jù)庫寫失敗緩存寫成功,但寫數(shù)據(jù)庫失敗或者響應(yīng)延遲,則下次讀取(并發(fā)讀)緩存時(shí),就出現(xiàn)臟讀這個(gè)寫緩存的方式,本身就是錯(cuò)誤的,需要改為先寫數(shù)據(jù)庫,把舊緩存置為失效;讀取數(shù)據(jù)的時(shí)候,如果緩存不存在,則讀取數(shù)據(jù)庫再寫緩存
先寫數(shù)據(jù)庫,再寫緩存,數(shù)據(jù)庫寫成功,緩存寫失敗寫數(shù)據(jù)庫成功,但寫緩存失敗,則下次讀?。úl(fā)讀)緩存時(shí),則讀不到數(shù)據(jù)緩存使用時(shí),假如讀緩存失敗,先讀數(shù)據(jù)庫,再回寫緩存的方式實(shí)現(xiàn)
需要緩存異步刷新指數(shù)據(jù)庫操作和寫緩存不在一個(gè)操作步驟中,比如在分布式場(chǎng)景下,無法做到同時(shí)寫緩存或需要異步刷新(補(bǔ)救措施)時(shí)候確定哪些數(shù)據(jù)適合此類場(chǎng)景,根據(jù)經(jīng)驗(yàn)值確定合理的數(shù)據(jù)不一致時(shí)間,用戶數(shù)據(jù)刷新的時(shí)間間隔

Redis常見性能問題和解決方案?

1、Master最好不要做任何持久化工作,包括內(nèi)存快照和AOF日志文件,特別是不要啟用內(nèi)存快照做持久化。

2、如果數(shù)據(jù)比較關(guān)鍵,某個(gè)Slave開啟AOF備份數(shù)據(jù),策略為每秒同步一次。

3、為了主從復(fù)制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個(gè)局域網(wǎng)內(nèi)。

4、盡量避免在壓力較大的主庫上增加從庫

5、Master調(diào)用BGREWRITEAOF重寫AOF文件,AOF在重寫的時(shí)候會(huì)占大量的CPU和內(nèi)存資源,導(dǎo)致服務(wù)load過高,出現(xiàn)短暫服務(wù)暫?,F(xiàn)象。

6、為了Master的穩(wěn)定性,主從復(fù)制不要用圖狀結(jié)構(gòu),用單向鏈表結(jié)構(gòu)更穩(wěn)定,即主從關(guān)系為:Master<–Slave1<–Slave2<–Slave3…,這樣的結(jié)構(gòu)也方便解決單點(diǎn)故障問題,實(shí)現(xiàn)Slave對(duì)Master的替換,也即,如果Master掛了,可以立馬啟用Slave1做Master,其他不變。

Redis官方為什么不提供Windows版本?

因?yàn)槟壳癓inux版本已經(jīng)相當(dāng)穩(wěn)定,而且用戶量很大,無需開發(fā)windows版本,反而會(huì)帶來兼容性等問題。

一個(gè)字符串類型的值能存儲(chǔ)最大容量是多少?

512M

Redis如何做大量數(shù)據(jù)插入?

Redis2.6開始redis-cli支持一種新的被稱之為pipe mode的新模式用于執(zhí)行大量數(shù)據(jù)插入工作。

假如Redis里面有1億個(gè)key,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開頭的,如果將它們?nèi)空页鰜恚?/strong>

使用keys指令可以掃出指定模式的key列表。

對(duì)方接著追問:如果這個(gè)redis正在給線上的業(yè)務(wù)提供服務(wù),那使用keys指令會(huì)有什么問題?

這個(gè)時(shí)候你要回答redis關(guān)鍵的一個(gè)特性:redis的單線程的。keys指令會(huì)導(dǎo)致線程阻塞一段時(shí)間,線上服務(wù)會(huì)停頓,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)。這個(gè)時(shí)候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key列表,但是會(huì)有一定的重復(fù)概率,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時(shí)間會(huì)比直接用keys指令長。

使用Redis做過異步隊(duì)列嗎,是如何實(shí)現(xiàn)的?

使用list類型保存數(shù)據(jù)信息,rpush生產(chǎn)消息,lpop消費(fèi)消息,當(dāng)lpop沒有消息時(shí),可以sleep一段時(shí)間,然后再檢查有沒有信息,如果不想sleep的話,可以使用blpop, 在沒有信息的時(shí)候,會(huì)一直阻塞,直到信息的到來。redis可以通過pub/sub主題訂閱模式實(shí)現(xiàn)一個(gè)生產(chǎn)者,多個(gè)消費(fèi)者,當(dāng)然也存在一定的缺點(diǎn),當(dāng)消費(fèi)者下線時(shí),生產(chǎn)的消息會(huì)丟失。

Redis如何實(shí)現(xiàn)延時(shí)隊(duì)列?

使用sortedset,使用時(shí)間戳做score, 消息內(nèi)容作為key,調(diào)用zadd來生產(chǎn)消息,消費(fèi)者使用zrangbyscore獲取n秒之前的數(shù)據(jù)做輪詢處理。

Redis回收進(jìn)程如何工作的?

1、一個(gè)客戶端運(yùn)行了新的命令,添加了新的數(shù)據(jù)。

2、Redis檢查內(nèi)存使用情況,如果大于maxmemory的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。

3、一個(gè)新的命令被執(zhí)行,等等。

4、所以我們不斷地穿越內(nèi)存限制的邊界,通過不斷達(dá)到邊界然后不斷地回收回到邊界以下。

如果一個(gè)命令的結(jié)果導(dǎo)致大量?jī)?nèi)存被使用(例如很大的集合的交集保存到一個(gè)新的鍵),不用多久內(nèi)存限制就會(huì)被這個(gè)內(nèi)存使用量超越。

Redis回收使用的是什么算法?

LRU算法

關(guān)于“Redis高頻面試題有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI