欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

2021年最新Redis面試題匯總(3)

 更新時間:2021年07月15日 17:31:56   作者:java李楊勇  
在程序員面試過程中redis相關(guān)的知識是常被問到的話題。這篇文章主要介紹了幾道Redis面試題,整理一下分享給大家,感興趣的小伙伴們可以參考一下

1、Redis 怎么保證高可用、有哪些集群模式

主從復制、哨兵模式、集群模式。

2、主從復制

在當前最新的 Redis 6.0 中,主從復制的完整過程如下:

1)開啟主從復制

通常有以下三種方式:

  • 在 slave 直接執(zhí)行命令:slaveof <masterip> <masterport>
  • 在 slave 配置文件中加入:slaveof <masterip> <masterport>
  • 使用啟動命令:--slaveof <masterip> <masterport>

注:在 Redis 5.0 之后,slaveof 相關(guān)命令和配置已經(jīng)被替換成 replicaof,例如 replicaof <masterip> <masterport>。為了兼容舊版本,通過配置的方式仍然支持 slaveof,但是通過命令的方式則不行了。

2)建立套接字(socket)連接

slave 將根據(jù)指定的 IP 地址和端口,向 master 發(fā)起套接字(socket)連接,master 在接受(accept) slave 的套接字連接之后,為該套接字創(chuàng)建相應的客戶端狀態(tài),此時連接建立完成。

3)發(fā)送PING命令

slave 向 master 發(fā)送一個 PING 命令,以檢査套接字的讀寫狀態(tài)是否正常、 master 能否正常處理命令請求。

4)身份驗證

slave 向 master 發(fā)送 AUTH password 命令來進行身份驗證。

5)發(fā)送端口信息

在身份驗證通過后后, slave 將向 master 發(fā)送自己的監(jiān)聽端口號, master 收到后記錄在 slave 所對應的客戶端狀態(tài)的 slave_listening_port 屬性中。

6)發(fā)送IP地址

如果配置了 slave_announce_ip,則 slave 向 master 發(fā)送 slave_announce_ip 配置的 IP 地址, master 收到后記錄在 slave 所對應的客戶端狀態(tài)的 slave_ip 屬性。

該配置是用于解決服務器返回內(nèi)網(wǎng) IP 時,其他服務器無法訪問的情況??梢酝ㄟ^該配置直接指定公網(wǎng) IP。

7)發(fā)送CAPA

CAPA 全稱是 capabilities,這邊表示的是同步復制的能力。slave 會在這一階段發(fā)送 capa 告訴 master 自己具備的(同步)復制能力, master 收到后記錄在 slave 所對應的客戶端狀態(tài)的 slave_capa 屬性。

8)數(shù)據(jù)同步

slave 將向 master 發(fā)送 PSYNC 命令, master 收到該命令后判斷是進行部分重同步還是完整重同步,然后根據(jù)策略進行數(shù)據(jù)的同步。

9)命令傳播

當完成了同步之后,就會進入命令傳播階段,這時 master 只要一直將自己執(zhí)行的寫命令發(fā)送給 slave ,而 slave 只要一直接收并執(zhí)行 master 發(fā)來的寫命令,就可以保證 master 和 slave 一直保持一致了。

以部分重同步為例,主從復制的核心步驟流程圖如下:

​3、哨兵

哨兵(Sentinel) 是 Redis 的高可用性解決方案:由一個或多個 Sentinel 實例組成的 Sentinel 系統(tǒng)可以監(jiān)視任意多個主服務器,以及這些主服務器屬下的所有從服務器。

Sentinel 可以在被監(jiān)視的主服務器進入下線狀態(tài)時,自動將下線主服務器的某個從服務器升級為新的主服務器,然后由新的主服務器代替已下線的主服務器繼續(xù)處理命令請求。

1)哨兵故障檢測

檢查主觀下線狀態(tài)

在默認情況下,Sentinel 會以每秒一次的頻率向所有與它創(chuàng)建了命令連接的實例(包括主服務器、從服務器、其他 Sentinel 在內(nèi))發(fā)送 PING 命令,并通過實例返回的 PING 命令回復來判斷實例是否在線。

