## redis的面試題地址:
2W字!詳解20道Redis經典面試題:
https://mp.weixin.qq.com/s/fBShKZbuR54yaIzzMR3R7g
redis的數據結構:
https://mp.weixin.qq.com/s/MGcOl1kGuKdA7om0Ahz5IA
Redis 那點破事 | 絕殺面試官 25 問!https://mp.weixin.qq.com/s/_54mD0EiS9R3CvpDXzN0lg
面試被問Redis的持久化,和面試官大戰幾個小時
https://mp.weixin.qq.com/s/MbllU3B7wDU8_VTm48-QaA
## redis為什么那么快?
1、基于純內存操作
2、epoll io多路復用
3、基于hash表,hash對于精準查詢的效率很高,用的rehash 算法避免了哈希碰撞
## 緩存穿透、緩存雪崩、緩存擊穿以及怎么解決?
**緩存穿透**
就是客戶持續向服務器發起對不存在服務器中數據的請求。客戶先在Redis中查詢,查詢不到后去數據庫中查詢。
1.采用布隆過濾器BloomFilter
2.緩存空值
**緩存擊穿**
就是一個很熱門的數據,突然失效,大量請求到服務器數據庫中
1. 互斥鎖,并行請求改為串行
2. 熱點數據永不過期
**緩存雪崩**
就是大量數據同一時間失效。
1.雙層緩存策略
C1為原始緩存,C2為拷貝緩存,C1失效時,可以訪問C2,C1緩存失效時間設置為短期,C2設置為長期
2.不同過期時間
設置不同的過期時間,讓緩存失效的時間點盡量均勻
3.熱點數據永不過期
部分用戶訪問特別頻繁的熱點數據,設置永不過期
## RDB和AOF機制?(如何選擇?reb觸發機制、aof運行機制?優缺點?)
* RDB:在指定的時間間隔能對你的數據進行快照存儲。
* AOF:記錄每次對服務器寫的操作,當服務器重啟的時候會重新執行這些命令來恢復原始的數據
### 持久化方案選擇
#### RDB和AOF的優缺點
RDB和AOF各有優缺點:
**RDB持久化**
* 優點:RDB文件緊湊,體積小,網絡傳輸快,適合全量復制;恢復速度比AOF快很多。當然,與AOF相比,RDB最重要的優點之一是對性能的影響相對較小。
* 缺點:RDB文件的致命缺點在于其數據快照的持久化方式決定了必然做不到實時持久化,而在數據越來越重要的今天,數據的大量丟失很多時候是無法接受的,因此AOF持久化成為主流。此外,RDB文件需要滿足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。
**AOF持久化**
* 與RDB持久化相對應,AOF的優點在于支持秒級持久化、兼容性好,缺點是文件大、恢復速度慢、對性能影響大。
** RDB持久化**
### 1. 工作原理:
* Redis調用fork(),產生一個子進程。
* 子進程把數據寫到一個臨時的RDB文件。
* 當子進程寫完新的RDB文件后,把舊的RDB文件替換掉。
### 2\. 觸發機制
RDB觸發持久化分為手動觸發和自動觸發
1. save 命令(手動觸發)
當客戶端向Redis server發送save命令請求進行持久化時,由于Redis是用一個主線程來處理所有,save命令會阻塞Redis server處理其他客戶端的請求,直到數據同步完成。save命令會阻塞Redis服務器進程,直到RDB文件創建完畢為止,在Redis服務器阻塞期間,服務器不能處理任何命令請求,因此線上環境不推薦使用
2. bgsave命令(手動觸發)
與save命令不同,bgsave是異步執行的,當執行bgsave命令之后,Redis主進程會fork 一個子進程將數據保存到rdb文件中,同步完數據之后,對原有文件進行替換,然后通知主進程表示同步完成。
3. 自動觸發
除了手動觸發RDB持久化,Redis內部還存在自動觸發機制,
在配置中集中配置 save m n 的方式,表示 m秒內數據集存在n次修改時,系統自動觸發bgsave 操作。

