通過FAQ簡單瞭解Redis

1. Redis與其他的鍵值對存儲有什麼不同?

2個主要原因。(1) Redis支持多種複雜的數據類型,並且在這些數據類型上定義了原子操作。可直接暴露給程序員;(2) Redis不僅是一個內存數據庫,還支持數據持久化到磁盤。實現了在內存容量內的高速讀寫數據。

2. Redis的內存佔用量是多少?

64 bit計算機爲例。

  • 一個空的Redis實例使用約3MB的內存。
  • 1百萬個小鍵->字符串值對使用〜85MB的內存。
  • 1百萬個鍵->哈希值(代表具有5個字段的對象)使用約160 MB的內存。

3. 無法擁有比內存更大的數據集。 能改變這一點嗎?

過去,Redis開發人員曾嘗試使用虛擬內存和其他系統來允許大於RAM的數據集。 因此,目前尚無計劃爲Redis創建磁盤後端。 畢竟,Redis的大部分功能都是其當前設計的直接結果。

如果你真正的問題不是所需的總RAM,而是需要將數據集拆分爲多個Redis實例的事實,請閱讀Redis官方文檔 分區以獲取更多信息。

4. 將Redis與持久化數據庫一起使用是一個好主意嗎?

是的。一個常見的設計模式是:有少量數據需要經常寫,將這些數據放到Redis中,最終與磁盤數據庫中的數據保持一致。

5. 有什麼辦法可以降低Redis的內存使用量?

見官方的 Redis內存優化

6. 如果Redis內存不足,會發生什麼?

Redis可能會被Linux內核OOM Killer殺死,由於錯誤而崩潰,或者開始變慢。

Redis具有內置保護功能,允許用戶使用配置文件中的maxmemory選項設置Redis可以使用的內存限制,從而設置內存使用的最大限制。 如果達到此限制,Redis將會只接受只讀命令,發送錯誤給寫命令。

INFO命令返回Redis當前的內存使用量,可以據此寫腳本監控Redis服務。

7. Redis磁盤快照是原子操作嗎?

對於Redis而言,命令的原子性指的是:一個操作的不可以再分,操作要麼執行,要麼不執行。

Redis 支持將當前數據的快照存成一個數據文件的持久化機制。Redis藉助了fork命令的copy on write機制。在生成快照時,將當前進程fork出一個子進程,然後在子進程中循環所有的數據,將數據寫成爲RDB文件,而主進程繼續接受讀寫請求。Redis持久化與數據庫持久化

Redis持久化:RDB(快照)和AOF(寫命令)

8. Redis是單線程的。 如何利用多個CPU /內核?

通常而言,CPU並不是Redis的使用瓶頸。 主要瓶頸是內存或網絡限制。所以,如果使用的Redis命令多爲O(N)O(log(N))時間複雜度,那麼基本上不會出現CPU瓶頸的情況。

爲了最大程度地利用CPU,可以在同一機器中啓動多個 Redis 實例,並將它們視爲不同的服務器。詳情見 Redis官方文檔 Partitioning page

在Redis 4.0之後,後端刪除對象、blocking commands 實現了多線程。

9. 一個Redis實例可以容納的最大密鑰數是多少? 哈希,列表,集合,排序集合中元素的最大數量是多少?

Redis最多可以處理232 個key。實驗表明,每一個Redis實例至少可以處理2.5億個key。

每一個hashlistsetsorted set最多可容納232 個元素。

換句話說,您的限制可能是系統中的可用內存,而不是Redis本身。

10. 爲什麼我的slave 和master中的key數量不同?

redis提供兩種方式進行持久化,一種是RDB持久化(原理是將Reids在內存中的數據庫記錄定時dump到磁盤上的RDB持久化),另外一種是AOF持久化(原理是將Reids的操作日誌以追加的方式寫入文件)。

如果你爲這些key設置了 Redis 過期時間,那麼這是正常現象。

  • Master在與slave的第一次同步時生成RDB文件。
  • RDB文件不包括master中已過期但仍在內存中的key。這些key仍然存在於master的內存中(邏輯上,這些key已經過期了,所以在master上認爲這些key已經不存在了),但是通過INFO命令DBSIZE命令能都看到這些信息。
  • slave讀取RDB文件時,並不會加載這些過期的key。

11. Redis實際上是什麼意思?

REmote DIctionary Server的縮寫。

12. Redis如何保證原子性?

Redis是單線程的,這也就是爲什麼Redis能夠保證原子性。

對於Redis而言,命令的原子性指的是:一個操作的不可以再分,操作要麼執行,要麼不執行。

問題來了,既然Redis是單線程,可以保證原子性,那麼它的異步和非阻塞是什麼?單線程如何實現異步和非阻塞?

13. Redis單線程,如何實現異步和非阻塞

再查閱了很多資料之後,我發現我對於同步/異步阻塞/非阻塞以及單線程/多線程的概念有些不清晰,下面給出簡單解釋。