如果一個實例在 down-after-miliseconds 毫秒內(nèi),連續(xù)向 Sentinel 返回無效回復,那么 Sentinel 會修改這個實例所對應的實例結(jié)構(gòu),在結(jié)構(gòu)的 flags 屬性中設置 SRI_S_DOWN 標識,以此來表示這個實例已經(jīng)進入主觀下線狀態(tài)。

檢查客觀下線狀態(tài)

當 Sentinel 將一個主服務器判斷為主觀下線之后,為了確定這個主服務器是否真的下線了,它會向同樣監(jiān)視這一服務器的其他 Sentinel 進行詢問,看它們是否也認為主服務器已經(jīng)進入了下線狀態(tài)(可以是主觀下線或者客觀下線)。

當 Sentinel 從其他 Sentinel 那里接收到足夠數(shù)量(quorum,可配置)的已下線判斷之后,Sentinel 就會將服務器置為客觀下線,在 flags 上打上 SRI_O_DOWN 標識,并對主服務器執(zhí)行故障轉(zhuǎn)移操作。

2)哨兵故障轉(zhuǎn)移流程

當哨兵監(jiān)測到某個主節(jié)點客觀下線之后,就會開始故障轉(zhuǎn)移流程。核心流程如下:

發(fā)起一次選舉,選舉出領頭 Sentinel領頭 Sentinel 在已下線主服務器的所有從服務器里面,挑選出一個從服務器,并將其升級為新的主服務器。領頭 Sentinel 將剩余的所有從服務器改為復制新的主服務器。領頭 Sentinel 更新相關(guān)配置信息,當這個舊的主服務器重新上線時,將其設置為新的主服務器的從服務器。

4、集群模式

哨兵模式最大的缺點就是所有的數(shù)據(jù)都放在一臺服務器上,無法較好的進行水平擴展。

為了解決哨兵模式存在的問題,集群模式應運而生。在高可用上,集群基本是直接復用的哨兵模式的邏輯,并且針對水平擴展進行了優(yōu)化。

集群模式具備的特點如下:

  1. 采取去中心化的集群模式,將數(shù)據(jù)按槽存儲分布在多個 Redis 節(jié)點上。集群共有 16384 個槽,每個節(jié)點負責處理部分槽。
  2. 使用 CRC16 算法來計算 key 所屬的槽:crc16(key,keylen) & 16383。
  3. 所有的 Redis 節(jié)點彼此互聯(lián),通過 PING-PONG 機制來進行節(jié)點間的心跳檢測。
  4. 分片內(nèi)采用一主多從保證高可用,并提供復制和故障恢復功能。在實際使用中,通常會將主從分布在不同機房,避免機房出現(xiàn)故障導致整個分片出問題,下面的架構(gòu)圖就是這樣設計的。
  5. 客戶端與 Redis 節(jié)點直連,不需要中間代理層(proxy)??蛻舳瞬恍枰B接集群所有節(jié)點,連接集群中任何一個可用節(jié)點即可。

集群的架構(gòu)圖如下所示:

​5、集群選舉

故障轉(zhuǎn)移的第一步就是選舉出新的主節(jié)點,以下是集群選舉新的主節(jié)點的方法:

1)當從節(jié)點發(fā)現(xiàn)自己正在復制的主節(jié)點進入已下線狀態(tài)時,會發(fā)起一次選舉:將 currentEpoch(配置紀元)加1,然后向集群廣播一條 CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 消息,要求所有收到這條消息、并且具有投票權(quán)的主節(jié)點向這個從節(jié)點投票。

2)其他節(jié)點收到消息后,會判斷是否要給發(fā)送消息的節(jié)點投票,判斷流程如下:

  1. 當前節(jié)點是 slave,或者當前節(jié)點是 master,但是不負責處理槽,則當前節(jié)點沒有投票權(quán),直接返回。
  2. 請求節(jié)點的 currentEpoch 小于當前節(jié)點的 currentEpoch,校驗失敗返回。因為發(fā)送者的狀態(tài)與當前集群狀態(tài)不一致,可能是長時間下線的節(jié)點剛剛上線,這種情況下,直接返回即可。
  3. 當前節(jié)點在該 currentEpoch 已經(jīng)投過票,校驗失敗返回。
  4. 請求節(jié)點是 master,校驗失敗返回。
  5. 請求節(jié)點的 master 為空,校驗失敗返回。
  6. 請求節(jié)點的 master 沒有故障,并且不是手動故障轉(zhuǎn)移,校驗失敗返回。因為手動故障轉(zhuǎn)移是可以在 master 正常的情況下直接發(fā)起的。
  7. 上一次為該master的投票時間,在cluster_node_timeout的2倍范圍內(nèi),校驗失敗返回。這個用于使獲勝從節(jié)點有時間將其成為新主節(jié)點的消息通知給其他從節(jié)點,從而避免另一個從節(jié)點發(fā)起新一輪選舉又進行一次沒必要的故障轉(zhuǎn)移
  8. 請求節(jié)點宣稱要負責的槽位,是否比之前負責這些槽位的節(jié)點,具有相等或更大的 configEpoch,如果不是,校驗失敗返回。