1) ?Redis父進程首先判斷:當前是否在執行save,或bgsave/bgrewriteaof(后面會詳細介紹該命令)的子進程,如果在執行則bgsave命令直接返回。bgsave/bgrewriteaof 的子進程不能同時執行,主要是基于性能方面的考慮:兩個并發的子進程同時執行大量的磁盤寫操作,可能引起嚴重的性能問題。
2) ?父進程執行fork操作創建子進程,這個過程中父進程是阻塞的,Redis不能執行來自客戶端的任何命令
3) ?父進程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父進程,并可以響應其他命令
4) ?子進程創建RDB文件,根據父進程內存快照生成臨時快照文件,完成后對原有文件進行原子替換
5) ?子進程發送信號給父進程表示完成,父進程更新統計信息
### 5. 數據恢復 & Redis啟動加載數據
RDB文件的載入工作是在服務器啟動時自動執行的,并沒有專門的命令。但是由于AOF的優先級更高,因此當AOF開啟時,Redis會優先載入AOF文件來恢復數據;
只有當AOF關閉時,才會在Redis服務器啟動時檢測RDB文件,并自動載入。服務器載入RDB文件期間處于阻塞狀態,直到載入完成為止。
所以Redis的內存數據如果很大,會導致數據恢復時間比較長,因此線上實踐更傾向于限制單個Redis的內存不能太大,同時結合Redis Cluster集群使用多節點部署
## AOF持久化
### 1.工作原理
由于需要記錄Redis的每條寫命令,因此AOF不需要觸發, AOF的執行流程包括:
* 命令追加(append):將Redis的寫命令追加到緩沖區aof\_buf;
* 文件寫入(write)和文件同步(sync):根據不同的同步策略將aof\_buf中的內容同步到硬盤;
* 文件重寫(rewrite):定期重寫AOF文件,達到壓縮的目的。

### 2. AOF 持久化配置

### 3. AOF同步策略
同步步驟分為兩步:
* Redis收到寫命令后首先會追加到AOF緩沖區aof\_buf,而不是直接寫入文件系統,因為AOF緩沖區是內存提存的,寫入速度極高,可以避免每次寫入命令到硬盤,導致硬盤IO成為Redis的負載瓶頸
* 通過調用系統函數 fsync() 把AOF緩沖區的數據真正寫到磁盤里面持久化。由于數據是先存儲在緩沖區內存里面,如果碰到斷電,宕機那么緩沖區里面的數據沒來得急落盤就會丟失,因此我們必須有一個相對可靠的機制保證數據落盤。
Redis寫命令寫入磁盤的命令是通過appendfsync來配置的。
appendfsync 三個取值代表三種落盤策略:
* `always`:命令寫入aof緩沖區后立即調用系統fsync操作同步到AOF文件,fsync完成后線程返回。這種情況下,每次有寫命令都要同步到AOF文件,硬盤IO成為性能瓶頸。
* `no`:命令寫入aof緩沖區后調用系統write操作,不對AOF文件做fsync同步;同步由操作系統負責,通常同步周期為30秒。這種情況下,文件同步的時間不可控,且緩沖區中堆積的數據會很多,數據安全性無法保證。
* `everysec`:命令寫入aof緩沖區后調用系統write操作,write完成后線程返回;fsync同步文件操作由專門的線程每秒調用一次。everysec是前述兩種策略的折中,是性能和數據安全性的平衡,因此是Redis的默認配置,也是我們推薦的配置。
### 4\. AOF文件重寫(rewrite)
隨著寫操作的不斷增加,AOF文件會越來越大。例如你遞增一個計數器100次,那么最終結果就是數據集里的計數器的值為最終的遞增結果,但是AOF文件里卻會把這100次操作完整的記錄下來。而事實上要恢復這個記錄,只需要1個命令就行了,也就是說AOF文件里那100條命令其實可以精簡為1條。所以Redis支持這樣一個功能:在不中斷服務的情況下在后臺重建AOF文件。

