乾貨!Redis面試必知必會

Redis 支持哪幾種數據類型?

  • string:最基本的數據類型,二進制安全的字符串,最大512M
  • list:按照添加順序保持順序的 字符串列表
  • set:無序的字符串集合,不存在重複的元素
  • sorted set:已排序的字符串集合
  • hash:key/value對的一種集合

Redis是單進程的仍是單線程的?

Redis是單進程單線程的,Redis利用隊列技術將併發訪問變爲串行訪問,消除了傳統數據庫串行控制的開銷。程序員

Redis爲何是單線程的?

多線程處理會涉及到鎖,並且多線程處理會設計到線程切換而消耗CPU。由於CPU不會Redis的瓶頸,Redis的瓶頸最有多是機器內存或者網絡帶寬。單線程沒法發揮多核CPU性能,不過能夠經過在單機開啓Redis實例來解決。web

Redis的優點

  • **速度快。**由於數據存儲於內存中,相似於HashMap,HashMap的優點就是查找和操做的時間複雜度都是O(1)
  • 支持豐富的數據類型,支持string,list,set,sorted set,hash
  • 支持事務,操做都是原子性,所謂的原子性就是對數據的更改要麼所有執行,要麼所有不執行
  • 豐富的特性:可用於緩存,消息,按key設置過時時間,過時後將會自動刪除

Redis和memcached有哪些優點

  • memcached全部的值均是簡單的字符串,Reids做爲其替代者,支持更爲豐富的數據類型
  • Redis的速度比memcached快不少
  • Redis能夠持久化其數據
  • Redis支持數據的備份,即master/slave模式的數據備份

Redis key的過時時間和永久有效分別怎麼設置?

EXPIREPERSIST命令。redis

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

內存。算法

爲何Redis須要把全部數據放到內存中?

Redis爲了達到最快的讀寫速度將數據都讀到內存中,並經過異步的方式將數據寫入磁盤。數據庫

因此redis具備快速和數據持久化的特徵。若是不將數據放在內存中,磁盤I/O速度爲嚴重影響redis的性能。後端

在內存愈來愈便宜的今天,redis將會愈來愈受歡迎。 若是設置了最大使用的內存,則數據已有記錄數達到內存限值後不能繼續插入新值。緩存

說說Redis哈希槽的概念?

Redis集羣沒有使用一致性hash,而是引入了哈希槽的概念,Redis集羣有16384個哈希槽,每一個key經過CRC16校驗後對16384取模來決定放置哪一個槽,集羣的每一個節點負責一部分hash槽。安全

Redis中的管道有什麼用?

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

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

怎麼理解Redis事務?

事務是一個單獨的隔離操做:事務中的全部命令都會序列化、按順序地執行。事務在執行的過程當中,不會被其餘客戶端發送來的命令請求所打斷。

事務是一個原子操做:事務中的命令要麼所有被執行,要麼所有都不執行。

Redis 事務相關的命令有哪幾個?

MULTIEXECDISCARDWATCH

Redis內存回收機制

Redis的內存回收主要圍繞如下兩個方面:

  1. Redis過時策略:刪除過時時間的key值
  2. Redis淘汰策略:內存使用到達maxmemory上限時觸發內存淘汰數據

Redis過時策略

Redis過時策略一般有如下三種:

  1. 定時過時 每一個設置過時時間的key都須要建立一個定時器,到過時時間就會當即清除。該策略能夠當即清除過時的數據,對內存很友好;可是會佔用大量的CPU資源去處理過時的數據,從而影響緩存的響應時間和吞吐量。

  2. 惰性過時 只有當訪問一個key時,纔會判斷該key是否已過時,過時則清除。該策略能夠最大化地節省CPU資源,卻對內存很是不友好。極端狀況可能出現大量的過時key沒有再次被訪問,從而不會被清除,佔用大量內存。

  3. 按期過時 每隔必定的時間,會掃描必定數量的數據庫的expires字典中必定數量的key,並清除其中已過時的key。該策略是前二者的一個折中方案。經過調整定時掃描的時間間隔和每次掃描的限定耗時,能夠在不一樣狀況下使得CPU和內存資源達到最優的平衡效果。

Redis中同時使用了惰性過時按期過時兩種過時策略。

Redis有哪幾種數據淘汰策略