如果通過以上所有校驗,那么主節(jié)點將向要求投票的從節(jié)點返回一條 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 消息,表示這個主節(jié)點支持從節(jié)點成為新的主節(jié)點。

3)每個參與選舉的從節(jié)點都會接收 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 消息,并根據(jù)自己收到了多少條這種消息來統(tǒng)計自己獲得了多少個主節(jié)點的支持。

4)如果集群里有N個具有投票權(quán)的主節(jié)點,那么當一個從節(jié)點收集到大于等于N/2+1 張支持票時,這個從節(jié)點就會當選為新的主節(jié)點。因為在每一個配置紀元里面,每個具有投票權(quán)的主節(jié)點只能投一次票,所以如果有 N個主節(jié)點進行投票,那么具有大于等于 N/2+1 張支持票的從節(jié)點只會有一個,這確保了新的主節(jié)點只會有一個。

5)如果在一個配置紀元里面沒有從節(jié)點能收集到足夠多的支持票,那么集群進入一個新的配置紀元,并再次進行選舉,直到選出新的主節(jié)點為止。

這個選舉新主節(jié)點的方法和選舉領頭 Sentinel 的方法非常相似,因為兩者都是基于 Raft 算法的領頭選舉(leader election)方法來實現(xiàn)的。

6、如何保證集群在線擴容的安全性?(Redis 集群要增加分片,槽的遷移怎么保證無損)

例如:集群已經(jīng)對外提供服務,原來有3分片,準備新增2個分片,怎么在不下線的情況下,無損的從原有的3個分片指派若干個槽給這2個分片?

Redis 使用了 ASK 錯誤來保證在線擴容的安全性。

在槽的遷移過程中若有客戶端訪問,依舊先訪問源節(jié)點,源節(jié)點會先在自己的數(shù)據(jù)庫里面査找指定的鍵,如果找到的話,就直接執(zhí)行客戶端發(fā)送的命令。

如果沒找到,說明該鍵可能已經(jīng)被遷移到目標節(jié)點了,源節(jié)點將向客戶端返回一個 ASK 錯誤,該錯誤會指引客戶端轉(zhuǎn)向正在導入槽的目標節(jié)點,并再次發(fā)送之前想要執(zhí)行的命令,從而獲取到結(jié)果。

ASK錯誤

在進行重新分片期間,源節(jié)點向目標節(jié)點遷移一個槽的過程中,可能會出現(xiàn)這樣一種情況:屬于被遷移槽的一部分鍵值對保存在源節(jié)點里面,而另一部分鍵值對則保存在目標節(jié)點里面。

當客戶端向源節(jié)點發(fā)送一個與數(shù)據(jù)庫鍵有關(guān)的命令,并且命令要處理的數(shù)據(jù)庫鍵恰好就屬于正在被遷移的槽時。源節(jié)點會先在自己的數(shù)據(jù)庫里面査找指定的鍵,如果找到的話,就直接執(zhí)行客戶端發(fā)送的命令。

否則,這個鍵有可能已經(jīng)被遷移到了目標節(jié)點,源節(jié)點將向客戶端返回一個 ASK 錯誤,指引客戶端轉(zhuǎn)向正在導入槽的目標節(jié)點,并再次發(fā)送之前想要執(zhí)行的命令,從而獲取到結(jié)果。

7、Redis 事務的實現(xiàn)

一個事務從開始到結(jié)束通常會經(jīng)歷以下3個階段:

1)事務開始:multi 命令將執(zhí)行該命令的客戶端從非事務狀態(tài)切換至事務狀態(tài),底層通過 flags 屬性標識。

2)命令入隊:當客戶端處于事務狀態(tài)時,服務器會根據(jù)客戶端發(fā)來的命令執(zhí)行不同的操作:

  • exec、discard、watch、multi 命令會被立即執(zhí)行
  • 其他命令不會立即執(zhí)行,而是將命令放入到一個事務隊列,然后向客戶端返回 QUEUED 回復。

3)事務執(zhí)行:當一個處于事務狀態(tài)的客戶端向服務器發(fā)送 exec 命令時,服務器會遍歷事務隊列,執(zhí)行隊列中的所有命令,最后將結(jié)果全部返回給客戶端。

不過 redis 的事務并不推薦在實際中使用,如果要使用事務,推薦使用 Lua 腳本,redis 會保證一個 Lua 腳本里的所有命令的原子性。

8、Redis 的 Java 客戶端有哪些?官方推薦哪個?

Redis 官網(wǎng)展示的 Java 客戶端如下圖所示,其中官方推薦的是標星的3個:Jedis、Redisson lettuce。

9、Redis 里面有1億個 key,其中有 10 個 key 是包含 java,如何將它們?nèi)空页鰜恚?/h2>

1)keys *java* 命令,該命令性能很好,但是在數(shù)據(jù)量特別大的時候會有性能問題

2)scan 0 MATCH *java* 命令,基于游標的迭代器,更好的選擇

SCAN 命令是一個基于游標的迭代器(cursor based iterator): SCAN 命令每次被調(diào)用之后, 都會向用戶返回一個新的游標, 用戶在下次迭代時需要使用這個新游標作為 SCAN 命令的游標參數(shù), 以此來延續(xù)之前的迭代過程。

當 SCAN 命令的游標參數(shù)被設置為 0 時, 服務器將開始一次新的迭代, 而當服務器向用戶返回值為 0 的游標時, 表示迭代已結(jié)束。

10、使用過 Redis 做消息隊列么?

Redis 本身提供了一些組件來實現(xiàn)消息隊列的功能,但是多多少少都存在一些缺點,相比于市面上成熟的消息隊列,例如 Kafka、Rocket MQ 來說并沒有優(yōu)勢,因此目前我們并沒有使用 Redis 來做消息隊列。

關(guān)于 Redis 做消息隊列的常見方案主要有以下:

1)Redis 5.0 之前可以使用 List(blocking)、Pub/Sub 等來實現(xiàn)輕量級的消息發(fā)布訂閱功能組件,但是這兩種實現(xiàn)方式都有很明顯的缺點,兩者中相對完善的 Pub/Sub 的主要缺點就是消息無法持久化,如果出現(xiàn)網(wǎng)絡斷開、Redis 宕機等,消息就會被丟棄。

2)為了解決 Pub/Sub 模式等的缺點,Redis 在 5.0 引入了全新的 Stream,Stream 借鑒了很多 Kafka 的設計思想,有以下幾個特點:

  • 提供了消息的持久化和主備復制功能,可以讓任何客戶端訪問任何時刻的數(shù)據(jù),并且能記住每一個客戶端的訪問位置,還能保證消息不丟失。
  • 引入了消費者組的概念,不同組接收到的數(shù)據(jù)完全一樣(前提是條件一樣),但是組內(nèi)的消費者則是競爭關(guān)系。

Redis Stream 相比于 pub/sub 已經(jīng)有很明顯的改善,但是相比于 Kafka,其實沒有優(yōu)勢,同時存在:尚未經(jīng)過大量驗證、成本較高、不支持分區(qū)(partition)、無法支持大規(guī)模數(shù)據(jù)等問題。

11、Redis 和 Memcached 的比較

1)數(shù)據(jù)結(jié)構(gòu):memcached 支持簡單的 key-value 數(shù)據(jù)結(jié)構(gòu),而 redis 支持豐富的數(shù)據(jù)結(jié)構(gòu):String、List、Set、Hash、SortedSet 等。

2)數(shù)據(jù)存儲:memcached 和 redis 的數(shù)據(jù)都是全部在內(nèi)存中。

網(wǎng)上有一種說法 “當物理內(nèi)存用完時,Redis可以將一些很久沒用到的 value 交換到磁盤,同時在內(nèi)存中清除”,這邊指的是 redis 里的虛擬內(nèi)存(Virtual Memory)功能,該功能在 Redis 2.0 被引入,但是在 Redis 2.4 中被默認關(guān)閉,并標記為廢棄,而在后續(xù)版中被完全移除。

3)持久化:memcached 不支持持久化,redis 支持將數(shù)據(jù)持久化到磁盤

4)災難恢復:實例掛掉后,memcached 數(shù)據(jù)不可恢復,redis 可通過 RDB、AOF 恢復,但是還是會有數(shù)據(jù)丟失問題

5)事件庫:memcached 使用 Libevent 事件庫,redis 自己封裝了簡易事件庫 AeEvent

6)過期鍵刪除策略:memcached 使用惰性刪除,redis 使用惰性刪除+定期刪除

7)內(nèi)存驅(qū)逐(淘汰)策略:memcached 主要為 LRU 算法,redis 當前支持8種淘汰策略,見本文第16題

8)性能比較

  • 按“CPU 單核” 維度比較:由于 Redis 只使用單核,而 Memcached 可以使用多核,所以在比較上:在處理小數(shù)據(jù)時,平均每一個核上 Redis 比 Memcached 性能更高,而在 100k 左右的大數(shù)據(jù)時, Memcached 性能要高于 Redis。
  • 按“實例”維度進行比較:由于 Memcached 多線程的特性,在 Redis 6.0 之前,通常情況下 Memcached 性能是要高于 Redis 的,同時實例的 CPU 核數(shù)越多,Memcached 的性能優(yōu)勢越大。
  • 至于網(wǎng)上說的 redis 的性能比 memcached 快很多,這個說法就離譜。

​總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

2021年最新Redis面試題匯總(1)

2021年最新Redis面試題匯總(2)

2021年最新Redis面試題匯總(4)

相關(guān)文章

  • java隨機驗證碼生成實現(xiàn)實例代碼

    java隨機驗證碼生成實現(xiàn)實例代碼

    這篇文章主要介紹了java隨機驗證碼生成實現(xiàn)實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • java模擬post請求發(fā)送json的例子

    java模擬post請求發(fā)送json的例子

    本篇文章主要介紹了java模擬post請求發(fā)送json的例子,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Java測試題 實現(xiàn)一個注冊功能過程解析

    Java測試題 實現(xiàn)一個注冊功能過程解析

    這篇文章主要介紹了Java測試題 實現(xiàn)一個注冊功能過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • Java中正則表達式的使用和詳解(下)

    Java中正則表達式的使用和詳解(下)

    這篇文章主要介紹了Java正則表達式的使用和詳解(下)的相關(guān)資料,包括常用正則表達式和正則表達式語法,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧
    2017-04-04
  • SpringBoot大學心理服務系統(tǒng)實現(xiàn)流程分步講解

    SpringBoot大學心理服務系統(tǒng)實現(xiàn)流程分步講解

    本系統(tǒng)主要論述了如何使用JAVA語言開發(fā)一個大學生心理服務系統(tǒng) ,本系統(tǒng)將嚴格按照軟件開發(fā)流程進行各個階段的工作,采用B/S架構(gòu),面向?qū)ο缶幊趟枷脒M行項目開發(fā)
    2022-09-09
  • 詳解Java-Jackson使用

    詳解Java-Jackson使用

    這篇文章主要介紹了Java-Jackson使用詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 一文帶你掌握Java?LinkedBlockingQueue

    一文帶你掌握Java?LinkedBlockingQueue

    LinkedBlockingQueue?是一個可選有界阻塞隊列,這篇文章主要為大家詳細介紹了Java中LinkedBlockingQueue的實現(xiàn)原理與適用場景,感興趣的可以了解一下
    2023-04-04
  • Android開發(fā)簡單計算器實現(xiàn)代碼

    Android開發(fā)簡單計算器實現(xiàn)代碼

    這篇文章主要介紹了Android開發(fā)簡單計算器實現(xiàn),本文放置了完整的Android開發(fā)電腦,通過部署項目可以直接按到效果,希望本篇文章可以對你有所幫助
    2021-06-06
  • MyBatis SELECT基本查詢實現(xiàn)方法詳解

    MyBatis SELECT基本查詢實現(xiàn)方法詳解

    這篇文章主要介紹了MyBatis SELECT基本查詢實現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot如何打包自定義生成的包名

    SpringBoot如何打包自定義生成的包名

    這篇文章主要介紹了SpringBoot如何打包自定義生成的包名問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評論