關于文件重寫的流程,有兩點需要特別注意:
(1)重寫由父進程fork子進程進行;
(2)重寫期間Redis執行的寫命令,需要追加到新的AOF文件中,為此Redis引入了aof\_rewrite\_buf緩存。
對照上圖,文件重寫的流程如下:
1) Redis父進程首先判斷當前是否存在正在執行 bgsave/bgrewriteaof的子進程,如果存在則bgrewriteaof命令直接返回,如果存在bgsave命令則等bgsave執行完成后再執行。前面曾介紹過,這個主要是基于性能方面的考慮。
2) 父進程執行fork操作創建子進程,這個過程中父進程是阻塞的。
3.1) 父進程fork后,bgrewriteaof命令返回”Background append only file rewrite started”信息并不再阻塞父進程,并可以響應其他命令。Redis的所有寫命令依然寫入AOF緩沖區,并根據appendfsync策略同步到硬盤,保證原有AOF機制的正確。
3.2) 由于fork操作使用寫時復制技術,子進程只能共享fork操作時的內存數據。由于父進程依然在響應命令,因此Redis使用AOF重寫緩沖區(圖中的aof\_rewrite\_buf)保存這部分數據,防止新AOF文件生成期間丟失這部分數據。也就是說,bgrewriteaof執行期間,Redis的寫命令同時追加到aof\_buf和aof\_rewirte\_buf兩個緩沖區。
4) 子進程根據內存快照,按照命令合并規則寫入到新的AOF文件。
5.1) 子進程寫完新的AOF文件后,向父進程發信號,父進程更新統計信息,具體可以通過info persistence查看。
5.2) 父進程把AOF重寫緩沖區的數據寫入到新的AOF文件,這樣就保證了新AOF文件所保存的數據庫狀態和服務器當前狀態一致。
5.3) 使用新的AOF文件替換老文件,完成AOF重寫。
#### 重寫觸發:
1. 手動觸發:直接調用bgrewriteaof命令,該命令的執行與bgsave有些類似:都是fork子進程進行具體的工作,且都只有在fork時阻塞。
2. 自動觸發:通過配置`auto-aof-rewrite-percentage`和`auto-aof-rewrite-min-size`來完成
`auto-aof-rewrite-percentage 100`:Redis會記住自從上一次重寫后AOF文件的大小(如果自Redis啟動后還沒重寫過,則記住啟動時使用的AOF文件的大小)。如果當前的文件大小比起記住的那個大小超過指定的百分比,則會觸發重寫。
`auto-aof-rewrite-min-size 64mb`:同時需要設置一個文件大小最小值,只有大于這個值文件才會重寫,以防文件很小,但是已經達到百分比的情況。
要禁用自動的日志重寫功能,我們可以把百分比設置為0:
`auto-aof-rewrite-percentage 0`:禁用日志重寫功能
### 5\. 數據恢復 & Redis啟動加載數據
前面提到過,當AOF開啟時,Redis啟動時會優先載入AOF文件來恢復數據;
只有當AOF關閉時,才會載入RDB文件恢復數據。
## redis事務?(命令是啥,命令作用,存在的意義)
Redis 事務的本質是一組命令的集合,就是一次性、順序性、排他性的執行一個隊列中的一系列命令。
沒有隔離級別、不保證原子性
**Redis事務的三個階段:**
* 開始事務
* 命令入隊
* 執行事務
**watch** key1 key2 ... : 監視一或多個key,如果在事務執行之前,被監視的key被其他命令改動,則事務被打斷 ( 類似樂觀鎖 )
**multi** : 標記一個事務塊的開始( queued )
**exec** : 執行所有事務塊的命令 ( 一旦執行exec后,之前加的監控鎖都會被取消掉 )
**discard** : 取消事務,放棄事務塊中的所有命令
**unwatch** : 取消watch對所有key的監控
## 主從復制?(開啟命令?原理?引出主從不一致的問題)
1. slave 服務啟動,slave 會建立和 master 的連接,發送 sync 命令。
2. master 啟動一個后臺進程將數據庫快照保存到 RDB 文件中
> 注意:此時如果生成 RDB 文件過程中存在寫數據操作會導致 RDB 文件和當前主 redis 數據不一致,所以此時 master 主進程會開始收集寫命令并緩存起來。
3. master 就發送 RDB 文件給 slave
4. slave 將文件保存到磁盤上,然后加載到內存恢復
5. master 把緩存的命令轉發給 slave
## 全量復制和部分復制?
全量復制
1、第一次建立連接進行數據同步是全量復制
2、從節點發送 psync {runid} {offset} 時,runid 與當前主節點的 runid 不匹配則進行全量復制
3、從節點所需要同步數據的偏移量 offset 不在**復制積壓緩沖區**中,也會進行全量復制
部分復制
正常情況下,offect在復制積壓緩沖區的
## 哨兵原理?腦裂?
* 集群監控,即時刻監控著redis的master和slave進程是否是在正常工作。
* 消息通知,就是說當它發現有redis實例有故障的話,就會發送消息給管理員
* 故障自動轉移,如果redis master 節點宕機了的話,它就會將請求轉到slave 節點上,slave升為master。
* 充當配置中心,如果發生了故障轉移,它會通知將master的新地址寫在配置中心告訴客戶端。
哨兵每秒向主節點和從節點發送ping命令,在規定時間內沒有收到pong,
#### 1、什么是腦裂
redis的主從模式下腦裂是指因為網絡問題,導致redis master節點跟redis slave節點和sentinel集群處于不同的網絡分區,此時因為sentinel集群無法感知到 master 的存在,就會將某一個 slave 節點提升為 master 節點。此時就存在兩個不同的 master節點,就像一個大腦分裂成了兩個。
集群腦裂問題中,如果客戶端還在基于原來的 master 節點繼續寫入數據,那么新的master 節點將無法同步這些數據,當網絡問題解決之后,sentinel 集群將原先的master節點降為 slave 節點,此時再從新的 master 中同步數據,將會造成大量的數據丟失。
#### redis 腦裂的解決方案
min-slaves-to-write 3
min-slaves-max-lag 10
第一個參數表示至少 master 要有1個slave節點,才允許寫入
第二個參數表示 slave 連接到 master 的最大延遲時間
## 集群方案?
https://blog.csdn.net/miss1181248983/article/details/90056960
#### 主從模式
一個master可以擁有多個slave,但是一個slave只能對應一個master
缺點:
從上面可以看出,master節點在主從模式中唯一,若master掛掉,則redis無法對外提供寫服務。
#### Sentinel模式
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的主觀下線狀態就會被移除
### Cluster模式
將redis配置文件中的`cluster-enable` 打開即可,每個集群中至少需要三個主數據庫才能正常運行
1、多個redis節點網絡互聯,數據共享
2、所有的節點都是一主一從(也可以是一主多從),其中從不提供服務,僅作為備用
3、客戶端可以連接任何一個主節點進行讀寫
## 過期刪除策略?內存淘汰策略?lru和lfu的區別
**定期刪除** Redis 默認會每秒進行十次過期掃描(100ms一次)隨機刪除20個
**惰性刪除** 查詢時候檢查是否過期,沒過期則返回
1. **no-eviction**:禁止驅逐數據,也就是說當內存不足以容納新寫入數據時,新寫入操作會報錯。
2. **volatile-ttl**:從已設置過期時間的數據集(server.db\[i\].expires)中挑選將要過期的數據淘汰;
3. **volatile-random**:從已設置過期時間的數據集(server.db\[i\].expires)中任意選擇數據淘汰;
4. **allkeys-lru**:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key;
5. **allkeys-random**:從數據集(server.db\[i\].dict)中任意選擇數據淘汰;
6. **volatile-lru**:從已設置過期時間的數據集(server.db\[i\].expires)中挑選最近最少使用的數據淘汰;
4.0 版本后增加以下兩種:
7. **volatile-lfu**:從已設置過期時間的數據集(server.db\[i\].expires)中挑選最不經常使用的數據淘汰;
8. **allkeys-lfu**:當內存不足以容納新寫入數據時,在鍵空間中,移除最不經常使用的 key。
#### LRU和LFU的區別:
LRU是最近最少使用頁面置換算法(Least Recently Used),也就是首先淘汰最長時間未被使用的頁面!
LFU是最近最不常用頁面置換算法(Least Frequently Used),也就是淘汰一定時期內被訪問次數最少的頁!
比如,第二種方法的時期T為10分鐘,如果每分鐘進行一次調頁,主存塊為3,若所需頁面走向為2 1 2 1 2 3 4
注意,當調頁面4時會發生缺頁中斷
若按LRU算法,應換頁面1(1頁面最久未被使用) 但按LFU算法應換頁面3(十分鐘內,頁面3只使用了一次)
可見LRU關鍵是看頁面最后一次被使用到發生調度的時間長短,
而LFU關鍵是看一定時間段內頁面被使用的頻率!
http://www.hmoore.net/sunjianjun/all_content/2210404
## 數據類型,結構、編碼?
## redis采用的I/O事件模型-epoll
## 分布式鎖?
## 布隆過濾器原理?
## 跳躍表skiplist的實現原理?
skiplist 會從 header 的頂層出發遍歷搜索找到第一個比目標元素小的開始降一層,直到降到最底層
字典和hash的實現原理
基本的命令?
各類型的適用場景?
## Redis常見性能問題和解決方案?
(1) Master最好不要做任何持久化工作,如RDB內存快照和AOF日志文件
(2) 如果數據比較重要,某個Slave開啟AOF備份數據,策略設置為每秒同步一次
(3) 為了主從復制的速度和連接的穩定性,Master和Slave最好在同一個局域網內
(4) 盡量避免在壓力很大的主庫上增加從庫
(5) 主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3…
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他不變。
https://blog.csdn.net/a519640026/article/details/106264559?spm=1001.2014.3001.5501 面試題
redis、memcached、mongodb 區別及優缺點使用場景?
## MySQL與MongoDB之間最基本的差別是什么?
MySQL和MongoDB兩者都是免費開源的數據庫。MySQL和MongoDB有許多基本差別包括數據的表示(data representation),查詢,關系,事務,schema的設計和定義,標準化(normalization),速度和性能。
通過比較MySQL和MongoDB,實際上我們是在比較關系型和非關系型數據庫,即數據存儲結構不同。
https://blog.csdn.net/Design407/article/details/106691804 mongodb
- 消息隊列
- 為什么要用消息隊列
- 各種消息隊列產品的對比
- 消息隊列的優缺點
- 如何保證消息隊列的高可用
- 如何保證消息不丟失
- 如何保證消息不會重復消費?如何保證消息的冪等性?
- 如何保證消息消費的順序性?
- 基于MQ的分布式事務實現
- Beanstalk
- PHP
- 函數
- 基礎
- 基礎函數題
- OOP思想及原則
- MVC生命周期
- PHP7.X新特性
- PHP8新特性
- PHP垃圾回收機制
- php-fpm相關
- 高級
- 設計模式
- 排序算法
- 正則
- OOP代碼基礎
- PHP運行原理
- zavl
- 網絡協議new
- 一面
- TCP和UDP
- 常見狀態碼和代表的意義以及解決方式
- 網絡分層和各層有啥協議
- TCP
- http
- 二面
- TCP2
- DNS
- Mysql
- 鎖
- 索引
- 事務
- 高可用?高并發?集群?
- 其他
- 主從復制
- 主從復制數據延遲
- SQL的語?分類
- mysqlQuestions
- Redis
- redis-question
- redis為什么那么快
- redis的優缺點
- redis的數據類型和使用場景
- redis的數據持久化
- 過期策略和淘汰機制
- 緩存穿透、緩存擊穿、緩存雪崩
- redis的事務
- redis的主從復制
- redis集群架構的理解
- redis的事件模型
- redis的數據類型、編碼、數據結構
- Redis連接時的connect與pconnect的區別是什么?
- redis的分布式鎖
- 緩存一致性問題
- redis變慢的原因
- 集群情況下,節點較少時數據分布不均勻怎么辦?
- redis 和 memcached 的區別?
- 基本算法
- MysqlNew
- 索引new
- 事務new
- 鎖new
- 日志new
- 主從復制new
- 樹結構
- mysql其他問題
- 刪除
- 主從配置
- 五種IO模型
- Kafka
- Nginx
- trait
- genergtor 生成器
- 如何實現手機掃碼登錄功能
- laravel框架的生命周期