同步/異步:首先同步和異步主要是從消息通知機制來講起的。

同步:一個任務的完成必須依賴另一個任務,兩個要麼都成功要麼都失敗,是一種可靠的任務序列。當一個同步調用發生後,調用者必須等待返回結果,才能繼續後面任務的執行。

異步:不需要等待被依賴任務的完成,只需要完成自己的任務就可以,所以是不可靠任務序列。當一個異步調用發生後,調用者不必等待返回結果,調用者可以去做其他的事情,被調用部件在處理完成後,通過(狀態、通知、回調)來通知調用者。

阻塞/非阻塞:阻塞和非阻塞和調用者等待消息通知時的狀態有關。很重要,不要和同步混淆。

阻塞:調用者在等待通知的過程中,不能執行其他業務,傻傻的等待通知到來。

非阻塞:和阻塞相反,調用者可以去執行其他業務。

14. RDB持久化和AOF持久化

原文 redis的持久化方式RDB和AOF的區別
原文 Redis詳解(六)------ RDB 持久化
原文 Redis持久化:RDB(快照)和AOF(寫命令)

RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換之前的文件,用二進制壓縮存儲。
RDB持久化可以手動觸發和自動觸發,保存RDB數據有兩個命令,一個是save,一個是bgsave(常用這個,會fork一個子進程來實現生成RDB文件,不阻塞主進程)。
在這裏插入圖片描述
AOF持久化以日誌的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。
在這裏插入圖片描述

二者選擇的標準,就是看系統是願意犧牲一些性能,換取更高的緩存一致性(aof),還是願意寫操作頻繁的時候,不啓用備份來換取更高的性能,待手動運行save的時候,再做備份(rdb)。rdb這個就有些最終一致性(eventually consistent)的意思了。不過生產環境其實更多都是二者結合使用的。

15. 如何保證Redis的主從數據一致?

詳情見 原文 Redis主從複製原理總結

假設 Redis 的主從架構如下:
在這裏插入圖片描述
對其總結一下:
Redis主從複製可以根據是否是全量分爲全量同步增量同步

  • 全量同步。一般發生在slave初始化節點,因爲slave需要把master上的所有數據都複製一份。具體過程如下:
    在這裏插入圖片描述
  • 增量同步mater的寫操作要同步到slave上。master每執行一個寫命令就向slave發送相同的寫命令,slave接收並執行收到的寫命令。

redis 的策略是,無論如何,首先會嘗試進行增量同步,如不成功,要求slave進行全量同步。

master爲複製流維護一個內存緩衝區(in-memory backlog)masterslave都維護一個複製偏移量(replication offset)master run id,當連接斷開時,slave會重新連接上master,然後請求繼續複製,假如master和slave的兩個master run id相同,並且指定的偏移量在內存緩衝區中還有效,複製就會從上次中斷的點開始繼續。如果其中一個條件不滿足,就會進行完全重新同步(在2.8版本之前就是直接進行完全重新同步)。因爲主運行id不保存在磁盤中,如果slave重啓了的話就只能進行完全同步了。

部分同步這個新特性內部使用PSYNC命令,舊的實現中使用SYNC命令。Redis2.8版本可以檢測出它所連接的服務器是否支持PSYNC命令,不支持的話使用SYNC命令。

16. Redis如何保證高可用?

詳情見原文 Redis系列八:redis主從複製和哨兵

Redis 主從的缺點

  1. 主從複製。若主節點出現問題,則不能提供服務,需要人工修改配置將從變主
  2. 主從複製。主節點的寫能力單機,能力有限
  3. 單機節點的存儲能力也有限

