Java面試題-Redis(更新於202004)

目錄

@、什麼是redis?

@、使用redis做緩存的原因?

@、Redis官方爲什麼不提供Windows版本?

@、Memcache與Redis的區別都有哪些?

@、Redis相比memcached有哪些優勢?

@、Redis有哪些數據結構?

@、爲什麼redis需要把所有數據放到內存中?

@、redis丟失問題常見原因?

@、redis的事務?

@、什麼是緩存穿透?如何避免?什麼是緩存雪崩?何如避免?

@、Redis如何做持久化的?

@、對多級緩存的理解?

@、redis常見性能問題和解決方案

@、Redis有哪些適合的場景?


@、什麼是redis?

Redis的全稱Remote Dictionary Server。

Redis 是一個基於內存的高性能key-value非關係型數據庫,由於數據存在內存裏面,讀寫速度特別快。

很像memcached,整個數據庫都加載在內存當中進行操作,定期通過異步操作把數據庫數據flush到硬盤上進行保存。

因爲是純內存操作,所以Redis的性能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DataBase。

Redis的出色之處不僅僅是性能,Redis最大的魅力是支持保存多種數據結構,此外單個value的最大限制是1GB,不像 memcached只能保存1MB的數據,因此Redis可以用來實現很多有用的功能,

比方說用他的List來做FIFO雙向鏈表,實現一個輕量級的高性 能消息隊列服務,用他的Set可以做高性能的tag系統等等。

另外Redis也可以對存入的Key-Value設置expire時間,因此也可以被當作一 個功能加強版的memcached來用。

Redis的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此Redis適合的場景主要侷限在較小數據量的高性能操作和運算上。

@、使用redis做緩存的原因?

redis是用C語言編寫的,穩定性和性能更好。支持集羣模式和持久化等特性,不會應爲緩存量太多而導致虛擬機崩潰。Redis是獨立部署的,即使網站更新,redis緩存的數據也不會消失。

集羣搭建(redis需要3臺主機,3臺從機,則配置6臺,需要6個端口):

1:安裝ruby環境,上傳接口工程,安裝接口程序,拷貝腳本到指定位置

2:創建6個redis實例,修改配置文件 ,然後啓動所有redis實例(爲簡化啓動步驟,可編寫啓動腳本)。

3:執行創建集羣的命令,連接測試

@、Redis官方爲什麼不提供Windows版本?

因爲目前Linux版本已經相當穩定,而且用戶量很大,無需開發windows版本,反而會帶來兼容性等問題。

@、Memcache與Redis的區別都有哪些?

1)存儲方式

Memecache把數據全部存在內存之中,斷電後會掛掉,數據不能超過內存大小。

Redis可以把數據保存在硬盤上,用來保證數據的持久性。

2)數據類型

Memcache的數據類型比較簡單。

Redis有複雜的數據類型。

3)使用底層模型不同

它們之間底層的實現方式 以及與客戶端之間通信的應用協議不一樣。

4)value大小

redis最大可以達到1GB,而memcache只有1MB

@、Redis相比memcached有哪些優勢?

(1) 數據類型:memcached所有的值均是簡單的字符串,redis作爲其替代者, 支持更爲豐富的數據類型

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

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

@、Redis有哪些數據結構?

字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。

String字符串:

格式: set key value

string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。

string類型是Redis最基本的數據類型,一個鍵最大能存儲512MB。

Hash(哈希)

格式: hmset name  key1 value1 key2 value2

Redis hash 是一個鍵值(key=>value)對集合。

Redis hash是一個string類型的field和value的映射表,hash特別適合用於存儲對象。

List(列表)

Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)

格式: lpush  name  value

在 key 對應 list 的頭部添加字符串元素

格式: rpush  name  value

在 key 對應 list 的尾部添加字符串元素

格式: lrem name  index

key 對應 list 中刪除 count 個和 value 相同的元素

格式: llen name  

返回 key 對應 list 的長度

Set(集合)

格式: sadd  name  value

Redis的Set是string類型的無序集合。

集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是O(1)。

zset(sorted set:有序集合)

格式: zadd  name score value

Redis zset 和 set 一樣也是string類型元素的集合,且不允許重複的成員。

不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來爲集合中的成員進行從小到大的排序。

zset的成員是唯一的,但分數(score)卻可以重複。

更進一步,redis還有數據結構HyperLogLog、Geo、Pub/Sub、BloomFilter,RedisSearch,Redis-ML等

@、爲什麼redis需要把所有數據放到內存中?

Redis爲了達到最快的讀寫速度,將數據都讀到內存中,並通過異步的方式將數據寫入磁盤。所以redis具有快速和數據持久化的特徵。

如果不將數據放在內存中,磁盤I/O速度爲嚴重影響redis的性能。

如果設置了最大使用的內存,則數據量達到內存限值後,將不能繼續插入新值。

@、redis丟失問題常見原因?

程序bug或人爲誤操作

因客戶端緩衝區內存使用過大,導致大量鍵被LRU淘汰

主庫故障後自動重啓,可能導致數據丟失

網絡分區的問題,可能導致短時間的寫入數據丟失

主從複製數據不一致,發生故障切換後,出現數據丟失

大量過期鍵,同時被淘汰清理

@、redis的事務?

Redis的事務是一組命令的集合,Redis事務的實現需要用到 MULTI 和 EXEC 兩個命令,事務開始的時候先向Redis服務器發送 MULTI 命令,然後依次發送需要在本次事務中處理的命令,最後再發送 EXEC 命令表示事務命令結束。