在Redis中,容許用戶設置最大使用內存大小server.maxmemory,當Redis內存數據集大小上升到必定大小的時候,就會執行數據淘汰策略

  • volatile-lru:從已設置過時的數據集中挑選最近最少使用的淘汰
  • volatile-ttl:從已設置過時的數據集中挑選將要過時的數據淘汰
  • volatile-random:從已設置過時的數據集中任意挑選數據淘汰
  • allkeys-lru:從數據集中挑選最近最少使用的數據淘汰
  • allkeys-random:從數據集中任意挑選數據淘汰
  • noenviction:禁止淘汰數據

Redis支持哪幾種持久化方式

RDB持久化 原理是將Redis在內存中的數據記錄定時dump到磁盤上的RDB文件。 指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操做過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換以前的文件,用二進制壓縮存儲。

AOF(append only file)持久化 原理是將Redis的操做日誌以追加的方式寫入文件。 以日誌的形式記錄服務器所處理的每個寫、刪除操做,查詢操做不會記錄,以文本的方式記錄,能夠打開文件看到詳細的操做記錄。當服務器重啓的時候會從新執行這些命令來恢復原始的數據。AOF命令以Reids協議追加保存每次寫的操做到文件末尾。Redis還能對AOF文件進行後臺重寫,使得AOF文件的體積不至於過大。

Redis兩種持久化方式優缺點?

RDB持久化

  • 優勢:RDB文件緊湊,體積小,網絡傳輸快,適合全量複製;恢復速度比AOF快不少。固然,與AOF相比,RDB最重要的優勢之一是對性能的影響相對較小
  • 缺點:RDB文件的致命缺點在與其數據快照的持久化方式決定了必然作不到實時持久化,而在數據愈來愈重要的今天,數據的大量丟失不少時候是沒法接受的,所以AOF持久化稱爲主流。此外,RDB文件須要知足特定格式,兼容性差。

AOF持久化 與RDB持久化相對應,AOF的優勢在於支持秒級持久化、兼容性好,缺點是文件大,恢復速度慢,對性能影響大

如何選擇Redis持久化方式策略?

在介紹持久化策略以前,首先要明白不管是RDB仍是AOF,持久化的開啓都是要付出性能方面的代價的。對比RDB持久化,一方面是bdsave在進行fork操做時Redis主進程會阻塞,另外一方面,子進程向硬盤寫數據也會帶來IO壓力;對於AOF持久化,向硬盤寫數據的頻率大大提升(everysec策略下爲秒級),IO壓力更大,設置可能形成AOF追加阻塞文件。此外,AOF文件的重寫與RDB的basave相似,會有fork時的阻塞和子進程的IO壓力問題。相對來講,因爲AOF向硬盤中寫數據的頻率更高,所以對Redis主進程性能的影響會更大。

在實際生產環境中,根據數據量、應用對數據的安全要求、預算限制等不一樣狀況,會有各類各樣的持久化策略;如徹底不使用任何持久化,使用RDB或AOF一種,或同事開啓RDB和AOF持久化等。此外,持久化的選擇必須與Redis的主從策略一塊兒考慮,由於主從複製與持久化一樣具備數據備份的功能,並且主機master和從機slave能夠獨立的選擇持久化方案。

爲何要作Redis分區?

分區可讓Redis管理更大的內存,Redis將可使用全部機器的內存。若是沒有分區,你最多隻能使用一臺機器的內存。分區使Redis的計算能力經過簡單地增長計算機獲得成倍提高,Redis的網絡帶寬也會隨着計算機和網卡的增長而成倍增加。

Redis集羣的主從複製模型是怎樣的?

爲了是在部分節點失敗或者大部分節點沒法通訊的狀況下集羣仍然可用,因此集羣是用了主從複製模型,每一個節點都會有N-1個複製品

Redis集羣會有寫操做丟失嗎?爲何?

Redis並不能保證數據強一致性,這意味着在實際中集羣在特定的條件下可能會丟失寫操做

Redis集羣之間是如何複製的

異步複製。

Redis如何作內存優化

儘量使用散列表(hashes),散列表(是說列表裏面存儲的數少)使用的內存很是小,因此你應該儘量的將你的數據模型抽象到一個散列表裏面,好比你的web系統中有一個用戶對象,不要爲這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶全部信息存儲到一張散列表中。

