面試被吊打 - Redis原理

小張興沖沖去面試,結果被面試官吊打!

小張:java

面試官,你好。我是來參加面試的。程序員

面試官:web

你好,小張。我看了你的簡歷,熟練掌握Redis,那麼我就隨便問你幾個Redis相關的問題吧。首先個人問題是,Redis是單線程仍是多線程呢?面試

小張:redis

Redis不一樣版本之間採用的線程模型是不同的,在Redis4.0版本以前使用的是單線程模型,在4.0版本以後增長了多線程的支持。算法

在4.0以前雖然咱們說Redis是單線程,也只是說它的網絡I/O線程以及Set 和 Get操做是由一個線程完成的。可是Redis的持久化、集羣同步仍是使用其餘線程來完成。數據庫

4.0以後添加了多線程的支持,主要是體如今大數據的異步刪除功能上,例如 unlink keyflushdb asyncflushall async服務器

面試官:微信

回答的很好,那爲何Redis在4.0以前會選擇使用單線程?並且使用單線程還那麼快?網絡

小張:

選擇單線程我的以爲主要是使用簡單,不存在鎖競爭,能夠在無鎖的狀況下完成全部操做,不存在死鎖和線程切換帶來的性能和時間上的開銷,但同時單線程也不能徹底發揮出多核CPU的性能。

至於爲何單線程那麼快我以爲主要有如下幾個緣由:

  1. Redis 的大部分操做都在內存中完成,內存中的執行效率自己就很快,而且採用了高效的數據結構,好比哈希表和跳錶。
  2. 使用單線程避免了多線程的競爭,省去了多線程切換帶來的時間和性能開銷,而且不會出現死鎖。
  3. 採用 I/O 多路複用機制處理大量客戶端的Socket請求,由於這是基於非阻塞的 I/O 模型,這就讓Redis能夠高效地進行網絡通訊,I/O的讀寫流程也再也不阻塞。

面試官:

不錯,那Redis是如何實現數據不丟失的呢?

小張:

Redis數據是存儲在內存中的,爲了保證Redis數據不丟失,那就要把數據從內存存儲到磁盤上,以便在服務器重啓後還可以從磁盤中恢復原有數據,這就是Redis的數據持久化。Redis數據持久化有三種方式。

  • AOF 日誌(Append Only File,文件追加方式):記錄全部的操做命令,並以文本的形式追加到文件中。
  • RDB 快照(Redis DataBase):將某一個時刻的內存數據,以二進制的方式寫入磁盤。
  • 混合持久化方式:Redis 4.0 新增了混合持久化的方式,集成了 RDB 和 AOF 的優勢。

面試官:

那你分別說說 AOF和 RDB的實現原理吧。

小張:

AOF採用的是寫後日志的方式,Redis先執行命令把數據寫入內存,而後再記錄日誌到文件中。AOF日誌記錄的是操做命令,不是實際的數據,若是採用AOF方法作故障恢復時須要將全量日誌都執行一遍。

RDB採用的是內存快照的方式,它記錄的是某一時刻的數據,而不是操做,因此採用RDB方法作故障恢復時只須要直接把RDB文件讀入內存便可,實現快速恢復。

面試官:

你剛提到了AOF採用的是 「寫後日志」 的方式,咱們平時用的MySQL則採用的是 「寫前日誌」,那 Redis爲何要先執行命令,再把數據寫入日誌呢?

小張:額頭開始冒汗,問的是些啥問題呀。。。

額,這個主要是因爲Redis在寫入日誌以前,不對命令進行語法檢查,因此只記錄執行成功的命令,避免出現記錄錯誤命令的狀況,並且在命令執行後再寫日誌不會阻塞當前的寫操做。

面試官:

後寫日誌又有什麼風險呢?

小張:

我... 這個我不會。

面試官:

好吧,後寫日誌主要有兩個風險可能會發生:

  • 數據可能會丟失:若是 Redis 剛執行完命令,此時發生故障宕機,會致使這條命令存在丟失的風險。
  • 可能阻塞其餘操做:AOF 日誌其實也是在主線程中執行,因此當 Redis 把日誌文件寫入磁盤的時候,仍是會阻塞後續的操做沒法執行。

我還有個問題是 RDB作快照時會阻塞線程嗎?

小張:

Redis 提供了兩個命令來生成 RDB 快照文件,分別是 savebgsavesave 命令在主線程中執行,會致使阻塞。而 bgsave 命令則會建立一個子進程,用於寫入 RDB 文件的操做,避免了對主線程的阻塞,這也是 Redis RDB 的默認配置。

面試官:

RDB 作快照的時候數據能修改嗎?

小張:

save是同步的會阻塞客戶端命令,bgsave的時候是能夠修改的。

面試官:

那Redis是怎麼解決在bgsave作快照的時候容許數據修改呢?

