1. 程式人生 > 其它 >資料庫面試題--Redis

資料庫面試題--Redis

Redis

1.什麼是Redis?簡述它的優缺點?

Redis本質上是一個Key-Value型別的記憶體資料庫,很像memcached,整個資料庫統統載入在記憶體當中進行操作,定期通過非同步操作把資料庫資料flush到硬碟上進行儲存。

因為是純記憶體操作,Redis的效能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知效能最快的Key-Value DB。

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

比方說用他的List來做FIFO雙向連結串列,實現一個輕量級的高性 能訊息佇列服務,用他的Set可以做高效能的tag系統等等。

另外Redis也可以對存入的Key-Value設定expire時間,因此也可以被當作一 個功能加強版的memcached來用。 Redis的主要缺點是資料庫容量受到實體記憶體的限制,不能用作海量資料的高效能讀寫,因此Redis適合的場景主要侷限在較小資料量的高效能操作和運算上。

2.Redis相比memcached有哪些優勢?

(1) memcached所有的值均是簡單的字串,redis作為其替代者,支援更為豐富的資料型別

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

(3) redis可以持久化其資料

3.Redis有哪些資料結構?

Redis 有 5 種基礎資料結構,它們分別是:string(字串)、list(列表)、hash(字典)、set(集合) 和 zset(有序集合)。這 5 種是 Redis 相關知識中最基礎、最重要的部分。

4.Redis主要消耗什麼物理資源?

記憶體。

5.Redis的全稱是什麼?

Remote Dictionary Server。

6.一個字串型別的值能儲存最大容量是多少?

512M

7.Redis為什麼那麼快?

1、記憶體操作;
2、單執行緒,省去執行緒切換、鎖競爭的開銷;
3、非阻塞IO模型,epoll。

8.Redis如何實現分散式鎖?

詳見:https://www.cnblogs.com/wlwl/p/11651409.html

9.Redis是單執行緒還是多執行緒?

Redis6.0採用多執行緒IO,不過命令的執行還是單執行緒的。
Redis6.0之前,IO執行緒和執行執行緒都是單執行緒的。

10.Redis 官方為什麼不提供 Windows 版本?

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

11.為什麼 Redis 需要把所有資料放到記憶體中?

Redis 為了達到最快的讀寫速度將資料都讀到記憶體中,並通過非同步的方式將資料寫入磁碟。

所以 redis 具有快速和資料持久化的特徵,如果不將資料放在記憶體中,磁碟 I/O 速度為嚴重影響 redis 的效能。

在記憶體越來越便宜的今天,redis 將會越來越受歡迎, 如果設定了最大使用的記憶體,則資料已有記錄數達到記憶體限值後不能繼續插入新值。

12.Redis如何設定密碼及驗證密碼?

設定密碼:config set requirepass 123456

授權密碼:auth 123456

13.Redis叢集如何選擇資料庫?

Redis叢集目前無法做資料庫選擇,預設在0資料庫。

14.快取失效?快取穿透?快取雪崩?快取併發?

  1. 快取失效
    快取失效指的是大量的快取在同一時間失效,到時DB的瞬間壓力飆升。造成這種現象的原因是,key的過期時間都設定成一樣了。解決方案是,key的過期時間引入隨機因素,比如5分鐘+隨機秒這種方式。

  2. 快取穿透
    快取穿透是指查詢一條資料庫和快取都沒有的一條資料,就會一直查詢資料庫,對資料庫的訪問壓力就會增大,快取穿透的解決方案,有以下2種:
    快取空物件:程式碼維護較簡單,但是效果不好。
    布隆過濾器:程式碼維護複雜,效果很好。

  3. 快取雪崩
    快取雪崩 是指在某一個時間段,快取集中過期失效。此刻無數的請求直接繞開快取,直接請求資料庫。
    造成快取雪崩的原因,有以下2種:
    reids宕機。
    大部分資料失效。

