文章目錄
- 1. Redis與其他的鍵值對存儲有什麼不同?
- 2. Redis的內存佔用量是多少?
- 3. 無法擁有比內存更大的數據集。 能改變這一點嗎?
- 4. 將Redis與持久化數據庫一起使用是一個好主意嗎?
- 5. 有什麼辦法可以降低Redis的內存使用量?
- 6. 如果Redis內存不足,會發生什麼?
- 7. Redis磁盤快照是原子操作嗎?
- 8. Redis是單線程的。 如何利用多個CPU /內核?
- 9. 一個Redis實例可以容納的最大密鑰數是多少? 哈希,列表,集合,排序集合中元素的最大數量是多少?
- 10. 爲什麼我的slave 和master中的key數量不同?
- 11. Redis實際上是什麼意思?
- 12. Redis如何保證原子性?
- 13. Redis單線程,如何實現異步和非阻塞
- 14. RDB持久化和AOF持久化
- 15. 如何保證Redis的主從數據一致?
- 16. Redis如何保證高可用?
- 17. Redis主從不一致怎麼辦
- 18. 如何保證數據庫和redis一致
- 19. 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持久化與數據庫持久化
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。
每一個hash
、list
、set
、sorted set
最多可容納232 個元素。
換句話說,您的限制可能是系統中的可用內存,而不是Redis
本身。
10. 爲什麼我的slave 和master中的key數量不同?
redis
提供兩種方式進行持久化,一種是RDB持久化
(原理是將Reids在內存中的數據庫記錄定時dump到磁盤上的RDB持久化),另外一種是AOF持久化
(原理是將Reids的操作日誌以追加的方式寫入文件)。
如果你爲這些key設置了 Redis
過期時間,那麼這是正常現象。
Maste
r在與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)
。master
和slave
都維護一個複製偏移量(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 主從的缺點
- 主從複製。若主節點出現問題,則不能提供服務,需要人工修改配置將從變主
- 主從複製。主節點的寫能力單機,能力有限
- 單機節點的存儲能力也有限
主從故障如何故障轉移(failover
)
- 主節點(
master
)故障,從節點slave
端執行slaveof no one
後變成新主節點; - 其它的節點成爲新主節點的從節點,並從新節點複製數據;
- 需要人工干預,無法實現高可用。
基於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中集羣模式:
主從模式
。單機數據基本上就是全部數據。sentinel模式
。單機數據基本上就是全部數據。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
也會同步將配置信息修改到配置文件中,不需要擔心
一個sentinel
或sentinel
集羣可以管理多個主從Redis
,多個sentinel也可以監控同一個Redis
sentinel
最好不要和Redis
部署在同一臺機器,避免當這臺機器出問題時,Redis
和Sentinel
都掛了。
工作機制:
每個
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的問題看這篇就夠了