主從故障如何故障轉移(failover

  1. 主節點(master)故障,從節點slave端執行slaveof no one後變成新主節點;
  2. 其它的節點成爲新主節點的從節點,並從新節點複製數據;
  3. 需要人工干預,無法實現高可用。

基於Redis主從的確定,所以 Redis通過Redis Sentinel來保證高可用。

Redis Sentinel 也叫哨兵機制。原理:當主節點出現故障時,由Redis Sentinel自動完成故障發現和轉移,並通知應用方,實現高可用性。

Sentinel的功能如下:

  • 監控(monitoring)。Sentinel會不斷檢查master和slave是否按預期工作。
  • 通知(notification)。若Redis實例出現問題,Sentinel可以通過API通知系統管理員或其他計算機程序。
  • 自動故障轉移(automatic failover)。如果master未按預期工作,則Sentinel可以啓動故障轉移,將slave升級爲master,其他slave從新的master進行同步,當應用程序連接時候,通知使用Redis服務器的應用程序要使用的新地址。
  • 配置提供者(configuration provider)。

Redis哨兵(Sentinel)模式
Redis 官方文檔 sentinel

17. Redis主從不一致怎麼辦

詳情見 原文 redis 數據庫主從不一致問題解決方案

18. 如何保證數據庫和redis一致

詳情請見 Redis 如何保持和MySQL數據一致

讀請求:先Redis,後Mysql。
寫請求:先Mysql,後刪Redis,重新寫入。

MySQL處理實時性數據,例如金融數據、交易數據
Redis處理實時性要求不高的數據,例如網站最熱貼排行榜,好友列表等

19. Redis集羣

詳情見 Redis集羣詳解

Redis 有3中集羣模式:

  1. 主從模式。單機數據基本上就是全部數據。
  2. sentinel模式。單機數據基本上就是全部數據。
  3. cluster模式。所有Redis節點的數據之和纔是全部數據。

主從模式

特點:

master可以進行讀寫操作,當讀寫操作導致數據變化時會自動將數據同步給slave

slave一般都是隻讀的,並且接收master同步過來的數據

一個master可以擁有多個slave,但是一個slave只能對應一個master

slave掛了不影響其他slave的讀和master的讀和寫,重新啓動後會將數據從master同步過來

master掛了以後,不影響slave的讀,但redis不再提供寫服務,master重啓後redis將重新對外提供寫服務。master掛了以後,不會自動在slave節點中重新選一個master,需要手動操作。

工作機制:

當slave啓動後,主動向master發送SYNC命令。master接收到SYNC命令後在後臺保存快照(RDB持久化)和緩存保存快照這段時間的命令,然後將保存的快照文件和緩存的命令發送給slave。slave接收到快照文件和命令後加載快照文件和緩存的執行命令。

全量複製完成後,進行增量複製,master每次接收到的寫命令都會同步發送給slave,保證主從數據一致性。

Sentinel(哨兵) 模式

由於上面的主從模式沒有failover,master掛了(Redis不在對外提供寫操作),需要手動切換,不滿足高可用性,所以產生了Sentinel模式

特點:

sentinel模式是建立在主從模式的基礎上,如果只有一個Redis節點,sentinel就沒有任何意義

當master掛了以後,sentinel會在slave中選擇一個做爲master,並修改它們的配置文件,其他slave的配置文件也會被修改,比如slaveof屬性會指向新的master

當舊的master重新啓動後,它將不再是master而是做爲slave接收新的master的同步數據

因爲sentinel也是一個進程有掛掉的可能(單點故障),所以sentinel也會啓動多個形成一個sentinel集羣。多sentinel配置的時候,sentinel之間也會自動監控

當主從模式配置密碼時,sentinel也會同步將配置信息修改到配置文件中,不需要擔心

一個sentinelsentinel集羣可以管理多個主從Redis,多個sentinel也可以監控同一個Redis

sentinel最好不要和Redis部署在同一臺機器,避免當這臺機器出問題時,RedisSentinel都掛了。

工作機制:

每個sentinel以每秒鐘一次的頻率向它所知的master,slave以及其他sentinel實例發送一個 PING 命令。心跳檢測

如果一個實例距離最後一次有效回覆 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被sentinel標記爲主觀下線。 如果一個master被標記爲主觀下線,則正在監視這個master的所有sentinel要以每秒一次的頻率確認master的確進入了主觀下線狀態

當有足夠數量的sentinel(大於等於配置文件指定的值)在指定的時間範圍內確認master的確進入了主觀下線狀態, 則master會被標記爲客觀下線

在一般情況下, 每個sentinel會以每 10 秒一次的頻率向它已知的所有master,slave發送 INFO 命令 。 當master被sentinel標記爲客觀下線時,sentinel向下線的master的所有slave發送 INFO 命令的頻率會從 10 秒一次改爲 1 秒一次

若沒有足夠數量的sentinel同意master已經下線,master的客觀下線狀態就會被移除;若master重新向sentinel的 PING 命令返回有效回覆,master的主觀下線狀態就會被移除。

當使用sentinel模式的時候,client 就不要直接連接Redis,而是連接sentinel的ip和port,由sentinel來提供具體的可提供服務的Redis實現,這樣當master節點掛掉以後,sentinel就會感知並將新的master節點提供給使用者。

Cluster模式

主從模式和Sentinel模式應對的是請求相當多而數據完全能夠存放在一臺機器中的情況。在大數據的情況下,就需要將數據分佈在不同的機器上,這也就是Redis Cluster。

特點:

多個Redis節點網絡互聯,數據共享

所有的節點都是一主一從(也可以是一主多從,),其中從不提供服務,僅作爲備用。

不支持同時處理多個key(如MSET/MGET),因爲Redis需要把key均勻分佈在各個節點上,
併發量很高的情況下同時創建key-value會降低性能並導致不可預測的行爲(見 Redis的分佈式鎖

支持在線增加、刪除節點

客戶端可以連接任何一個主節點進行讀寫

Redis cluster集羣是去中心化的,每個節點都是平等的,連接哪個節點都可以獲取和設置數據。

其餘關於Redis的問題 見 面試中關於Redis的問題看這篇就夠了

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