對於快取雪崩的解決方案有以下2種:
搭建高可用的叢集,防止單機的redis宕機。
設定不同的過期時間,防止同意之間內大量的key失效。

  1. 快取併發
    有時候如果網站併發訪問高,一個快取如果失效,可能出現多個程序同時查詢DB,同時設定快取的情況,如果併發確實很大,這也可能造成DB壓力過大,還有快取頻繁更新的問題。
    一般處理方案是在查DB的時候進行加鎖,如果KEY不存在,就加鎖,然後查DB入快取,然後解鎖;其他程序如果發現有鎖就等待,然後等解鎖後再查快取或者進入DB查詢。

15.Redis中的熱key怎麼處理?

1、對熱key進行分散處理。比如:在key上加上不同的前後綴,快取多個key,使得各個key分散到不同的節點上。
2、採用多級快取。

16.Redis中的大key怎麼處理?

大key指的是value特別大的key。比如很長的字串,或者很大的set等等。
大key會造成2個問題:1、資料傾斜,比如某些節點記憶體佔用過高。2、當刪除大key或者大key自動過期的時候,會造成QPS突降,因為Redis是單執行緒的緣故。
處理方案:可以將一個大key進行分片處理,比如:將一個大set分成多個小的set。

17.使用Redis統計網站的UV,應該怎麼做?

UV與PV不同,UV需要去重。一般有2種方案:
1、用BitMap。存的是使用者的uid,計算UV的時候,做下bitcount就行了。
2、用布隆過濾器。將每次訪問的使用者uid都放到布隆過濾器中。優點是省記憶體,缺點是無法得到精確的UV。但是對於不需要精確知道具體UV,只需要大概的數量級的場景,是個不錯的選擇。

18.Redis事務機制瞭解過嗎?

Redis事務的概念:
Redis 事務的本質是一組命令的集合。事務支援一次執行多個命令,一個事務中所有命令都會被序列化。在事務執行過程,會按照順序序列化執行佇列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
Redis事務就是一次性、順序性、排他性的執行一個佇列中的一系列命令。  

Redis事務沒有隔離級別的概念:
批量操作在傳送 EXEC 命令前被放入佇列快取,並不會被實際執行,也就不存在事務內的查詢要看到事務裡的更新,事務外查詢不能看到。
Redis不保證原子性:
Redis中,單條命令是原子性執行的,但事務不保證原子性,且沒有回滾。事務中任意命令執行失敗,其餘的命令仍會被執行。

Redis事務的三個階段:
開始事務
命令入隊
執行事務

Redis事務相關命令:
watch key1 key2 ... : 監視一或多個key,如果在事務執行之前,被監視的key被其他命令改動,則事務被打斷 ( 類似樂觀鎖 )
multi : 標記一個事務塊的開始( queued )
exec : 執行所有事務塊的命令 ( 一旦執行exec後,之前加的監控鎖都會被取消掉 ) 
discard : 取消事務,放棄事務塊中的所有命令
unwatch : 取消watch對所有key的監控

19.Redis key的淘汰策略有哪些?

8種:noeviction,volatile-lru,volatile-lfu,volatile-ttl,volatile-random,allkey-lru,allkeys-lfu,allkeys-random

20.Redis在什麼情況下會觸發key的回收?

2種情況:1、定時(抽樣)清理;2、執行命令時,判斷記憶體是否超過maxmemory。

21.Redis的持久化了解過嗎?

Redis持久化有RDB和AOF這2種方式。
RDB:將資料庫快照以二進位制的方式儲存到磁碟中。
AOF:以協議文字方式,將所有對資料庫進行過寫入的命令和引數記錄到AOF檔案,從而記錄資料庫狀態。

22.Redis在叢集種查詢key的時候,是怎麼定位到具體節點的?

使用crc16演算法對key進行hash
將hash值對16384取模,得到具體的槽位
根據節點和槽位的對映資訊(與叢集建立連線後,客戶端可以取得槽位對映資訊),找到具體的節點地址
去具體的節點找key
如果key不在這個節點上,則redis叢集會返回moved指令,加上新的節點地址給客戶端,同時,客戶端會重新整理本地的節點槽位對映關係
如果槽位正在遷移中,那麼redis叢集會返回asking指令給客戶端,這是臨時糾正,客戶端不會重新整理本地的節點槽位對映關係