Redis經常使用的使用場景

  • Session共享(單點登陸)
  • 頁面緩存
  • 隊列
  • 排行榜/計算器
  • 發佈/訂閱

Redis有哪些架構模式?講講各自的特色?

單機版

特色:簡單

存在問題:

  1. 內存容量有限
  2. 處理能力有限
  3. 沒法高可用

主從複製

Redis的複製(replication)功能容許用戶根據一個Redis服務器來建立任意多個該服務器的複製品,其中被複制的服務器爲主服務器(master),而經過複製建立出來的服務器複製品則爲從服務器(slave)。主要主從服務器之間的網絡鏈接正常,主從服務器二者會具備相同的數據,主服務器就會一直將發生在本身身上的數據更新同步給從服務器,從而一直保證主從服務器的數據相同。

問題:

  1. 沒法保證高可用
  2. 沒有解決master寫的壓力

哨兵

Redis sentinel 是一個分佈式系統中監控 redis 主從服務器,並在主服務器下線時自動進行故障轉移。其中三個特性:

  • 監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運做正常。

  • 提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 能夠經過 API 向管理員或者其餘應用程序發送通知。

  • 自動故障遷移(Automatic failover): 當一個主服務器不能正常工做時, Sentinel 會開始一次自動故障遷移操做。

特色:

  1. 保證高可用
  2. 監控各個節點
  3. 自動故障遷移

缺點:

  1. 主從模式,切換須要時間,會丟數據
  2. 沒有解決master寫的壓力

集羣(proxy型)

Twemproxy 是一個 Twitter 開源的一個 redis 和 memcache 快速/輕量級代理服務器; Twemproxy 是一個快速的單線程代理程序,支持 Memcached ASCII 協議和 redis 協議。

特色:

  1. 多種 hash 算法:MD五、CRC1六、CRC3二、CRC32a、hsieh、murmur、Jenkins
  2. 支持失敗節點自動刪除
  3. 後端 Sharding 分片邏輯對業務透明,業務方的讀寫方式和操做單個 Redis 一致

缺點:

  1. 增長了新的 proxy,須要維護其高可用。
  2. failover 邏輯須要本身實現,其自己不能支持故障的自動轉移可擴展性差,進行擴縮容都須要手動干預

集羣(直連型)

從redis 3.0以後版本支持redis-cluster集羣,Redis-Cluster採用無中心結構,每一個節點保存數據和整個集羣狀態,每一個節點都和其餘全部節點鏈接。

特色:

  1. 無中心架構(不存在哪一個節點影響性能瓶頸),少了 proxy 層。
  2. 數據按照 slot 存儲分佈在多個節點,節點間數據共享,可動態調整數據分佈。
  3. 可擴展性,可線性擴展到 1000 個節點,節點可動態添加或刪除。
  4. 高可用性,部分節點不可用時,集羣仍可用。經過增長 Slave 作備份數據副本
  5. 實現故障自動 failover,節點之間經過 gossip 協議交換狀態信息,用投票機制完成 Slave到 Master的角色提高。

缺點:

  1. 資源隔離性較差,容易出現相互影響的狀況。
  2. 數據經過異步複製,不保證數據的強一致性

使用過Redis分佈式鎖嗎,它是怎麼實現的?

先拿setnx來爭搶鎖,搶到以後,再用expire給鎖加一個過時時間防止鎖忘記了釋放。 若是在setnx以後執行expire以前進程意外crash或者要重啓維護了,那會怎麼樣? set指令有很是複雜的參數,這個應該是能夠同時把setnx和expire合成一條指令來用的!

使用過 Redis 作異步隊列麼,你是怎麼用的?有什麼缺點?

般使用 list 結構做爲隊列,rpush 生產消息,lpop 消費消息。當 lpop 沒有消息的時候,要適當 sleep一會再重試。

缺點:

  • 在消費者下線的狀況下,生產的消息會丟失,得使用專業的消息隊列如 rabbitmq 等。
  • 能不能生產一次消費屢次呢?
  • 使用 pub/sub 主題訂閱者模式,能夠實現 1:N 的消息隊列。

什麼是緩存穿透?如何避免?

緩存穿透

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