@、什麼是緩存穿透?如何避免?什麼是緩存雪崩?何如避免?

緩存穿透

一般的緩存系統,都是按照key去緩存查詢,如果不存在對應的value,就應該去後端系統查找(比如DB)。一些惡意的請求會故意查詢不存在的key,請求量很大,就會對後端系統造成很大的壓力。這就叫做緩存穿透。

如何避免?

1:對查詢結果爲空的情況也進行緩存,緩存時間設置短一點,或者該key對應的數據insert了之後清理緩存。

2:對一定不存在的key進行過濾。可以把所有的可能存在的key放到一個大的Bitmap中,查詢時通過該bitmap過濾。

緩存雪崩

當緩存服務器重啓或者大量緩存集中在某一個時間段失效,這樣在失效的時候,會給後端系統帶來很大壓力。導致系統崩潰。

如何避免?

1:在緩存失效後,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。

2:做二級緩存,A1爲原始緩存,A2爲拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置爲短期,A2設置爲長期

3:不同的key,設置不同的過期時間,讓緩存失效的時間點儘量均勻。

MySQL裏有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據?

redis內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。

@、Redis如何做持久化的?

bgsave做鏡像全量持久化,aof做增量持久化。

因爲bgsave會耗費較長時間,達不到實時,在停機的時候會導致大量丟失數據,所以需要aof來配合使用。

如果不要求性能,在每條寫指令時都sync一下磁盤,就不會丟失數據。但是在高性能的要求下每次都sync是不現實的,一般都使用定時sync,比如1秒1次,這個時候最多會丟失1s的數據。

Redis會定期做aof重寫,壓縮aof文件日誌大小。

在redis實例重啓時,優先使用aof來恢復內存的狀態,如果沒有aof日誌,就會使用rdb文件來恢復。

講一下對Redis的同步機制的理解

Redis可以使用主從同步,從從同步。

第一次同步時,主節點做一次bgsave,並同時將後續修改操作記錄到內存buffer,待完成後將rdb文件全量同步到複製節點,複製節點接受完成後將rdb鏡像加載到內存。

加載完成後,再通知主節點將期間修改的操作記錄同步到複製節點進行重放就完成了同步過程。

@、對多級緩存的理解?

多級緩存就是有多個緩存,將ehcache配合redis緩存,比如ehcache作爲1級緩存,使用redis作爲2級緩存。

@、redis常見性能問題和解決方案

(1) Master最好不要做任何持久化工作,如RDB內存快照和AOF日誌文件

(2) 如果數據比較重要,某個Slave開啓AOF備份數據,策略設置爲每秒同步一次

(3) 爲了主從複製的速度和連接的穩定性,Master和Slave最好在同一個局域網內

(4) 儘量避免在壓力很大的主庫上增加從庫

(5) 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master <- Slave1 <- Slave2 <- Slave3...

這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啓用Slave1做Master,其他不變。

@、Redis有哪些適合的場景?

(1)、會話緩存(Session Cache)最常用的一種使用Redis的情景是會話緩存(session cache)。用Redis緩存會話比其他存儲(如Memcached)的優勢在於:Redis提供持久化。當維護一個不是嚴格要求一致性的緩存時,如果用戶的購物車信息全部丟失,大部分人都會不高興的,現在,他們還會這樣嗎?幸運的是,隨着 Redis 這些年的改進,很容易找到怎麼恰當的使用Redis來緩存會話的文檔。甚至廣爲人知的商業平臺Magento也提供Redis的插件。

(2)、全頁緩存(FPC)除基本的會話token之外,Redis還提供很簡便的FPC平臺。回到一致性問題,即使重啓了Redis實例,因爲有磁盤的持久化,用戶也不會看到頁面加載速度的下降,這是一個極大改進,類似PHP本地FPC。再次以Magento爲例,Magento提供一個插件來使用Redis作爲全頁緩存後端。此外,對WordPress的用戶來說,Pantheon有一個非常好的插件 wp-redis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面。

(3)、隊列Reids在內存存儲引擎領域的一大優點是提供 list 和 set 操作,這使得Redis能作爲一個很好的消息隊列平臺來使用。Redis作爲隊列使用的操作,就類似於本地程序語言(如Python)對 list 的 push/pop 操作。如果你快速的在Google中搜索“Redis queues”,你馬上就能找到大量的開源項目,這些項目的目的就是利用Redis創建非常好的後端工具,以滿足各種隊列需求。例如,Celery有一個後臺就是使用Redis作爲broker,你可以從這裏去查看。

(4),排行榜/計數器Redis在內存中對數字進行遞增或遞減的操作實現的非常好。集合(Set)和有序集合(Sorted Set)也使得我們在執行這些操作的時候變的非常簡單,Redis只是正好提供了這兩種數據結構。所以,我們要從排序集合中獲取到排名最靠前的10個用戶–我們稱之爲“user_scores”,我們只需要像下面一樣執行即可:當然,這是假定你是根據你用戶的分數做遞增的排序。如果你想返回用戶及用戶的分數,你需要這樣執行:ZRANGE user_scores 0 10 WITHSCORESAgora Games就是一個很好的例子,用Ruby實現的,它的排行榜就是使用Redis來存儲數據的,你可以在這裏看到。

(5)、發佈/訂閱最後(但肯定不是最不重要的)是Redis的發佈/訂閱功能。發佈/訂閱的使用場景確實非常多。我已看見人們在社交網絡連接中使用,還可作爲基於發佈/訂閱的腳本觸發器,甚至用Redis的發佈/訂閱功能來建立聊天系統!(不,這是真的,你可以去核實)。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章