23.Redis叢集各個節點之間是怎麼保持資料一致性的?

主要考察點是Redis的Gossip協議。
詳見:https://mp.weixin.qq.com/s/dW0I29Sw86lU0qHpxyhdmw

24.用Redis做延時佇列,具體應該怎麼實現?

可以使用Zset實現。member是任務描述,score是執行時間,然後用定時器定時去掃描,一旦有執行時間小於或等於當前時間的任務,就立即執行。

25.Redis String的內部編碼有哪些?

int、embstr、raw
10000以下的整數會使用快取裡的int常量。
長度小於等於44位元組:embstr編碼
長度大於44位元組:raw編碼

26.Redis 叢集方案應該怎麼做?都有哪些方案?

  • codis
  • 目前用的最多的叢集方案,基本和 twemproxy 一致的效果,但它支援在節點數量改變情況下,舊節點資料可恢復到新 hash 節點。
  • redis cluster3.0 自帶的叢集,特點在於他的分散式演算法不是一致性 hash,而是 hash 槽的概念,以及自身支援節點設定從節點。具體看官方文件介紹。
  • 在業務程式碼層實現,起幾個毫無關聯的 redis 例項,在程式碼層,對 key 進行 hash 計算,然後去對應的redis 例項操作資料。這種方式對 hash 層程式碼要求比較高,考慮部分包括,節點失效後的替代演算法方案,資料震盪後的自動指令碼恢復,例項的監控,等等。
  • Java 架構學習資料(裡面有高可用、高併發、高效能及分散式、Jvm 效能調優、Spring 原始碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx 等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!

27.Redis 叢集方案什麼情況下會導致整個叢集不可用?

有 A,B,C 三個節點的叢集,在沒有複製模型的情況下,如果節點 B 失敗了,那麼整個叢集就會以為缺少5501-11000 這個範圍的槽而不可用。

28.MySQL 裡有 2000w 資料,redis 中只存 20w 的資料,如何保證 redis 中的資料都是熱點資料?

redis 記憶體資料集大小上升到一定大小的時候,就會施行資料淘汰策略。

其實面試除了考察 Redis,不少公司都很重視高併發高可用的技術,特別是一線網際網路公司,分散式、

JVM、spring 原始碼分析、微服務等知識點已是面試的必考題。

29.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 WITHSCORES

Agora Games就是一個很好的例子,用Ruby實現的,它的排行榜就是使用Redis來儲存資料的,你可以在這裡看到。

(5)釋出/訂閱

最後(但肯定不是最不重要的)是Redis的釋出/訂閱功能。釋出/訂閱的使用場景確實非常多。我已看見人們在社交網路連線中使用,還可作為基於釋出/訂閱的指令碼觸發器,甚至用Redis的釋出/訂閱功能來建立聊天系統!

30.Redis和Redisson有什麼關係?

Redisson是一個高階的分散式協調Redis客服端,能幫助使用者在分散式環境中輕鬆實現一些Java的物件 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。

31.Redis中的管道有什麼用?

一次請求/響應伺服器能實現處理新的請求即使舊的請求還未被響應。這樣就可以將多個命令傳送到伺服器,而不用等待回覆,最後在一個步驟中讀取該答覆。

這就是管道(pipelining),是一種幾十年來廣泛使用的技術。例如許多POP3協議已經實現支援這個功能,大大加快了從伺服器下載新郵件的過程。

32.Redis如何做記憶體優化?

儘可能使用散列表(hashes),散列表(是說散列表裡面儲存的數少)使用的記憶體非常小,所以你應該儘可能的將你的資料模型抽象到一個散列表裡面。

比如你的web系統中有一個使用者物件,不要為這個使用者的名稱,姓氏,郵箱,密碼設定單獨的key,而是應該把這個使用者的所有資訊儲存到一張散列表裡面。

線上刷題小程式

參考連結

http://blog.itpub.net/31545684/viewspace-2213990/

https://blog.csdn.net/weixin_34081595/article/details/92420220