如何避免?

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

  2. 對必定不存在的key進行過濾。能夠把全部的可能存在的key放到一個大的Bitmap中,查詢時經過該bitmap過濾。

什麼是緩存雪崩?何如避免?

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

如何避免?

  1. 在緩存失效後,經過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。好比對某個key只容許一個線程查詢數據和寫緩存,其餘線程等待。
  2. 作二級緩存,A1爲原始緩存,A2爲拷貝緩存,A1失效時,能夠訪問A2,A1緩存失效時間設置爲短時間,A2設置爲長期 3:不一樣的key,設置不一樣的過時時間,讓緩存失效的時間點儘可能均勻

緩存併發

這裏的併發指的是多個redis的client同時set key引發的併發問題。其實redis自身就是單線程操做,多個client併發操做,按照先到先執行的原則,先到的先執行,其他的阻塞。固然,另外的解決方案是把redis.set操做放在隊列中使其串行化,必須的一個一個執行。

緩存預熱

緩存預熱就是系統上線後,將相關的緩存數據直接加載到緩存系統。

這樣就能夠避免在用戶請求的時候,先查詢數據庫,而後再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據!

解決思路:

  1. 直接寫個緩存刷新頁面,上線時手工操做下;
  2. 數據量不大,能夠在項目啓動的時候自動進行加載;

目的就是在系統上線前,將數據加載到緩存中。

Redis回收進程如何工做的?

  1. 客戶端執行數據寫入操做
  2. redis server接收到寫入操做以後,檢查maxmemory的限制,若是超過了限制,那麼就根據對應的policy清理掉部分數據
  3. 寫入操做完成執行。

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

能夠在同一個服務器部署多個Redis的實例,並把他們看成不一樣的服務器來使用,在某些時候,不管如何一個服務器是不夠的, 因此,若是你想使用多個CPU,你能夠考慮一下分片(shard)。

修改配置不重啓Redis會實時生效嗎?

針對運行實例,有許多配置選項能夠經過 CONFIG SET 命令進行修改,而無需執行任何形式的重啓。 從 Redis 2.2 開始,能夠從 AOF 切換到 RDB 的快照持久性或其餘方式而不須要重啓 Redis。檢索 CONFIG GET * 命令獲取更多信息。 但偶爾從新啓動是必須的,如爲升級 Redis 程序到新的版本,或者當你須要修改某些目前 CONFIG 命令還不支持的配置參數的時候。

Redis的內存用完了會發生什麼?

若是達到設置的上限,Redis的寫命令會返回錯誤信息(可是讀命令還能夠正常返回。)或者你能夠將Redis當緩存來使用配置淘汰機制,當Redis達到內存上限時會沖刷掉舊的內容。

分佈式Redis是前期作仍是後期規模上來了再作好?爲何?

既然Redis是如此的輕量(單實例只使用1M內存),爲防止之後的擴容,最好的辦法就是一開始就啓動較多實例。即使你只有一臺服務器,你也能夠一開始就讓Redis以分佈式的方式運行,使用分區,在同一臺服務器上啓動多個實例。一開始就多設置幾個Redis實例,例如32或者64個實例,對大多數用戶來講這操做起來可能比較麻煩,可是從長久來看作這點犧牲是值得的。這樣的話,當你的數據不斷增加,須要更多的Redis服務器時,你須要作的就是僅僅將Redis實例從一臺服務遷移到另一臺服務器而已(而不用考慮從新分區的問題)。一旦你添加了另外一臺服務器,你須要將你一半的Redis實例從第一臺機器遷移到第二臺機器。

Redis與其餘key-value存儲有什麼不一樣?

Redis有着更爲複雜的數據結構而且提供對他們的原子性操做,這是一個不一樣於其餘數據庫的進化路徑。Redis的數據類型都是基於基本數據結構的同時對程序員透明,無需進行額外的抽象。Redis運行在內存中可是能夠持久化到磁盤,因此在對不一樣數據集進行高速讀寫時須要權衡內存,應爲數據量不能大於硬件內存。在內存數據庫方面的另外一個優勢是, 相比在磁盤上相同的複雜的數據結構,在內存中操做起來很是簡單,這樣Redis能夠作不少內部複雜性很強的事情。 同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,由於他們並不須要進行隨機訪問。

關注得到更多分享


好文推薦:

相關文章
相關標籤/搜索