小張:(你咋還問。。。我™不會啊!)

額,這個我不太清楚...


面試官:

這裏主要是利用 bgsave的子線程實現的,具體操做以下:

  • 若是主線程執行讀操做,則主線程和 bgsave 子進程互相不影響;
  • 若是主線程執行寫操做,則被修改的數據會複製一份副本,而後 bgsave子進程會把該副本數據寫入 RDB 文件,在這個過程當中,主線程仍然能夠直接修改原來的數據。


要注意,Redis 對 RDB 的執行頻率很是重要,由於這會影響快照數據的完整性以及 Redis 的穩定性,因此在 Redis 4.0 後,增長了 AOF 和 RDB 混合的數據持久化機制: 把數據以 RDB 的方式寫入文件,再將後續的操做命令以 AOF 的格式存入文件,既保證了 Redis 重啓速度,又下降數據丟失風險。

小張:

學到了學到了。

面試官:

那你再跟我說說Redis如何實現高可用吧?

小張:

Redis實現高可用主要有三種方式:主從複製、哨兵模式,以及 Redis 集羣。

主從複製

將從前的一臺 Redis 服務器,同步數據到多臺從 Redis 服務器上,即一主多從的模式,這個跟MySQL主從複製的原理同樣。


哨兵模式

使用 Redis 主從服務的時候,會有一個問題,就是當 Redis 的主從服務器出現故障宕機時,須要手動進行恢復,爲了解決這個問題,Redis 增長了哨兵模式(由於哨兵模式作到了能夠監控主從服務器,而且提供自動容災恢復的功能)。


Redis Cluster(集羣)

Redis Cluster 是一種分佈式去中心化的運行模式,是在 Redis 3.0 版本中推出的 Redis 集羣方案,它將數據分佈在不一樣的服務器上,以此來下降系統對單主節點的依賴,從而提升 Redis 服務的讀寫性能。


面試官:

使用哨兵模式在數據上有副本數據作保證,在可用性上又有哨兵監控,一旦master宕機會選舉salve節點爲master節點,這種已經知足了咱們的生產環境須要,那爲何還須要使用集羣模式呢?

小張:

額,哨兵模式歸根節點仍是主從模式,在主從模式下咱們能夠經過增長slave節點來擴展讀併發能力,可是沒辦法擴展寫能力和存儲能力,存儲能力只能是master節點可以承載的上限。因此爲了擴展寫能力和存儲能力,咱們就須要引入集羣模式。

面試官:

集羣中那麼多Master節點,redis cluster在存儲的時候如何肯定選擇哪一個節點呢?

小張:

這應該是使用了某種hash算法,可是我不太清楚。。。


面試官:

那好,今天的面試就到這裏吧,你先回去等咱們的面試通知。

小張:

好的,謝謝面試官,你能告訴我redis cluster怎麼實現節點選擇的嗎?

面試官:

Redis Cluster採用的是類一致性哈希算法實現節點選擇的,至於什麼是一致性哈希算法你本身回去看看。

Redis Cluster將本身分紅了16384個Slot(槽位),哈希槽相似於數據分區,每一個鍵值對都會根據它的 key,被映射到一個哈希槽中,具體執行過程分爲兩大步。

  • 根據鍵值對的 key,按照 CRC16 算法計算一個 16 bit 的值。
  • 再用 16bit 值對 16384 取模,獲得 0~16383 範圍內的模數,每一個模數表明一個相應編號的哈希槽。

每一個Redis節點負責處理一部分槽位,假如你有三個master節點 ABC,每一個節點負責的槽位以下:

節點 處理槽位
A 0-5000
B 5001 - 10000
C 10001 - 16383

這樣就實現了cluster節點的選擇。

好了,各位看官朋友們,Redis原理的這些面試點大家記住了嗎?但願大家的面試不會被這個問題難倒喲~



End




乾貨分享



這裏爲你們準備了一份小小的禮物,關注公衆號,輸入以下代碼,便可得到百度網盤地址,無套路領取!

001:《程序員必讀書籍》
002:《從無到有搭建中小型互聯網公司後臺服務架構與運維架構》
003:《互聯網企業高併發解決方案》
004:《互聯網架構教學視頻》
006:《SpringBoot實現點餐系統》
007:《SpringSecurity實戰視頻》
008:《Hadoop實戰教學視頻》
009:《騰訊2019Techo開發者大會PPT》

010: 微信交流羣






近期熱文top



一、關於JWT Token 自動續期的解決方案

二、SpringBoot開發祕籍-事件異步處理

三、架構師之路-服務器硬件掃盲

四、基於Prometheus和Grafana的監控平臺 - 環境搭建

五、RocketMQ進階 - 事務消息



我就知道你「在看」


本文分享自微信公衆號 - JAVA日知錄(javadaily)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索