Redis面試題


1、談談Redis的主從復制流程

有幾個重點:
主節點負責寫,從節點負責讀,slave node 主要用來進行橫向擴容,做讀寫分離,擴容的 slave node 可以提高讀的吞吐量。
必須開啟 master node 的持久化,不建議用 slave node 作為 master node 的數據熱備,因為那樣的話,如果你關掉 master 的持久化,可能在 master 宕機重啟的時候數據是空的,然后可能一經過復制, slave node 的數據也丟了。
當啟動一個 slave node 的時候,它會發送一個 PSYNC 命令給 master node。
slave node 初次連接到 master node,那么會觸發一次 full resynchronization 全量復制。此時 master 會啟動一個后台線程,開始生成一份 RDB 快照文件,同時還會將從客戶端 client 新收到的所有寫命令緩存在內存中。
斷點續傳是通過offset機制。
如果 master node 重啟或者數據出現了變化,那么 slave node 應該根據不同的 run id 區分。
更詳細見:https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-master-slave.md


2、Redis主從復制的斷點續傳機制是什么?
backlog、offset


3、從節點是根據主節點的IP來定位master嗎?
不是,是根據master run id來定位,因為如果更換主節點或者ip更換就不能定位了

4、從節點會過期key嗎?
不會,主節點才會,通過LRU淘汰key之后,會模擬一條del命令給從節點。

5、主備切換高可用的Redis哨兵集群的機制,描述一下
https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-sentinel.md

6、哨兵集群下數據丟失問題有什么解決方法
設置
min-slaves-to-write 1
min-slaves-max-lag 10
表示最少有一個從機,數據復制的延遲不能超過10秒。這樣就可以減少因為異步復制數據的丟失,還有減少腦裂的數據丟失

7、哨兵集群如何實現自動發現機制
通過pub/sub實現,同時往__sentinel__:hello 這個channel發送消息,同時其他哨兵也消費這個消息,感知其他哨兵的存在。
每隔2秒發送一次,內容有自己的host、ip、runid等。

8、講講slave->master選舉算法
如果master被判odown了,大部分哨兵允許主備切換,那么需要選舉一個slave,考慮如下:
1、跟master斷開連接的時長;
2、slave優先級
3、復制offset的位置,復制的越多,越優先
4、如果以上都選不出來,就選runid最小的

9、redis持久化的兩種方式是什么?

RDB:對數據執行周期持久化
AOF:每條命令寫入日志,append-only模式,重啟后通過回放aof日志構建所有數據集

10、redis的RDB持久化優缺點是什么?
rdb是多個數據文件(分時段的處理),非常適合冷備。
對redis提供對外服務的性能影響非常少,因為redis只要fork一個子進程執行磁盤io來持久化
比aof重啟更加快速,更快恢復數據
缺點是,沒有AOF那么的更少的丟失數據,因為RDB需要5分鍾或更久持久化一次,更容易在master故障時丟失數據。

11、如果保證Redis的高並發和高可用?
這個題目比較大。說中幾點即可。參考
https://blog.csdn.net/zero__007/article/details/86564520

12、如何保證Redis和數據庫的雙寫一致性?
主要考查點是Cache Aside Pattern中的更新數據,先寫數據庫,再刪緩存

13、redis 都有哪些數據類型?分別在哪些場景下使用比較合適?
過於基礎,除了對初級開發,很少會問
https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-data-types.md

14、Redis的數據過期策略是什么?內存淘汰機制都有哪些?
過期策略就是內存淘汰,並不是定時檢查是否過期。
內存淘汰機制:
noeviction: 當內存不足以容納新寫入數據時,新寫入操作會報錯,這個一般沒人用吧,實在是太惡心了。
allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最常用的)。
allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個 key,這個一般沒人用吧,為啥要隨機,肯定是把最近最少使用的 key 給干掉啊。
volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的 key(這個一般不太合適)。
volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個 key。
volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的 key 優先移除。

15、Redis寫的並發競爭如何解決
1、用第三方的分布式鎖,比如用zookeeper的node實現
2、用redis的自身樂觀鎖實現(事務),即先watch、multi、set、exec事務實現。
偽代碼:

WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC

 


3、紅鎖實現,具體算法見http://www.redis.cn/topics/distlock.html,用Redisson客戶端實現的主要方式:

public class DistributedRedisLock {
private static Redisson redisson = RedissonManager.getRedisson();
private static final String LOCK_TITLE = "redisLock_";

public static void acquire(String lockName){
String key = LOCK_TITLE + lockName;
RLock mylock = redisson.getLock(key);
mylock.lock(2, TimeUnit.MINUTES); //lock提供帶timeout參數,timeout結束強制解鎖,防止死鎖
System.err.println("======lock======"+Thread.currentThread().getName());
}

public static void release(String lockName){
String key = LOCK_TITLE + lockName;
RLock mylock = redisson.getLock(key);
mylock.unlock();
System.err.println("======unlock======"+Thread.currentThread().getName());
}
}

 

16、如何解決緩存雪崩和穿透
https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-caching-avalanche-and-caching-penetration.md

  • 事前:Redis 高可用,主從+哨兵,Redis cluster,避免全盤崩潰。
  • 事中:本地 ehcache 緩存 + hystrix 限流&降級,避免 MySQL 被打死。
  • 事后:Redis 持久化,一旦重啟,自動從磁盤上加載數據,快速恢復緩存數據。

在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個key只允許一個線程查詢數據和寫緩存,其他線程等待。

可以通過緩存reload機制,預先去更新緩存,再即將發生大並發訪問前手動觸發加載緩存
不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻
做二級緩存,或者雙緩存策略。A1為原始緩存,A2為拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置為短期,A2設置為長期。

使用Sentinel來降級。

17、講講Redis cluster 的高可用與主備切換原理
redis cluster 的高可用的原理,幾乎跟哨兵是類似的。

判斷節點宕機
如果一個節點認為另外一個節點宕機,那么就是 pfail,主觀宕機。如果多個節點都認為另外一個節點宕機了,那么就是 fail,客觀宕機,跟哨兵的原理幾乎一樣,sdown,odown。

在 cluster-node-timeout 內,某個節點一直沒有返回 pong,那么就被認為 pfail。

如果一個節點認為某個節點 pfail 了,那么會在 gossip ping 消息中,ping 給其他節點,如果超過半數的節點都認為 pfail 了,那么就會變成 fail。

從節點過濾
對宕機的 master node,從其所有的 slave node 中,選擇一個切換成 master node。

檢查每個 slave node 與 master node 斷開連接的時間,如果超過了 cluster-node-timeout * cluster-slave-validity-factor,那么就沒有資格切換成 master。

從節點選舉
每個從節點,都根據自己對 master 復制數據的 offset,來設置一個選舉時間,offset 越大(復制數據越多)的從節點,選舉時間越靠前,優先進行選舉。

所有的 master node 開始 slave 選舉投票,給要進行選舉的 slave 進行投票,如果大部分 master node(N/2 + 1)都投票給了某個從節點,那么選舉通過,那個從節點可以切換成 master。

從節點執行主備切換,從節點切換為主節點。

與哨兵比較
整個流程跟哨兵相比,非常類似,所以說,redis cluster 功能強大,直接集成了 replication 和 sentinel 的功能。

18、聊聊Redis分布式尋址算法
首先要明白hash尋址只是負載均衡尋址算法的其中一種,就如同nginx提供4種主要算法,round-robin、ip-hash、least-connected、weighted(權重),redis主要利用hash尋址實現。

只撿重要的說,那就是一致性哈希(包含虛擬節點)和hash slot算法
一致性hash見:
https://my.oschina.net/xianggao/blog/394545?fromerr=Df6BNkP4
hash slot算法:
https://www.cnblogs.com/abc-begin/p/8203613.html

redis cluster 有固定的 16384 個 hash slot,對每個 key 計算 CRC16 值,然后對 16384 取模,可以獲取 key 對應的 hash slot。
redis cluster 中每個 master 都會持有部分 slot,比如有 3 個 master,那么可能每個 master 持有 5000 多個 hash slot。hash slot 讓 node 的增加和移除很簡單,增加一個 master,就將其他 master 的 hash slot 移動部分過去,減少一個 master,就將它的 hash slot 移動到其他 master 上去。移動 hash slot 的成本是非常低的。客戶端的 api,可以對指定的數據,讓他們走同一個 hash slot,通過 hash tag 來實現。任何一台機器宕機,另外兩個節點,不影響的。因為 key 找的是 hash slot,不是機器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM