最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

1、Redis 是單線程還是多線程?

這個(gè)問(wèn)題應(yīng)該已經(jīng)看到過(guò)無(wú)數(shù)次了,最近 redis 6 出來(lái)之后又被翻出來(lái)了。

redis 4.0 之前,redis 是完全單線程的。

redis 4.0 時(shí),redis 引入了多線程,但是額外的線程只是用于后臺(tái)處理,例如:刪除對(duì)象,核心流程還是完全單線程的。這也是為什么有些人說(shuō) 4.0 是單線程的,因?yàn)樗麄冎傅氖呛诵牧鞒淌菃尉€程的。

這邊的核心流程指的是 redis 正常處理客戶端請(qǐng)求的流程,通常包括:接收命令、解析命令、執(zhí)行命令、返回結(jié)果等。

而在最近,redis 6.0 版本又一次引入了多線程概念,與 4.0 不同的是,這次的多線程會(huì)涉及到上述的核心流程。

redis 6.0 中,多線程主要用于網(wǎng)絡(luò) I/O 階段,也就是接收命令和寫(xiě)回結(jié)果階段,而在執(zhí)行命令階段,還是由單線程串行執(zhí)行。由于執(zhí)行時(shí)還是串行,因此無(wú)需考慮并發(fā)安全問(wèn)題。

值得注意的時(shí),redis 中的多線程組不會(huì)同時(shí)存在“讀”和“寫(xiě)”,這個(gè)多線程組只會(huì)同時(shí)“讀”或者同時(shí)“寫(xiě)”。 

redis 6.0 加入多線程 I/O 之后,處理命令的核心流程如下:

1、當(dāng)有讀事件到來(lái)時(shí),主線程將該客戶端連接放到全局等待讀隊(duì)列

2、讀取數(shù)據(jù):1)主線程將等待讀隊(duì)列的客戶端連接通過(guò)輪詢調(diào)度算法分配給 I/O 線程處理;2)同時(shí)主線程也會(huì)自己負(fù)責(zé)處理一個(gè)客戶端連接的讀事件;3)當(dāng)主線程處理完該連接的讀事件后,會(huì)自旋等待所有 I/O 線程處理完畢

3、命令執(zhí)行:主線程按照事件被加入全局等待讀隊(duì)列的順序(這邊保證了執(zhí)行順序是正確的),串行執(zhí)行客戶端命令,然后將客戶端連接放到全局等待寫(xiě)隊(duì)列

4、寫(xiě)回結(jié)果:跟等待讀隊(duì)列處理類似,主線程將等待寫(xiě)隊(duì)列的客戶端連接使用輪詢調(diào)度算法分配給 I/O 線程處理,同時(shí)自己也會(huì)處理一個(gè),當(dāng)主線程處理完畢后,會(huì)自旋等待所有 I/O 線程處理完畢,最后清空隊(duì)列。

大致流程圖如下:

2、為什么 Redis 是單線程?

在 redis 6.0 之前,redis 的核心操作是單線程的。

因?yàn)?redis 是完全基于內(nèi)存操作的,通常情況下CPU不會(huì)是redis的瓶頸,redis 的瓶頸最有可能是機(jī)器內(nèi)存的大小或者網(wǎng)絡(luò)帶寬。

既然CPU不會(huì)成為瓶頸,那就順理成章地采用單線程的方案了,因?yàn)槿绻褂枚嗑€程的話會(huì)更復(fù)雜,同時(shí)需要引入上下文切換、加鎖等等,會(huì)帶來(lái)額外的性能消耗。

而隨著近些年互聯(lián)網(wǎng)的不斷發(fā)展,大家對(duì)于緩存的性能要求也越來(lái)越高了,因此 redis 也開(kāi)始在逐漸往多線程方向發(fā)展。

最近的 6.0 版本就對(duì)核心流程引入了多線程,主要用于解決 redis 在網(wǎng)絡(luò) I/O 上的性能瓶頸。而對(duì)于核心的命令執(zhí)行階段,目前還是單線程的。 

3、Redis 為什么使用單進(jìn)程、單線程也很快

主要有以下幾點(diǎn):

1、基于內(nèi)存的操作

2、使用了 I/O 多路復(fù)用模型,select、epoll 等,基于 reactor 模式開(kāi)發(fā)了自己的網(wǎng)絡(luò)事件處理器

3、單線程可以避免不必要的上下文切換和競(jìng)爭(zhēng)條件,減少了這方面的性能消耗。

4、以上這三點(diǎn)是 redis 性能高的主要原因,其他的還有一些小優(yōu)化,例如:對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行了優(yōu)化,簡(jiǎn)單動(dòng)態(tài)字符串、壓縮列表等。
 

4、Redis 在項(xiàng)目中的使用場(chǎng)景

緩存(核心)、分布式鎖(set + lua 腳本)、排行榜(zset)、計(jì)數(shù)(incrby)、消息隊(duì)列(stream)、地理位置(geo)、訪客統(tǒng)計(jì)(hyperloglog)等。 

5、Redis 常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)

基礎(chǔ)的5種:

  • String:字符串,最基礎(chǔ)的數(shù)據(jù)類型。
  • List:列表。
  • Hash:哈希對(duì)象。
  • Set:集合。
  • Sorted Set:有序集合,Set 的基礎(chǔ)上加了個(gè)分值。

高級(jí)的4種:

  • HyperLogLog:通常用于基數(shù)統(tǒng)計(jì)。使用少量固定大小的內(nèi)存,來(lái)統(tǒng)計(jì)集合中唯一元素的數(shù)量。統(tǒng)計(jì)結(jié)果不是精確值,而是一個(gè)帶有0.81%標(biāo)準(zhǔn)差(standard error)的近似值。所以,HyperLogLog適用于一些對(duì)于統(tǒng)計(jì)結(jié)果精確度要求不是特別高的場(chǎng)景,例如網(wǎng)站的UV統(tǒng)計(jì)。
  • Geo:redis 3.2 版本的新特性??梢詫⒂脩艚o定的地理位置信息儲(chǔ)存起來(lái), 并對(duì)這些信息進(jìn)行操作:獲取2個(gè)位置的距離、根據(jù)給定地理位置坐標(biāo)獲取指定范圍內(nèi)的地理位置集合。
  • Bitmap:位圖。
  • Stream:主要用于消息隊(duì)列,類似于 kafka,可以認(rèn)為是 pub/sub 的改進(jìn)版。提供了消息的持久化和主備復(fù)制功能,可以讓任何客戶端訪問(wèn)任何時(shí)刻的數(shù)據(jù),并且能記住每一個(gè)客戶端的訪問(wèn)位置,還能保證消息不丟失。 

6、Redis 的字符串(SDS)和C語(yǔ)言的字符串區(qū)別

 

7、Sorted Set底層數(shù)據(jù)結(jié)構(gòu)

Sorted Set(有序集合)當(dāng)前有兩種編碼:ziplist、skiplist

ziplist:使用壓縮列表實(shí)現(xiàn),當(dāng)保存的元素長(zhǎng)度都小于64字節(jié),同時(shí)數(shù)量小于128時(shí),使用該編碼方式,否則會(huì)使用 skiplist。這兩個(gè)參數(shù)可以通過(guò) zset-max-ziplist-entries、zset-max-ziplist-value 來(lái)自定義修改。

skiplist:zset實(shí)現(xiàn),一個(gè)zset同時(shí)包含一個(gè)字典(dict)和一個(gè)跳躍表(zskiplist)

 

8、Sorted Set 為什么同時(shí)使用字典和跳躍表?

主要是為了提升性能。

單獨(dú)使用字典:在執(zhí)行范圍型操作,比如 zrank、zrange,字典需要進(jìn)行排序,至少需要 O(NlogN) 的時(shí)間復(fù)雜度及額外 O(N) 的內(nèi)存空間。

單獨(dú)使用跳躍表:根據(jù)成員查找分值操作的復(fù)雜度從 O(1) 上升為 O(logN)。 

9、Sorted Set 為什么使用跳躍表,而不是紅黑樹(shù)?

主要有以下幾個(gè)原因:

1)跳表的性能和紅黑樹(shù)差不多。

2)跳表更容易實(shí)現(xiàn)和調(diào)試。

網(wǎng)上有同學(xué)說(shuō)是因?yàn)樽髡卟粫?huì)紅黑樹(shù),我覺(jué)得挺有可能的。

10、Hash 對(duì)象底層結(jié)構(gòu)

Hash 對(duì)象當(dāng)前有兩種編碼:ziplist、hashtable

ziplist:使用壓縮列表實(shí)現(xiàn),每當(dāng)有新的鍵值對(duì)要加入到哈希對(duì)象時(shí),程序會(huì)先將保存了鍵的節(jié)點(diǎn)推入到壓縮列表的表尾,然后再將保存了值的節(jié)點(diǎn)推入到壓縮列表表尾。

因此:1)保存了同一鍵值對(duì)的兩個(gè)節(jié)點(diǎn)總是緊挨在一起,保存鍵的節(jié)點(diǎn)在前,保存值的節(jié)點(diǎn)在后;2)先添加到哈希對(duì)象中的鍵值對(duì)會(huì)被放在壓縮列表的表頭方向,而后來(lái)添加的會(huì)被放在表尾方向。

hashtable:使用字典作為底層實(shí)現(xiàn),哈希對(duì)象中的每個(gè)鍵值對(duì)都使用一個(gè)字典鍵值來(lái)保存,跟 java 中的 HashMap 類似。

11、Hash 對(duì)象的擴(kuò)容流程

hash 對(duì)象在擴(kuò)容時(shí)使用了一種叫“漸進(jìn)式 rehash”的方式,步驟如下:

1)計(jì)算新表 size、掩碼,為新表 ht[1] 分配空間,讓字典同時(shí)持有 ht[0] 和 ht[1] 兩個(gè)哈希表。

2)將 rehash 索引計(jì)數(shù)器變量 rehashidx 的值設(shè)置為0,表示 rehash 正式開(kāi)始。

3)在 rehash 進(jìn)行期間,每次對(duì)字典執(zhí)行添加、刪除、査找、更新操作時(shí),程序除了執(zhí)行指定的操作以外,還會(huì)觸發(fā)額外的 rehash 操作,在源碼中的 _dictRehashStep 方法。

_dictRehashStep:從名字也可以看出來(lái),大意是 rehash 一步,也就是 rehash 一個(gè)索引位置。

該方法會(huì)從 ht[0] 表的 rehashidx 索引位置上開(kāi)始向后查找,找到第一個(gè)不為空的索引位置,將該索引位置的所有節(jié)點(diǎn) rehash 到 ht[1],當(dāng)本次 rehash 工作完成之后,將 ht[0] 索引位置為 rehashidx 的節(jié)點(diǎn)清空,同時(shí)將 rehashidx 屬性的值加一。

4)將 rehash 分?jǐn)偟矫總€(gè)操作上確實(shí)是非常妙的方式,但是萬(wàn)一此時(shí)服務(wù)器比較空閑,一直沒(méi)有什么操作,難道 redis 要一直持有兩個(gè)哈希表嗎?

答案當(dāng)然不是的。我們知道,redis 除了文件事件外,還有時(shí)間事件,redis 會(huì)定期觸發(fā)時(shí)間事件,這些時(shí)間事件用于執(zhí)行一些后臺(tái)操作,其中就包含 rehash 操作:當(dāng) redis 發(fā)現(xiàn)有字典正在進(jìn)行 rehash 操作時(shí),會(huì)花費(fèi)1毫秒的時(shí)間,一起幫忙進(jìn)行 rehash。

5)隨著操作的不斷執(zhí)行,最終在某個(gè)時(shí)間點(diǎn)上,ht[0] 的所有鍵值對(duì)都會(huì)被 rehash 至 ht[1],此時(shí) rehash 流程完成,會(huì)執(zhí)行最后的清理工作:釋放 ht[0] 的空間、將 ht[0] 指向 ht[1]、重置 ht[1]、重置 rehashidx 的值為 -1。

 總結(jié)

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

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

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

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

相關(guān)文章

  • Java中Arrays.asList()方法詳解及實(shí)例

    Java中Arrays.asList()方法詳解及實(shí)例

    這篇文章主要介紹了Java中Arrays.asList()方法將數(shù)組作為列表時(shí)的一些差異的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 深入了解Java中Synchronized的各種使用方法

    深入了解Java中Synchronized的各種使用方法

    在Java當(dāng)中synchronized關(guān)鍵字通常是用來(lái)標(biāo)記一個(gè)方法或者代碼塊。本文將通過(guò)示例為大家詳細(xì)介紹一下Synchronized的各種使用方法,需要的可以參考一下
    2022-08-08
  • Java調(diào)用C++動(dòng)態(tài)庫(kù)超詳細(xì)步驟講解(附源碼)

    Java調(diào)用C++動(dòng)態(tài)庫(kù)超詳細(xì)步驟講解(附源碼)

    C語(yǔ)言因其高效和接近硬件的特性,時(shí)常會(huì)被用在性能要求較高或者需要直接操作硬件的場(chǎng)合,這篇文章主要介紹了Java調(diào)用C++動(dòng)態(tài)庫(kù)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • Java8 新特性Lambda表達(dá)式實(shí)例詳解

    Java8 新特性Lambda表達(dá)式實(shí)例詳解

    這篇文章主要介紹了Java8 新特性Lambda表達(dá)式實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn)

    Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn)

    這篇文章主要介紹了Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Java設(shè)計(jì)模式之享元模式

    Java設(shè)計(jì)模式之享元模式

    這篇文章介紹了Java設(shè)計(jì)模式之享元模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • 最新springboot中必須要了解的自動(dòng)裝配原理

    最新springboot中必須要了解的自動(dòng)裝配原理

    本文給大家介紹springboot中必須要了解的自動(dòng)裝配原理,spring-boot-dependencies:核心依賴都在父工程中,這個(gè)里面主要是管理項(xiàng)目的資源過(guò)濾及插件,本文對(duì)springboot自動(dòng)裝配原理給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-05-05
  • idea更換jdk版本的完整步驟(附詳細(xì)圖文)

    idea更換jdk版本的完整步驟(附詳細(xì)圖文)

    idea很多地方都設(shè)置了jdk版本,不同模塊的jdk版本也可能不一樣,這篇文章主要介紹了idea更換jdk版本的完整步驟,通過(guò)文中介紹的步驟可以成功更換jdk版本,需要的朋友可以參考下
    2025-04-04
  • Java中自定義LRU緩存詳解

    Java中自定義LRU緩存詳解

    這篇文章主要介紹了Java中自定義LRU緩存詳解,基于LRU算法的緩存系統(tǒng),可以在達(dá)到緩存容量上限時(shí),清理最近最少使用的數(shù)據(jù),為新的數(shù)據(jù)的插入騰出空間,需要的朋友可以參考下
    2023-09-09
  • IntelliJ?IDEA?2021.3?正式發(fā)布之支持遠(yuǎn)程開(kāi)發(fā)、IDE故障排查等多項(xiàng)優(yōu)化改進(jìn)

    IntelliJ?IDEA?2021.3?正式發(fā)布之支持遠(yuǎn)程開(kāi)發(fā)、IDE故障排查等多項(xiàng)優(yōu)化改進(jìn)

    IntelliJ?IDEA?2021.3?正式發(fā)布:支持遠(yuǎn)程開(kāi)發(fā)、IDE故障排查等多項(xiàng)優(yōu)化改進(jìn)問(wèn)題,在這個(gè)版本中的遠(yuǎn)程開(kāi)發(fā)還不是一個(gè)正式版本,而是BETA版,但通過(guò)這個(gè)BETA版本,也可以體驗(yàn)IDEA“遠(yuǎn)程開(kāi)發(fā)”給我們帶來(lái)的全新體驗(yàn)
    2021-12-12

最新評(píng)論

宁晋县| 夏河县| 保山市| 麻栗坡县| 海盐县| 滨海县| 东平县| 林芝县| 禄丰县| 奉化市| 龙南县| 大连市| 六安市| 淮阳县| 恩平市| 云和县| 静海县| 夏河县| 平顶山市| 武平县| 滨海县| 重庆市| 建水县| 简阳市| 中山市| 辽宁省| 上蔡县| 余干县| 永昌县| 商河县| 三都| 青神县| 抚松县| 沁水县| 清水县| 威信县| 都昌县| 弥渡县| 岢岚县| 寿宁县| 凌云县|