您好,登錄后才能下訂單哦!
Redis 如何做內(nèi)存優(yōu)化?
答:盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面。比如你的 web 系統(tǒng)中有一個(gè)用戶對象,不要為這個(gè)用戶的名稱,姓氏,郵箱,密碼設(shè)置單獨(dú)的 key,而是應(yīng)該把這個(gè)用戶的所有信息存儲到一張散列表里面。
Redis 回收進(jìn)程如何工作的?
答:一個(gè)客戶端運(yùn)行了新的命令,添加了新的數(shù)據(jù)。Redi 檢查內(nèi)存使用情況,如果大于 maxmemory 的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。一個(gè)新的命令被執(zhí)行,等等。所以我們不斷地穿越內(nèi)存限制的邊界,通過不斷達(dá)到邊界然后不斷地回收回到邊界以下。如果一個(gè)命令的結(jié)果導(dǎo)致大量內(nèi)存被使用(例如很大的集合的交集保存到一個(gè)新的鍵),不用多久內(nèi)存限制就會被這個(gè)內(nèi)存使用量超越。
都有哪些辦法可以降低 Redis 的內(nèi)存使用情況呢?
答:如果你使用的是 32 位的 Redis 實(shí)例,可以好好利用 Hash,list,sorted set,set等集合類型數(shù)據(jù),因?yàn)橥ǔG闆r下很多小的 Key-Value 可以用更緊湊的方式存放到一起。
Redis 的內(nèi)存用完了會發(fā)生什么?
答:如果達(dá)到設(shè)置的上限,Redis 的寫命令會返回錯誤信息(但是讀命令還可以正常返回。)或者你可以將 Redis 當(dāng)緩存來使用配置淘汰機(jī)制,當(dāng) Redis 達(dá)到內(nèi)存上限時(shí)會沖刷掉舊的內(nèi)容。
一個(gè) Redis 實(shí)例最多能存放多少的 keys?List、Set、Sorted Set 他們最多能存放多少元素?
答:理論上 Redis 可以處理多達(dá) 232 的 keys,并且在實(shí)際中進(jìn)行了測試,每個(gè)實(shí)例至少存放了 2 億 5 千萬的 keys。我們正在測試一些較大的值。任何 list、set、和 sorted set 都可以放 232 個(gè)元素。換句話說,Redis 的存儲極限是系統(tǒng)中的可用內(nèi)存值。
MySQL 里有 2000w 數(shù)據(jù),redis 中只存 20w 的數(shù)據(jù),如何保證 redis 中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)?
答:Redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時(shí)候,就會施行數(shù)據(jù)淘汰策略。
相關(guān)知識:Redis 提供 6 種數(shù)據(jù)淘汰策略:
volatile-lru:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
volatile-ttl:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰
volatile-random:從已設(shè)置過期時(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ù)
Redis 最適合的場景?
1、會話緩存(Session Cache)
最常用的一種使用 Redis 的情景是會話緩存(session cache)。用 Redis 緩存會話比其他存儲(如 Memcached)的優(yōu)勢在于:Redis 提供持久化。當(dāng)維護(hù)一個(gè)不是嚴(yán)格要求一致性的緩存時(shí),如果用戶的購物車信息全部丟失,大部分人都會不高興的,現(xiàn)在,他們還會這樣嗎? 幸運(yùn)的是,隨著 Redis 這些年的改進(jìn),很容易找到怎么恰當(dāng)?shù)氖褂?Redis 來緩存會話的文檔。甚至廣為人知的商業(yè)平臺Magento 也提供 Redis 的插件。
2、全頁緩存(FPC)
除基本的會話 token 之外,Redis 還提供很簡便的 FPC 平臺?;氐揭恢滦詥栴},即使重啟了 Redis 實(shí)例,因?yàn)橛写疟P的持久化,用戶也不會看到頁面加載速度的下降,這是一個(gè)極大改進(jìn),類似 PHP 本地 FPC。 再次以 Magento 為例,Magento提供一個(gè)插件來使用 Redis 作為全頁緩存后端。 此外,對 WordPress 的用戶來說,Pantheon 有一個(gè)非常好的插件 wp-redis,這個(gè)插件能幫助你以最快速度加載你曾瀏覽過的頁面。
3、隊(duì)列
Reids 在內(nèi)存存儲引擎領(lǐng)域的一大優(yōu)點(diǎn)是提供 list 和 set 操作,這使得 Redis能作為一個(gè)很好的消息隊(duì)列平臺來使用。Redis 作為隊(duì)列使用的操作,就類似于本地程序語言(如 Python)對 list 的 push/pop 操作。 如果你快速的在 Google中搜索“Redis queues”,你馬上就能找到大量的開源項(xiàng)目,這些項(xiàng)目的目的就是利用 Redis 創(chuàng)建非常好的后端工具,以滿足各種隊(duì)列需求。例如,Celery 有一個(gè)后臺就是使用 Redis 作為 broker,你可以從這里去查看。
4,排行榜/計(jì)數(shù)器
Redis 在內(nèi)存中對數(shù)字進(jìn)行遞增或遞減的操作實(shí)現(xiàn)的非常好。集合(Set)和有序集合(Sorted Set)也使得我們在執(zhí)行這些操作的時(shí)候變的非常簡單,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 來存儲數(shù)據(jù)的,你可以在這里看到。
5、發(fā)布/訂閱
最后(但肯定不是最不重要的)是 Redis 的發(fā)布/訂閱功能。發(fā)布/訂閱的使用場景確實(shí)非常多。我已看見人們在社交網(wǎng)絡(luò)連接中使用,還可作為基于發(fā)布/訂閱的腳本觸發(fā)器,甚至用 Redis 的發(fā)布/訂閱功能來建立聊天系統(tǒng)!
假如 Redis 里面有 1 億個(gè) key,其中有 10w 個(gè) key 是以某個(gè)固定的已知的前綴開頭的,如果將它們?nèi)空页鰜恚?br/>答:使用 keys 指令可以掃出指定模式的 key 列表。
如果這個(gè) redis 正在給線上的業(yè)務(wù)提供服務(wù),那使用 keys 指令會有什么問題?
這個(gè)時(shí)候你要回答 redis 關(guān)鍵的一個(gè)特性:redis 的單線程的。keys 指令會導(dǎo)致線程阻塞一段時(shí)間,線上服務(wù)會停頓,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)。這個(gè)時(shí)候可以使用 scan 指令,scan 指令可以無阻塞的提取出指定模式的 key 列表,但是會有一定的重復(fù)概率,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時(shí)間會比直接用 keys 指令長。
如果有大量的 key 需要設(shè)置同一時(shí)間過期,一般需要注意什么?
答:如果大量的 key 過期時(shí)間設(shè)置的過于集中,到過期的那個(gè)時(shí)間點(diǎn),redis 可能會出現(xiàn)短暫的卡頓現(xiàn)象。一般需要在時(shí)間上加一個(gè)隨機(jī)值,使得過期時(shí)間分散一些。
使用過 Redis 做異步隊(duì)列么,你是怎么用的?
答:一般使用 list 結(jié)構(gòu)作為隊(duì)列,rpush 生產(chǎn)消息,lpop 消費(fèi)消息。當(dāng) lpop 沒有消息的時(shí)候,要適當(dāng) sleep 一會再重試。如果對方追問可不可以不用 sleep 呢?list 還有個(gè)指令叫 blpop,在沒有消息的時(shí)候,它會阻塞住直到消息到來。如果對方追問能不能生產(chǎn)一次消費(fèi)多次呢?使用 pub/sub 主題訂閱者模式,可以實(shí)現(xiàn)1:N 的消息隊(duì)列。
如果對方追問 pub/sub 有什么缺點(diǎn)?
在消費(fèi)者下線的情況下,生產(chǎn)的消息會丟失,得使用專業(yè)的消息隊(duì)列如 RabbitMQ等。
如果對方追問 redis 如何實(shí)現(xiàn)延時(shí)隊(duì)列?
我估計(jì)現(xiàn)在你很想把面試官一棒打死如果你手上有一根棒球棍的話,怎么問的這么詳細(xì)。但是你很克制,然后神態(tài)自若的回答道:使用 sortedset,拿時(shí)間戳作為score,消息內(nèi)容作為 key 調(diào)用 zadd 來生產(chǎn)消息,消費(fèi)者用 zrangebyscore 指令獲取 N 秒之前的數(shù)據(jù)輪詢進(jìn)行處理。到這里,面試官暗地里已經(jīng)對你豎起了大拇指。但是他不知道的是此刻你卻豎起了中指,在椅子背后。
使用過 Redis 分布式鎖么,它是什么回事?
先拿 setnx 來爭搶鎖,搶到之后,再用 expire 給鎖加一個(gè)過期時(shí)間防止鎖忘記了釋放。
這時(shí)候?qū)Ψ綍嬖V你說你回答得不錯,然后接著問如果在 setnx 之后執(zhí)行 expire之前進(jìn)程意外 crash 或者要重啟維護(hù)了,那會怎么樣?這時(shí)候你要給予驚訝的反饋:唉,是喔,這個(gè)鎖就永遠(yuǎn)得不到釋放了。緊接著你需要抓一抓自己得腦袋,故作思考片刻,好像接下來的結(jié)果是你主動思考出來的,然后回答:我記得 set 指令有非常復(fù)雜的參數(shù),這個(gè)應(yīng)該是可以同時(shí)把 setnx 和expire 合成一條指令來用的!對方這時(shí)會顯露笑容,心里開始默念:摁,這小子還不錯。
Redis的應(yīng)用場景
總結(jié)一:
計(jì)數(shù)器
可以對 String 進(jìn)行自增自減運(yùn)算,從而實(shí)現(xiàn)計(jì)數(shù)器功能。
Redis 這種內(nèi)存型數(shù)據(jù)庫的讀寫性能非常高,很適合存儲頻繁讀寫的計(jì)數(shù)量。
緩存
將熱點(diǎn)數(shù)據(jù)放到內(nèi)存中,設(shè)置內(nèi)存的最大使用量以及淘汰策略來保證緩存的命中率。
會話緩存
可以使用 Redis 來統(tǒng)一存儲多臺應(yīng)用服務(wù)器的會話信息。
當(dāng)應(yīng)用服務(wù)器不再存儲用戶的會話信息,也就不再具有狀態(tài),一個(gè)用戶可以請求任意一個(gè)應(yīng)用服務(wù)器,從而更容易實(shí)現(xiàn)高可用性以及可伸縮性。
全頁緩存(FPC)
除基本的會話token之外,Redis還提供很簡便的FPC平臺。
以Magento為例,Magento提供一個(gè)插件來使用Redis作為全頁緩存后端。此外,對WordPress的用戶來說,Pantheon有一個(gè)非常好的插件 wp-redis,這個(gè)插件能幫助你以最快速度加載你曾瀏覽過的頁面。
查找表
例如 DNS 記錄就很適合使用 Redis 進(jìn)行存儲。
查找表和緩存類似,也是利用了 Redis 快速的查找特性。但是查找表的內(nèi)容不能失效,而緩存的內(nèi)容可以失效,因?yàn)榫彺娌蛔鳛榭煽康臄?shù)據(jù)來源。
消息隊(duì)列(發(fā)布/訂閱功能)
List 是一個(gè)雙向鏈表,可以通過 lpush 和 rpop 寫入和讀取消息
不過最好使用 Kafka、RabbitMQ 等消息中間件。
分布式鎖實(shí)現(xiàn)
在分布式場景下,無法使用單機(jī)環(huán)境下的鎖來對多個(gè)節(jié)點(diǎn)上的進(jìn)程進(jìn)行同步。
可以使用 Redis 自帶的 SETNX 命令實(shí)現(xiàn)分布式鎖,除此之外,還可以使用官方提供的 RedLock 分布式鎖實(shí)現(xiàn)。
其它
Set 可以實(shí)現(xiàn)交集、并集等操作,從而實(shí)現(xiàn)共同好友等功能。
ZSet 可以實(shí)現(xiàn)有序性操作,從而實(shí)現(xiàn)排行榜等功能。
總結(jié)二:
Redis相比其他緩存,有一個(gè)非常大的優(yōu)勢,就是支持多種數(shù)據(jù)類型。
數(shù)據(jù)類型說明string字符串,最簡單的k-v存儲hashhash格式,value為field和value,適合ID-Detail這樣的場景。list簡單的list,順序列表,支持首位或者末尾插入數(shù)據(jù)set無序list,查找速度快,適合交集、并集、差集處理sorted set有序的set
其實(shí),通過上面的數(shù)據(jù)類型的特性,基本就能想到合適的應(yīng)用場景了。
string——適合最簡單的k-v存儲,類似于memcached的存儲結(jié)構(gòu),短信驗(yàn)證碼,配置信息等,就用這種類型來存儲。
hash——一般key為ID或者唯一標(biāo)示,value對應(yīng)的就是詳情了。如商品詳情,個(gè)人信息詳情,新聞詳情等。
list——因?yàn)閘ist是有序的,比較適合存儲一些有序且數(shù)據(jù)相對固定的數(shù)據(jù)。如省市區(qū)表、字典表等。因?yàn)閘ist是有序的,適合根據(jù)寫入的時(shí)間來排序,如:最新的***,消息隊(duì)列等。
set——可以簡單的理解為ID-List的模式,如微博中一個(gè)人有哪些好友,set最牛的地方在于,可以對兩個(gè)set提供交集、并集、差集操作。例如:查找兩個(gè)人共同的好友等。
Sorted Set——是set的增強(qiáng)版本,增加了一個(gè)score參數(shù),自動會根據(jù)score的值進(jìn)行排序。比較適合類似于top 10等不根據(jù)插入的時(shí)間來排序的數(shù)據(jù)。
如上所述,雖然Redis不像關(guān)系數(shù)據(jù)庫那么復(fù)雜的數(shù)據(jù)結(jié)構(gòu),但是,也能適合很多場景,比一般的緩存數(shù)據(jù)結(jié)構(gòu)要多。了解每種數(shù)據(jù)結(jié)構(gòu)適合的業(yè)務(wù)場景,不僅有利于提升開發(fā)效率,也能有效利用Redis的性能。
為什么要用 Redis /為什么要用緩存
主要從“高性能”和“高并發(fā)”這兩點(diǎn)來看待這個(gè)問題。
高性能:
假如用戶第一次訪問數(shù)據(jù)庫中的某些數(shù)據(jù)。這個(gè)過程會比較慢,因?yàn)槭菑挠脖P上讀取的。將該用戶訪問的數(shù)據(jù)存在數(shù)緩存中,這樣下一次再訪問這些數(shù)據(jù)的時(shí)候就可以直接從緩存中獲取了。操作緩存就是直接操作內(nèi)存,所以速度相當(dāng)快。如果數(shù)據(jù)庫中的對應(yīng)數(shù)據(jù)改變的之后,同步改變緩存中相應(yīng)的數(shù)據(jù)即可!
高并發(fā):
直接操作緩存能夠承受的請求是遠(yuǎn)遠(yuǎn)大于直接訪問數(shù)據(jù)庫的,所以我們可以考慮把數(shù)據(jù)庫中的部分?jǐn)?shù)據(jù)轉(zhuǎn)移到緩存中去,這樣用戶的一部分請求會直接到緩存這里而不用經(jīng)過數(shù)據(jù)庫。
更多面試資料免費(fèi)獲取:
QQ獲取
搜索Q群號:668470172
不常用QQ的小伙伴可以微信獲取(記得備注一下加群渠道哦~)
輸入賬號:13272413561
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。