欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:面試篇:Redis

柚子快報邀請碼778899分享:面試篇:Redis

http://yzkb.51969.com/

目錄

一、緩存穿透

1、緩存穿透

?2、查詢流程

3、出現(xiàn)原因

4、解決方法一(設置value為null)

5、解決方法二(布隆過濾器)

6、概括

7、?面試官:什么是緩存穿透?怎么解決?

8、?面試官:你能介紹一下布隆過濾器嗎?

二、緩存擊穿

1、概念

?2、解決方法一(互斥鎖)

3、解決方法二(邏輯過期)

4、概括

5、?面試官:什么是緩存擊穿 ? 怎么解決 ?

三、緩存雪崩

1、緩存雪崩

?2、查詢流程

3、解決方法

4、面試官:什么是緩存雪崩?怎么解決 ?

5、打油詩速記

四、redis做為緩存,mysql的數(shù)據(jù)如何與redis進行同步呢?(雙寫一致性)?

?1、雙寫一致性

2、先刪除緩存再修改數(shù)據(jù)庫

3、先修改數(shù)據(jù)庫再刪除緩存

4、為什么要進行兩次刪除緩存呢?

5、為什么要進行延遲雙刪呢?

6、一致性方法一(強一致性)

7、一致性方法二(異步通知保證數(shù)據(jù)的最終一致性)

8、概括

?9、面試官:redis做為緩存,mysql的數(shù)據(jù)如何與redis進行同步呢?(雙寫一致性)

10、面試官:那這個排他鎖是如何保證讀寫、讀讀互斥的呢??

11、面試官:你聽說過延時雙刪嗎?為什么不用它呢?

五、redis做為緩存,數(shù)據(jù)的持久化是怎么做的?

1、RDB

2、RDB執(zhí)行原理

3、AOF

?編輯?4、RDB和AOF對比

?5、面試官: redis做為緩存,數(shù)據(jù)的持久化是怎么做的?

6、這兩種持久化方式有什么區(qū)別呢?

7、這兩種方式,哪種恢復的比較快呢?

六、數(shù)據(jù)過期策略

1、假如redis的key過期之后,會立即刪除嗎?

2、Redis數(shù)據(jù)刪除策略-惰性刪除

3、Redis數(shù)據(jù)刪除策略-定期刪除

4、Redis選擇的策略

七、數(shù)據(jù)淘汰策略

1、Redis支持8種不同策略來選擇要刪除的key:

2、 LRU與LFU區(qū)別

3、淘汰策略使用建議

4、關于數(shù)據(jù)淘汰策略其他的面試問題

5、概括

6、?面試官: Redis的數(shù)據(jù)淘汰策略有哪些?

7、面試官:數(shù)據(jù)庫有1000萬數(shù)據(jù),Redis只能緩存20w數(shù)據(jù),如何保證Redis中的數(shù)據(jù)都是熱點數(shù)據(jù)?

8、面試官: Redis的內存用完了會發(fā)生什么?

?八、Redis分布式鎖使用場景

1、搶卷場景下的代碼流程

2、模擬本地多線程情況下?lián)尵淼膱?zhí)行流程

?3、服務集群部署情況

九、Redis分布式鎖實現(xiàn)原理(setnx,redisson)

1、setnx命令

?2、setnx執(zhí)行流程

3、setnx命令缺陷

4、Redis實現(xiàn)分布式鎖如何合理的控制鎖的有效時長?

5、Redisson實現(xiàn)分布式鎖的使用流程

6、redisson執(zhí)行代碼

7、Redisson實現(xiàn)的分布式鎖-鎖可重入

8、Redisson實現(xiàn)的分布式鎖——主從一致性?

?9、概括

10、?面試官: Redis分布式鎖如何實現(xiàn)?

11、面試官:好的,那你如何控制Redis實現(xiàn)分布式鎖有效時長呢?

12、面試官:好的,redisson實現(xiàn)的分布式鎖是可重入的嗎?

13、面試官: redisson實現(xiàn)的分布式鎖能解決主從一致性的問題嗎?

十、主從復制,主從同步流程(高并發(fā))

1、主從復制

2、主從同步原理——主從同步變量

3、主從同步原理——主從增量同步?

?4、概括

5、面試官: Redis集群有哪些方案,知道嗎?

6、面試官:那你來介紹一下主從同步

7、面試官:能說一下,主從同步數(shù)據(jù)的流程?

十一、哨兵模式,集群腦裂 (高可用)

1、哨兵的作用

?2、服務狀態(tài)監(jiān)控

3、Redis集群腦裂

4、概括?

5、面試官:怎么保證Redis的高并發(fā)高可用

6、面試官:你們使用redis是單點還是集群,哪種集群

7、redis集群腦裂,該怎么解決呢?

十二、分片集群、數(shù)據(jù)讀寫規(guī)則

1、分片集群結構?

?2、分片集群架構——數(shù)據(jù)讀寫

3、概括

?4、面試官: redis的分片集群有什么作用

5、面試官: Redis分片集群中數(shù)據(jù)是怎么存儲和讀取的?

十三、 Redis是單線程,為什么速度還這么快?

1、Redis是單線程的,但是為什么還那么快?

2、能解釋一下I/O多路復用模型?

3、用戶空間和內核空間

4、阻塞IO

5、非阻塞IO

6、I/O多路復用

7、多路復用I/O通知方式

8、Redis網(wǎng)絡模型

9、概括

10、?面試官: Redis是單線程的,但是為什么還那么快?

11、面試官:能解釋一下I/O多路復用模型?

十四、Redis是什么?

十五、Redis優(yōu)缺點?

1、優(yōu)點

2、缺點

十六、Redis為什么這么快?

十七、既然Redis那么快,為什么不用它做主數(shù)據(jù)庫,只用它做緩存?

十八、Redis應用場景有哪些?

十九、Redis 數(shù)據(jù)類型有哪些?

1、基本數(shù)據(jù)類型:

?2、特殊的數(shù)據(jù)類型:

二十、Redis的內存用完了會怎樣?

二十一、keys命令存在的問題?

二十二、Redis常見性能問題和解決方案?

二十三、說說為什么Redis過期了為什么內存沒釋放?

1、可能是覆蓋之前的key,導致key過期時間發(fā)生了改變

2、Redis過期key的處理策略導致內存沒釋放

一、緩存穿透

1、緩存穿透

查詢一個不存在的數(shù)據(jù),mysql查詢不到數(shù)據(jù)也不會直接寫入緩存,就會導致每次請求都查數(shù)據(jù)庫。即:大量請求根本不存在的key?

?2、查詢流程

3、出現(xiàn)原因

業(yè)務層誤將緩存和庫中的數(shù)據(jù)刪除了,也可能是有人惡意攻擊,專門訪問庫中不存在的數(shù)據(jù)?

4、解決方法一(設置value為null)

緩存空數(shù)據(jù),查詢返回的數(shù)據(jù)為空,仍把這個空結果進行緩存?

?

優(yōu)點:簡單缺點:消耗內存,可能導致不一致性?

5、解決方法二(布隆過濾器)

bitmap(位圖):相當于是一個以 (bit) 位為單位的數(shù)組,數(shù)組中每個單元只能存儲二進制數(shù)0或1。

布隆過濾器作用:布隆過濾器可以用于檢索一個元素是否在一個集合中。

?

?當訪問id存在的時候,會根據(jù)布隆過濾器的hash函數(shù)獲取hash值來計算相應的位置并且修改0為1。當查詢的時候就會根據(jù)生成的hash函數(shù)獲取hash值判斷對應位置是否為1,如果都為1,則可以進入redis緩存查詢,否則不可以。

誤判: 為空的數(shù)據(jù)計算的hash值在數(shù)組中都為1,但實際上該數(shù)據(jù)不存在

誤判率:數(shù)組越小誤判率就越大,數(shù)組越大誤判率就越小,但是同時帶來了更多的內存消耗。一般誤判率是5%。

布隆過濾器優(yōu)點:內存占用較少,沒有多余key。布隆過濾器優(yōu)點:實現(xiàn)復雜,存在誤判。

6、概括

Redis的使用場景

根據(jù)自己簡歷上的業(yè)務進行回答緩存:穿透、擊穿、雪崩、雙寫一致、持久化、數(shù)據(jù)過期、淘汰策略分布式鎖:setnx、redisson

什么是緩存穿透,怎么解決?

緩存穿透:查詢一個不存在的數(shù)據(jù),mysql查詢不到數(shù)據(jù)也不會直接寫入緩存,就會導致每次請求都查數(shù)據(jù)庫。解決方案一:緩存空數(shù)據(jù)解決方案二:布隆過濾器

7、?面試官:什么是緩存穿透?怎么解決?

緩存穿透是指查詢一個一定不存在的數(shù)據(jù),如果從存儲層查不到數(shù)據(jù)則不寫入緩存,這將導致這個不存在的數(shù)據(jù)每次請求都要到 DB 去查詢,可能導致 DB 掛掉。這種情況大概率是遭到了攻擊。解決方案的話,我們通常都會用布隆過濾器來解決它。

8、?面試官:你能介紹一下布隆過濾器嗎?

布隆過濾器主要是用于檢索一個元素是否在一個集合中。我們當時使用的是redisson實現(xiàn)的布隆過濾器。它的底層主要是先去初始化一個比較大數(shù)組,里面存放的二進制0或1。在一開始都是0,當一個key來了之后經過3次hash計算,模于數(shù)組長度找到數(shù)據(jù)的下標然后把數(shù)組中原來的0改為1,這樣的話,三個數(shù)組的位置就能標明一個key的存在。查找的過程也是一樣的。當然是有缺點的,布隆過濾器有可能會產生一定的誤判,我們一般可以設置這個誤判率,大概不會超過5%,其實這個誤判是必然存在的,要不就得增加數(shù)組的長度,其實已經算是很劃分了,5%以內的誤判率一般的項目也能接受,不至于高并發(fā)下壓倒數(shù)據(jù)庫。

二、緩存擊穿

1、概念

給某一個key設置了過期時間,當key過期的時候,恰好這時間點對這個key有大量的并發(fā)請求過來,這些并發(fā)的請求可能會瞬間把DB壓垮。即:redis中一個熱點key過期(大量用戶訪問該熱點key,但是熱點key過期)

?2、解決方法一(互斥鎖)

優(yōu)點:強一致性缺點:性能差適用于與交易相關的業(yè)務?

當線程1查詢緩存的時候,未命中緩存,然后獲取互斥鎖成功。此時線程1去查詢數(shù)據(jù)庫,將數(shù)據(jù)寫入緩存,最后釋放鎖。

在線程1查詢緩存的時候,未命中緩存,然后線程2去獲取互斥鎖,獲取失敗,因為線程1獲取到了互斥鎖,此時線程2只能休眠一會再重試。當線程1寫入緩存成功后并釋放鎖的同時,線程2重試命中緩存,命中成功直接獲取緩存。

3、解決方法二(邏輯過期)

優(yōu)點:高可用,性能好缺點:數(shù)據(jù)不一致適用于注重用戶的體驗

4、概括

緩存擊穿:給某一個key設置了過期時間,當key過期的時候,恰好這時間點對這個key有大量的并發(fā)請求過來,這些并發(fā)的請求可能會瞬間把DB壓垮。解決方案一:互斥鎖,強一致,性能差。解決方案二:邏輯過期,高可用,性能優(yōu),不能保證數(shù)據(jù)絕對一致。

5、?面試官:什么是緩存擊穿 ? 怎么解決 ?

緩存擊穿的意思是對于設置了過期時間的key,緩存在某個時間點過期的時候,恰好這時間點對這個Key有大量的并發(fā)請求過來,這些請求發(fā)現(xiàn)緩存過期一般都會從后端 DB 加載數(shù)據(jù)并回設到緩存,這個時候大并發(fā)的請求可能會瞬間把 DB 壓垮。解決方案有兩種方式:第一可以使用互斥鎖:當緩存失效時,不立即去load db,先使用如 Redis 的 setnx或者Redisson去設置一個互斥鎖。當操作成功返回時再進行 load db的操作并回設緩存,否則重試get緩存的方法第二種方案可以設置當前key邏輯過期,大概是思路如下:

①在設置key的時候,設置一個過期時間字段一塊存入緩存中,不給當前key設置過期時間。②當查詢的時候,從redis取出數(shù)據(jù)后判斷時間是否過期。③如果過期則開通另外一個線程進行數(shù)據(jù)同步,當前線程正常返回數(shù)據(jù),這個數(shù)據(jù)不是最新。當然兩種方案各有利弊:

如果選擇數(shù)據(jù)的強一致性,建議使用分布式鎖的方案,性能上可能沒那么高,鎖需要等,也有可能產生死鎖的問題如果選擇key的邏輯刪除,則優(yōu)先考慮的高可用性,性能比較高,但是數(shù)據(jù)同步這塊做不到強一致。

三、緩存雪崩

1、緩存雪崩

緩存雪崩是指在同一時段大量的緩存key同時失效或者Redis服務宕機,導致大量請求到達數(shù)據(jù)庫,帶來巨大壓力。

?2、查詢流程

3、解決方法

給不同的Key的TTL添加隨機值。集群模式利用Redis集群提高服務的可用性哨兵模式。(哨兵模式,集群模式)給緩存業(yè)務添加降級限流策略。(nginx或者Spring Cloud GateWay)給業(yè)務添加多級緩存。 ?

4、面試官:什么是緩存雪崩?怎么解決 ?

緩存雪崩意思是設置緩存時采用了相同的過期時間,導致緩存在某一時刻同時失效,請求全部轉發(fā)到DB,DB 瞬時壓力過重雪崩。與緩存擊穿的區(qū)別:雪崩是很多key,擊穿是某一個key緩存。解決方案主要是可以將緩存失效時間分散開,比如可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發(fā)集體失效的事件。?

5、打油詩速記

????????????????《緩存三兄弟》穿透無中生有key,布隆過濾null隔離。緩存擊穿過期key,鎖與非期解難題。雪崩大量過期key,過期時間要隨機。面試必考三兄弟,可用限流來保底?。

四、redis做為緩存,mysql的數(shù)據(jù)如何與redis進行同步呢?(雙寫一致性)?

?1、雙寫一致性

當修改了數(shù)據(jù)庫的數(shù)據(jù)也要同時更新緩存的數(shù)據(jù),緩存和數(shù)據(jù)庫的數(shù)據(jù)要保持一致。讀操作:緩存命中,直接返回;緩存未命中查詢數(shù)據(jù)庫,寫入緩存,設定超時時間。寫操作:延遲雙刪。

那么先刪除緩存還是先修改數(shù)據(jù)庫呢? (2.3)

那么為什么要刪除兩次緩存呢?(4)

那么為什么要延時刪除呢?(5)

2、先刪除緩存再修改數(shù)據(jù)庫

此時緩存和數(shù)據(jù)庫的值分別為10,10

?

如下是正常的情況,數(shù)據(jù)庫和緩存的值修改正常?

?

但是一般而言線程是交叉進行的

?此時緩存和數(shù)據(jù)庫的值分別為10,20。造成了數(shù)據(jù)庫和緩存不一致情況

?

3、先修改數(shù)據(jù)庫再刪除緩存

此時緩存和數(shù)據(jù)庫的值分別為10,10

?

如下是正常的情況,數(shù)據(jù)庫和緩存的值修改正常??

但是一般而言線程是交叉進行的

??此時緩存和數(shù)據(jù)庫的值分別為10,20。造成了數(shù)據(jù)庫和緩存不一致情況

?

4、為什么要進行兩次刪除緩存呢?

為了保證緩存和數(shù)據(jù)庫的一致性。因為不管是先修改數(shù)據(jù)庫還是先刪緩存都會導致數(shù)據(jù)庫和緩存的值不同。而兩次刪除緩存會避免這種情況發(fā)生。但是一般情況下數(shù)據(jù)庫都是主從分離的,所以可能出現(xiàn)主從數(shù)據(jù)庫數(shù)據(jù)不一致的情況。

5、為什么要進行延遲雙刪呢?

一般情況下數(shù)據(jù)庫都是主從分離的,所以可能出現(xiàn)主從數(shù)據(jù)庫數(shù)據(jù)不一致的情況。為了避免這種情況,就會延遲一會,等待主節(jié)點同步到從節(jié)點。所以要延時,但是這個延時時間不好控制,在這個過程中依然可能會出現(xiàn)臟數(shù)據(jù)。所以延時雙刪只是控制減少了臟數(shù)據(jù)的出現(xiàn),但無法避免臟數(shù)據(jù)的出現(xiàn)。

6、一致性方法一(強一致性)

使用分布式鎖來避免數(shù)據(jù)的不一致性

但是這種普通的讀寫加鎖性能太差,所以可以使用讀寫鎖來處理這種問題。因為緩存一般都是讀多寫少,所以可以分別使用讀鎖和寫鎖來進行加鎖

共享鎖:讀鎖readLock,加鎖之后,其他線程可以共享讀操作排他鎖:獨占鎖writeLock,加鎖之后,阻塞其他線程讀寫操作

?讀鎖相關代碼,注意讀鎖和寫鎖的鎖名必須一致

?寫鎖相關代碼

但是此方法雖然保持了強一致,但是性能不高。?

7、一致性方法二(異步通知保證數(shù)據(jù)的最終一致性)

?

8、概括

redis做為緩存,mysql的數(shù)據(jù)如何與redis進行同步呢? (雙寫一致性)

介紹自己簡歷上的業(yè)務,我們當時是把文章的熱點數(shù)據(jù)存入到了緩存中,雖然是熱點數(shù)據(jù),但是實時要求性并沒有那么高,所以,我們當時采用的是異步的方案同步的數(shù)據(jù)我們當時是把搶券的庫存存入到了緩存中,這個需要實時的進行數(shù)據(jù)同步,為了保證數(shù)據(jù)的強一致,我們當時采用的是redisson提供的讀寫鎖來保證數(shù)據(jù)的同步

那你來介紹一下異步的方案(你來介紹一下redisson讀寫鎖的這種方案)

允許延時一致的業(yè)務,采用異步通知

使用MQ中間中間件,更新數(shù)據(jù)之后,通知緩存刪除

強一致性的,采用Redisson提供的讀寫鎖o

共享鎖: 讀鎖readLock,加鎖之后,其他線程可以共享讀操作排他鎖:獨占鎖writeLock也叫,加鎖后,阻塞其他線程讀寫操作?

?9、面試官:redis做為緩存,mysql的數(shù)據(jù)如何與redis進行同步呢?(雙寫一致性)

嗯!就說我最近做的這個項目,里面有xxxx(根據(jù)自己的簡歷上寫)的功能,需要讓數(shù)據(jù)庫與redis高度保持一致,因為要求時效性比較高,我們當時采用的讀寫鎖保證的強一致性。我們采用的是redisson實現(xiàn)的讀寫鎖,在讀的時候添加共享鎖,可以保證讀讀不互斥,讀寫互斥。當我們更新數(shù)據(jù)的時候,添加排他鎖,它是讀寫,讀讀都互斥,這樣就能保證在寫數(shù)據(jù)的同時是不會讓其他線程讀數(shù)據(jù)的,避免了臟數(shù)據(jù)。這里面需要注意的是讀方法和寫方法上需要使用同一把鎖才行。

10、面試官:那這個排他鎖是如何保證讀寫、讀讀互斥的呢??

其實排他鎖底層使用也是setnx,保證了同時只能有一個線程操作鎖住的方法

11、面試官:你聽說過延時雙刪嗎?為什么不用它呢?

延遲雙刪,如果是寫操作,我們先把緩存中的數(shù)據(jù)刪除,然后更新數(shù)據(jù)庫,最后再延時刪除緩存中的數(shù)據(jù),其中這個延時多久不太好確定,在延時的過程中可能會出現(xiàn)臟數(shù)據(jù),并不能保證強一致性,所以沒有采用它。?

五、redis做為緩存,數(shù)據(jù)的持久化是怎么做的?

在Redis中提供了兩種數(shù)據(jù)持久化的方式:

RDBAOF

1、RDB

RDB全稱Redis Database Backup file (Redis數(shù)據(jù)備份文件),也被叫做Redis數(shù)據(jù)快照。簡單來說就是把內存中的所有數(shù)據(jù)都記錄到磁盤中。當Redis實例故障重啟后,從磁盤讀取快照文件,恢復數(shù)據(jù)。

主動備份

被動備份

?save 300 10: 表示300秒內,有10個key被修改可以執(zhí)行bgsave

2、RDB執(zhí)行原理

bgsave的子進程執(zhí)行的時候不會阻塞主進程,不過在開啟子進程的時候會阻塞主進程,但是由于時間是納秒級所以幾乎毫無影響。

bgsave開始時會fork主進程得到子進程,子進程共享主進程的內存數(shù)據(jù)。完成fork后讀取內存數(shù)據(jù)并寫入 RDB 文件。fork采用的是copy-on-write技術

當主進程執(zhí)行讀操作時,訪問共享內存當主進程執(zhí)行寫操作時,則會拷貝一份數(shù)據(jù),執(zhí)行寫操作

?

????????在linux系統(tǒng)中進程不能直接操作物理內存,需要頁表來進行虛擬內存和物理內存直接的映射。主進程通過頁表關聯(lián)到物理內存真正的地址,這樣就能對物理內存進行讀和寫操作了。

????????當開啟RDB的時候,主進程就會fork(將主進程的頁表數(shù)據(jù)復制過去,因此子進程就有了和主進程相同的映射關系了,這樣子進程就可以根據(jù)頁表進行對物理內存中數(shù)據(jù)的讀取了)一個子進程。然后子進程就可以去物理內存讀取數(shù)據(jù)并且寫入到磁盤中去,生成新的RDB文件,并且將新的RDB文件覆蓋舊的RDB文件中去。

????????但是子進程在寫RDB文件的過程中,主進程可以接受用戶的請求來修改內存中的數(shù)據(jù)。這就導致了讀寫沖突,甚至可能產生臟數(shù)據(jù)。為了避免這種問題的發(fā)生,fork底層會采用Copy On Write的技術。在fork的過程中,就會將數(shù)據(jù)標記為Read—Only(只讀)模式,任何一個進程只能來讀數(shù)據(jù)不能來寫數(shù)據(jù)。如果主進程進行寫數(shù)據(jù),那么就會將物理內存中的數(shù)據(jù)拷貝一份,然后對這個拷貝的數(shù)據(jù)進讀和寫,避免了臟寫的情況。

3、AOF

AOF全稱為Append Only File(追加文件)。Redis處理的每一個寫命令都會記錄在AOF文件,可以看做是命令日志文件。?

AOF默認是關閉的,需要修改redis.conf配置文件來開啟AOF:

AOF的命令記錄的頻率也可以通過redis.conf文件來配:?

因為 AOF 持久化是通過保存被執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài)的,所以隨著服務器運行時間的流逝,AOF 文件中的內容會越來越多,文件的體積也會越來越大。

體積過大的 AOF 文件很可能對Redis服務器、甚至整個宿主計算機造成影響并且 AOF 文件的體積越大,使用AOF文件來進行數(shù)據(jù)還原所需的時間就越多

所以 Redis 服務器就會選擇一個時間點創(chuàng)建一個新的 AOF 文件來替代現(xiàn)有的 AOF 文件,新舊兩個 AOF 文件所保存的數(shù)據(jù)庫狀態(tài)相同,但新 AOF 文件不會包含任何浪費空間的冗余命令,所以新 AOF 文件的體積通常會比舊 AOF 文件的體積要小得多

因為是記錄命令,AOF文件會比RDB文件大的多。而且AOF會記錄對同一個key的多次寫操作,但只有最后一次寫操作才有意義。通過執(zhí)行bgrewriteaof命令,可以讓AOF文件執(zhí)行重寫功能,用最少的命令達到相同效果。

?4、RDB和AOF對比

5、面試官: redis做為緩存,數(shù)據(jù)的持久化是怎么做的?

在Redis中提供了兩種數(shù)據(jù)持久化的方式: 1、RDB 2、AOF

6、這兩種持久化方式有什么區(qū)別呢?

RDB是一個快照文件,它是把redis內存存儲的數(shù)據(jù)寫到磁盤上,當redis實例宕機恢復數(shù)據(jù)的時候,方便從RDB的快照文件中恢復數(shù)據(jù)。AOF的含義是追加文件,當redis操作寫命令的時候,都會存儲這個文件中,當redis實例宕機恢復數(shù)據(jù)的時候,會從這個文件中再次執(zhí)行一遍命令來恢復數(shù)據(jù)。

7、這兩種方式,哪種恢復的比較快呢?

RDB因為是二進制文件,在保存的時候體積也是比較小的,它恢復的比較快,但是它有可能會丟數(shù)據(jù),我們通常在項目中也會使用AOF來恢復數(shù)據(jù),雖然AOF恢復的速度慢一些,但是它丟數(shù)據(jù)的風險要小很多,在AOF文件中可以設置刷盤策略,我們當時設置的就是每秒批量寫入一次命令。

8、RDB 優(yōu)劣勢

優(yōu)勢

一旦采用該方式,那么你的整個 Redis 數(shù)據(jù)庫將只包含一個文件,這樣非常方便進行備份,比如你可能打算每 1 天歸檔一些數(shù)據(jù)。我們可以很容易的將一個一個 RDB 文件移動到其他的存儲介質上RDB 在恢復大數(shù)據(jù)集時的速度比 AOF 的恢復速度要快。RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然后這個子進程就會處理接下來的所有保存工作,父進程無須執(zhí)行任何磁盤 I/O 操作。

劣勢

如果你需要盡量避免在服務器故障時丟失數(shù)據(jù),那么 RDB 不適合你。 雖然 Redis 允許你設置不同的保存點(save point)來控制保存 RDB 文件的頻率, 但是, 因為RDB 文件需要保存整個數(shù)據(jù)集的狀態(tài), 所以它并不是一個輕松的操作。 因此你可能會至少 5 分鐘才保存一次 RDB 文件。 在這種情況下, 一旦發(fā)生故障停機, 你就可能會丟失好幾分鐘的數(shù)據(jù)。每次保存 RDB 的時候,Redis 都要 fork() 出一個子進程,并由子進程來進行實際的持久化工作。 在數(shù)據(jù)集比較龐大時, fork() 可能會非常耗時,造成服務器在某某毫秒內停止處理客戶端; 如果數(shù)據(jù)集非常巨大,并且 CPU 時間非常緊張的話,那么這種停止時間甚至可能會長達整整一秒(當然了,AOF 重寫也需要進行 fork() ,不過無論 AOF 重寫的執(zhí)行間隔有多長,數(shù)據(jù)的持久性都不會有任何損失)

9、AOF 優(yōu)劣勢

優(yōu)勢:

使用 AOF 持久化會讓 Redis 的持久性比較好(much more durable):你可以設置不同的 fsync 策略,比如無 fsync ,每秒鐘一次 fsync ,或者每次執(zhí)行寫入命令時 fsync 。 AOF 的默認策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的性能,并且就算發(fā)生故障停機,也最多只會丟失一秒鐘的數(shù)據(jù)( fsync 會在后臺線程執(zhí)行,所以主線程可以繼續(xù)努力地處理命令請求)。AOF 文件是一個只進行追加操作的日志文件(append only log), 因此對 AOF 文件的寫入不需要進行 seek , 即使日志因為某些原因而包含了未寫入完整的命令(比如寫入時磁盤已滿,寫入中途停機,等等), redis-check-aof 工具也可以輕易地修復這種問題。AOF 文件有序地保存了對數(shù)據(jù)庫執(zhí)行的所有寫入操作, 這些寫入操作以 Redis 協(xié)議的格式保存, 因此?AOF 文件的內容非常容易被人讀懂, 對文件進行分析(parse)也很輕松。 導出(export) AOF 文件也非常簡單: 舉個例子, 如果你不小心執(zhí)行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那么只要停止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重啟 Redis , 就可以將數(shù)據(jù)集恢復到 FLUSHALL 執(zhí)行之前的狀態(tài)。

劣勢:

對于相同的數(shù)據(jù)集來說,AOF 文件的體積通常要大于 RDB 文件的體積。根據(jù)所使用的 fsync 策略,AOF 的速度可能會慢于 RDB 。 在一般情況下, 每秒 fsync 的性能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。AOF 在過去曾經發(fā)生過這樣的 bug : 因為個別命令的原因,導致 AOF 文件在重新載入時,無法將數(shù)據(jù)集恢復成保存時的原樣。(舉個例子,阻塞命令 BRPOPLPUSH 就曾經引起過這樣的 bug) 測試套件里為這種情況添加了測試: 它們會自動生成隨機的、復雜的數(shù)據(jù)集, 并通過重新載入這些數(shù)據(jù)來確保一切正常。 雖然這種 bug 在 AOF 文件中并不常見, 但是對比來說, RDB 幾乎是不可能出現(xiàn)這種 bug 的。

六、數(shù)據(jù)過期策略

1、假如redis的key過期之后,會立即刪除嗎?

Redis對數(shù)據(jù)設置數(shù)據(jù)的有效時間,數(shù)據(jù)過期以后,就需要將數(shù)據(jù)從內存中刪除掉??梢园凑詹煌囊?guī)則進行刪除,這種刪除規(guī)則就被稱之為數(shù)據(jù)的刪除策略(數(shù)據(jù)過期策略)。

2、Redis數(shù)據(jù)刪除策略-惰性刪除

惰性刪除:設置該key過期時間后,我們不去管它,當需要該key時,我們在檢查其是否過期,如果過期,我們就刪掉它,反之返回該key。

優(yōu)點:對CPU友好,只會在使用該key時才會進行過期檢查,對于很多用不到的key不用浪費時間進行過期檢查缺點:對內存不友好,如果一個key已經過期,但是一直沒有使用,那么該key就會一直存在內存中,內存永遠不會釋放?

3、Redis數(shù)據(jù)刪除策略-定期刪除

定期刪除:每隔一段時間,我們就對一些key進行檢查,刪除里面過期的key(從一定數(shù)量的數(shù)據(jù)庫中取出一定數(shù)量的隨機key進行檢查,并刪除其中的過期key)。定期清理有兩種模式:

SLOW模式是定時任務,執(zhí)行頻率默認為10hz,每次不超過25ms,以通過修改配置文件redis.conf 的hz 選項來調整這個次數(shù)。FAST模式執(zhí)行頻率不固定,但兩次間隔不低于2ms,每次耗時不超過1ms。優(yōu)點:可以通過限制刪除操作執(zhí)行的時長和頻率來減少刪除操作對 CPU 的影響。另外定期刪除,也能有效釋放過期鍵占用的內存。缺點: 難以確定刪除操作執(zhí)行的時長和頻率。

4、Redis選擇的策略

?Redis的過期刪除策略: 惰性刪除 + 定期刪除兩種策略進行配合使用。

七、數(shù)據(jù)淘汰策略

數(shù)據(jù)的淘汰策略:當Redis中的內存不夠用時,此時在向Redis中添加新的key,那么Redis就會按照某一種規(guī)則將內存中的數(shù)據(jù)刪除掉,這種數(shù)據(jù)的刪除規(guī)則被稱之為內存的淘汰策略。

1、Redis支持8種不同策略來選擇要刪除的key:

noeviction: 不淘汰任何key,但是內存滿時不允許寫入新數(shù)據(jù),默認就是這種策略。volatile-ttl: 對設置了TTL的key,比較key的剩余TTL值,TTL越小越先被淘汰。allkeys-random:對全體key ,隨機進行淘汰。volatile-random:對設置了TTL的key ,隨機進行淘汰。allkeys-lru: 對全體key,基于LRU算法進行淘汰。volatile-lru:對設置了TTL的key,基于LRU算法進行淘汰。allkeys-lfu: 對全體key,基于LFU算法進行淘汰。volatile-lfu: 對設置了TTL的key,基于LFU算法進行淘汰。?

2、 LRU與LFU區(qū)別

LRU(Least Recently Used)最近最少使用。用當前時間減去最后一次訪問時間,這個值越大則淘汰優(yōu)先級越高。

key1是在3s之前訪問的,key2是在9s之前訪問的,刪除的就是key2。LFU (Least Frequently Used) 最少頻率使用。會統(tǒng)計每個key的訪問頻率,值越小淘汰優(yōu)先級越高。

key1最近5s訪問了4次, ey2最近5s訪問了9次,刪除的就是key1。

3、淘汰策略使用建議

優(yōu)先使用 allkeys-lru 策略。充分利用LRU 算法的優(yōu)勢,把最近最常訪問的數(shù)據(jù)留在緩存中。如果業(yè)務有明顯的冷熱數(shù)據(jù)區(qū)分,建議使用。如果業(yè)務中數(shù)據(jù)訪問頻率差別不大,沒有明顯冷熱數(shù)據(jù)區(qū)分,建議使用 allkeys-random,隨機選擇淘汰。如果業(yè)務中有置頂?shù)男枨螅梢允褂?volatile-lru 策略,同時置頂數(shù)據(jù)不設置過期時間,這些數(shù)據(jù)就一直不被刪除會淘汰其他設置過期時間的數(shù)據(jù)。?如果業(yè)務中有短時高頻訪問的數(shù)據(jù),可以使用 allkeys-lfu 或 volatile-lfu 策略。

4、關于數(shù)據(jù)淘汰策略其他的面試問題

數(shù)據(jù)庫有1000萬數(shù)據(jù),Redis只能緩存20w數(shù)據(jù),如何保證Redis中的數(shù)據(jù)都是熱點數(shù)據(jù)?

使用allkeys-lru(挑選最近最少使用的數(shù)據(jù)淘汰)淘汰策略,留下來的都是經常訪問的熱點數(shù)據(jù)。

Redis的內存用完了會發(fā)生什么?

主要看數(shù)據(jù)淘汰策略是什么? 如果是默認的配置 (noeviction ),會直接報錯。?

5、概括

數(shù)據(jù)淘汰策略

Redis提供了8種不同的數(shù)據(jù)淘汰策略,默認是noeviction不刪除任何數(shù)據(jù),內存不足直接報錯。LRU: 最少最近使用。用當前時間減去最后一次訪問時間,這個值越大則淘汰優(yōu)先級越高。LFU:最少頻率使用。會統(tǒng)計每個key的訪問頻率,值越小淘汰優(yōu)先級越高?。

平時開發(fā)過程中用的比較多的就是allkeys-lru (結合自己的業(yè)務場景) ,因為allkeys-lru保存下來的數(shù)據(jù)一般都是熱點數(shù)據(jù)。

6、?面試官: Redis的數(shù)據(jù)淘汰策略有哪些?

嗯,這個在redis中提供了很多種,默認是noeviction,不刪除任何數(shù)據(jù),內部不足直接報錯??梢栽趓edis的配置文件中進行設置的,里面有兩個非常重要的概念,一個是LRU,另外一個是LFU。LRU的意思就是最少最近使用,用當前時間減去最后一次訪問時間,這個值越大則淘汰優(yōu)先級越高。LFU的意思是最少頻率使用。會統(tǒng)計每個key的訪問頻率,值越小淘汰優(yōu)先級越高。我們在項目設置的是allkeys-lru,挑選最近最少使用的數(shù)據(jù)淘汰,把一些經常訪問的key留在redis中。

7、面試官:數(shù)據(jù)庫有1000萬數(shù)據(jù),Redis只能緩存20w數(shù)據(jù),如何保證Redis中的數(shù)據(jù)都是熱點數(shù)據(jù)?

嗯,我想一下~~可以使用 alkeys-lru(挑選最近最少使用的數(shù)據(jù)淘汰)淘汰策略,那留下來的都是經常訪問的熱點數(shù)據(jù)?

8、面試官: Redis的內存用完了會發(fā)生什么?

會觸發(fā)數(shù)據(jù)淘汰策略,默認為noeviction,不刪除任何數(shù)據(jù),內部不足直接報錯。但是redis有8中淘汰策略,其中有兩種主要概念就是LRU和LFU。其余的幾種淘汰策略主要圍繞這兩種進行。

?八、Redis分布式鎖使用場景

需要結合項目中的業(yè)務進行回答,通常情況下,分布式鎖使用的場景:

集群情況下的定時任務、搶單、冪等性場景

1、搶卷場景下的代碼流程

這是它的流程:?

2、模擬本地多線程情況下?lián)尵淼膱?zhí)行流程

正常情況:

線程1查詢優(yōu)惠價,查看庫存數(shù)量是否充足,如果充足就減庫存,否則拋出異常。在線程1執(zhí)行完后線程2進行同樣的流程。

多線程情況:

?假設此時庫存剩余1

?

?線程1查詢庫存看到庫存為1,查完后切換到線程2查詢到庫存也是1。然后再切換到線程1取查看庫存是否充足,結果充足,然后庫存減1為0。再切換到線程2查看庫存為1,結果充足,然后減少庫存庫存為-1。

解決方法:

添加互斥鎖

?流程如下:

?3、服務集群部署情況

使用setnx加鎖情況:

?

結果發(fā)生8080和8081服務器都能查詢到庫存為1。這是因為setnx是本地鎖只能在當前的JVM進行加鎖,但是集群部署是多臺服務器,每個服務器都有自己的JVM,就導致了數(shù)據(jù)異常的情況。

使用redisson分布式鎖情況:

線程1獲取分布式鎖之后,其他服務器包括本服務器的線程不能再獲取鎖,只有當線程1釋放鎖之后才可以獲取鎖。

九、Redis分布式鎖實現(xiàn)原理(setnx,redisson)

1、setnx命令

Redis實現(xiàn)分布式鎖主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在則SET)的簡寫。

?2、setnx執(zhí)行流程

3、setnx命令缺陷

死鎖問題

根據(jù)上圖流程,線程在獲取鎖成功以后,在執(zhí)行業(yè)務的時候突然服務器宕機了,但是此刻依舊沒有釋放鎖,導致鎖無法釋放就會導致死鎖。

代碼未執(zhí)行完但鎖時間到期了

如果添加了鎖的過期時間,會出現(xiàn)業(yè)務代碼未執(zhí)行完就會釋放鎖。這是因為鎖的時間難以預估出現(xiàn)代碼未執(zhí)行完出現(xiàn)鎖提前釋放,無法保證代碼的原子性。?

4、Redis實現(xiàn)分布式鎖如何合理的控制鎖的有效時長?

根據(jù)業(yè)務執(zhí)行時間進行評估給鎖續(xù)期

5、Redisson實現(xiàn)分布式鎖的使用流程

注:releaseTime過期時間

當線程1嘗試獲取鎖并且獲取鎖成功的時候,就會新開一個線程Watch dog,Watch dog會監(jiān)聽鎖的情況,每隔releaseTime/3時間會做一次續(xù)期,每次續(xù)期就會重置過期時間。比如說過期時間為30秒,那么每30/3=10秒進行一次續(xù)期,將過期時間重置為30秒。如果業(yè)務執(zhí)行完成的話,就會手動釋放鎖。釋放鎖以后watch dog就不需要再進行監(jiān)聽了,因為key已經被刪除了。

如果線程2嘗試獲取鎖,但是線程1占用著鎖,就會獲取鎖失敗,但是線程2不會終止,而是在有限的次數(shù)不斷循環(huán),直到獲取鎖位置。

6、redisson執(zhí)行代碼

首先是獲取鎖,然后是嘗試獲取鎖,根據(jù)嘗試獲取鎖的結果判斷是否獲取鎖成功,如果獲取鎖成功那么就可以執(zhí)行業(yè)務代碼。

7、Redisson實現(xiàn)的分布式鎖-鎖可重入

如下圖代碼:

可重入的邏輯:每一個線程都有自己的線程id,加鎖首先判斷是否為同一個線程id,如果為同一個線程id,那么就可以加鎖。?

在add1()方法中,線程1創(chuàng)建了一把鎖名為heimalock。然后在加鎖的代碼中執(zhí)行add2()方法。但是add2()方法中也添加了一把鎖,也名為heimalock。在redis中根據(jù)hash結構來記錄線程id和重入次數(shù)。如下圖為當前的線程id和可重入情況:

?key為heimalock,field為當前線程id,value為重入鎖的次數(shù)。因為當前線程執(zhí)行了add1()和add()2方法所以擁有兩把鎖。

當add2()方法釋放鎖時候,重入次數(shù)就會減1,如下圖

執(zhí)行add1()方法中的lock.unlock()方法就會釋放鎖,如下圖

因此可重入鎖優(yōu)點是可以避免死鎖,提高了程序的可靠性和效率?

8、Redisson實現(xiàn)的分布式鎖——主從一致性?

一般情況下都會使用redis的主從集群架構,主節(jié)點寫數(shù)據(jù),從節(jié)點讀數(shù)據(jù)

此時線程1獲取到了鎖,對主節(jié)點進行寫數(shù)據(jù),但是突然主節(jié)點宕機了導致修改的數(shù)據(jù)還沒有同步到從節(jié)點。那么就會開啟哨兵模式,將從節(jié)點設置為主節(jié)點。但會出現(xiàn)一種情況,線程1因為宕機沒有釋放鎖,并且信息沒有同步到從節(jié)點。所以新節(jié)點就會從新設置的主節(jié)點獲取同一把鎖,因此線程2就獲取到了和線程1相同的鎖。

這時候會出現(xiàn)兩個線程獲取同一把鎖,如果業(yè)務還在執(zhí)行就可能出現(xiàn)臟數(shù)據(jù)的情況。因為宕機的節(jié)點修改后的數(shù)據(jù)沒有同步到先建立的主節(jié)點,導致現(xiàn)場2獲取的數(shù)據(jù)不是提交過的數(shù)據(jù)。

為了解決這種主從一致性的情況,redis提供了另外一種鎖(不推薦):

RedLock(紅鎖):不能只在一個redis實例上創(chuàng)建鎖,應該是在多個redis實例上創(chuàng)建鎖(n /2 + 1),避免在個redis實上加鎖。?

?9、概括

redis分布式鎖,是如何實現(xiàn)的?

先按照自己簡歷上的業(yè)務進行描述分布式鎖使用的場景我們當使用的redisson實現(xiàn)的分布式鎖,底層是setnx和lua腳本(保證原子性)

Redisson實現(xiàn)分布式鎖如何合理的控制鎖的有效時長?

在redisson的分布式鎖中,提供了一個WatchDog(看門狗),一個線程獲取鎖成功以后WatchDog會給持有鎖的線程續(xù)期 (默認是每隔10秒續(xù)期一次)

Redisson的這個鎖,可以重入嗎?

可以重入,多個鎖重入需要判斷是否是當前線程,在redis中進行存儲的時候使用的hash結構來存儲線程信息和重入的次數(shù)

Redisson鎖能解決主從數(shù)據(jù)一致的問題嗎

不能解決,但是可以使用redisson提供的紅鎖來解決,但是這樣的話,性能就太低了,如果業(yè)務中非要保證數(shù)據(jù)的強一致性,建議采用zookeeper實現(xiàn)的分布式鎖

10、?面試官: Redis分布式鎖如何實現(xiàn)?

嗯,在redis中提供了一個命令setnx(SET ifnot exists)由于redis的單線程的,用了命令之后,只能有一個客戶端對某一個key設置值,在沒有過期或刪除key的時候是其他客戶端是不能設置這個key的

11、面試官:好的,那你如何控制Redis實現(xiàn)分布式鎖有效時長呢?

嗯,的確,redis的setnx指令不好控制這個問題,我們當時采用的redis的一個框架redisson實現(xiàn)的。在redisson中需要手動加鎖,并且可以控制鎖的失效時間和等待時間,當鎖住的一個業(yè)務還沒有執(zhí)行完成的時候,在redisson中引入了一個看門狗機制,就是說每隔一段時間就檢查當前業(yè)務是否還持有鎖,如果持有就增加加鎖的持有時間,當業(yè)務執(zhí)行完成之后需要使用釋放鎖就可以了。還有一個好處就是,在高并發(fā)下,一個業(yè)務有可能會執(zhí)行很快,先客戶1持有鎖的時候,客戶2來了以后并不會馬上拒絕,它會自選不斷嘗試獲取鎖,如果客戶1釋放之后,客戶2就可以馬上持有鎖,性能也得到了提升。

12、面試官:好的,redisson實現(xiàn)的分布式鎖是可重入的嗎?

嗯,是可以重入的。這樣做是為了避免死鎖的產生。這個重入其實在內部就是判斷是否是當前線程持有的鎖,如果是當前線程持有的鎖就會計數(shù),如果釋放鎖就會在計算上減一。在存儲數(shù)據(jù)的時候采用的hash結構,大key可以按照自己的業(yè)務進行定制,其中小key是當前線程的唯一標識,value是當前線程重入的次數(shù)

13、面試官: redisson實現(xiàn)的分布式鎖能解決主從一致性的問題嗎?

這個是不能的,比如,當線程1加鎖成功后,master節(jié)點數(shù)據(jù)會異步復制到slave節(jié)點,此時當前持有Redis鎖的master節(jié)點宕機,slave節(jié)點被提升為新的master節(jié)點,假如現(xiàn)在來了一個線程2,再獲取鎖,就會出現(xiàn)兩個線程獲取同一把鎖,導致臟數(shù)據(jù)的出現(xiàn)。

十、主從復制,主從同步流程(高并發(fā))

1、主從復制

單節(jié)點Redis的并發(fā)能力是有上限的,要進一步提高Redis的并發(fā)能力,就需要搭建主從集群,實現(xiàn)讀寫分離。

2、主從同步原理——主從同步變量

?注:repl_baklog用來記錄除第一次同步以后的數(shù)據(jù)

流程:

首先從節(jié)點執(zhí)行replicaof命令用來建立連接, 然后從節(jié)點請求數(shù)據(jù)同步。主節(jié)點收到請求以后進行判斷是否第一次進行同步,通過判斷replid是否一致。因為剛開始每個數(shù)據(jù)庫的replid都不同,只有當?shù)谝淮瓮胶笾鲝膔eplid才會一致。因此主節(jié)點會根據(jù)replid判斷是否是第一次同步。如果是第一次同步,那么主節(jié)點會返回它的節(jié)點信息給從數(shù)據(jù)庫,從節(jié)點保存版本信息以后,主節(jié)點會進行bgsave將redis的數(shù)據(jù)生成RDB文件,然后將RDB文件發(fā)送給從數(shù)據(jù)庫。然后從數(shù)據(jù)庫刪除本地文件加載RDB文件。在生成RDB文件也需要時間,因此也會有主節(jié)點數(shù)據(jù)的寫入,因此在生成RDB文件期間將寫入的記錄保存到repl_baklog中。再將repl_baklog中的命令發(fā)送給從節(jié)點,從節(jié)點收到后執(zhí)行收到命令實現(xiàn)主從同步。如果不是第一次同步,那么在第2步從節(jié)點會將自己的偏移量和replid發(fā)送給主節(jié)點。主節(jié)點判斷replid不是第一次同步,就會將數(shù)據(jù)版本信息返回給從節(jié)點,里面也包括replid和offset。從節(jié)點然后保存這些信息。然后同步的時候不再發(fā)送RDB文件,而是將repl_baklog文件發(fā)送給從節(jié)點。至于發(fā)送多少呢?由偏移量計算覺得,比如從節(jié)點偏移量是50,主節(jié)點偏移量是80,那么主節(jié)點就會發(fā)送50-80這些偏移量的數(shù)據(jù)。當發(fā)送repl_baklog后,會將從節(jié)點的偏移量改變?yōu)樽钚录?0。

3、主從同步原理——主從增量同步?

?流程:

從節(jié)點重啟或者非第一次同步之后數(shù)據(jù)發(fā)生變化,則進行主從增量同步。從節(jié)點發(fā)送replid和offset后,主節(jié)點通過replid是不是第一次同步,如果不是第一次同步回復continue給從從節(jié)點。然后主節(jié)點去repl_baklog獲取offset數(shù)據(jù)和從節(jié)點的offset進行對比,發(fā)送偏移量的數(shù)據(jù)給從節(jié)點。然后從節(jié)點獲取數(shù)據(jù)后進行同步。

?4、概括

介紹一下redis的主從同步?

單節(jié)點Redis的并發(fā)能力是有上限的,要進一步提高Redis的并發(fā)能力,就需要搭建主從集群,實現(xiàn)般都是一主多從,主節(jié)點負責寫數(shù)據(jù),從節(jié)點負責讀數(shù)據(jù)。

能說一下,主從同步數(shù)據(jù)的流程?

全量同步

從節(jié)點請求主節(jié)點同步數(shù)據(jù) (replication id、 offset)。主節(jié)點判斷是否是第一次請求,是第一次就與從節(jié)點同步版本信息 (replication id和offset)主節(jié)點執(zhí)行bgsave,生成rdb文件后,發(fā)送給從節(jié)點去執(zhí)行。在rdb生成執(zhí)行期間,主節(jié)點會以命令的方式記錄到緩沖區(qū)(一個日志文件)。把生成之后的命令日志文件發(fā)送給從節(jié)點進行同步。增量同步

從節(jié)點請求主節(jié)點同步數(shù)據(jù),主節(jié)點判斷不是第一次請求,不是第一次就獲取從節(jié)點的offset值。主節(jié)點從命令日志中獲取offset值之后的數(shù)據(jù),發(fā)送給從節(jié)點進行數(shù)據(jù)同步。

5、面試官: Redis集群有哪些方案,知道嗎?

??嗯~~,在Redis中提供的集群方案總共有三種:主從復制、哨兵模式、Redis分片集群。

6、面試官:那你來介紹一下主從同步

嗯,是這樣的,單節(jié)點Redis的并發(fā)能力是有上限的,要進一步提高Redis的并發(fā)能力,可以搭建主從集群,實現(xiàn)讀寫分離。一般都是一主多從,主節(jié)點負責寫數(shù)據(jù),從節(jié)點負責讀數(shù)據(jù),主節(jié)點寫入數(shù)據(jù)之后,需要把數(shù)據(jù)同步到從節(jié)點中。

7、面試官:能說一下,主從同步數(shù)據(jù)的流程?

嗯~~,好!主從同步分為了兩個階段,一個是全量同步,一個是增量同步。全量同步是指從節(jié)點第一次與主節(jié)點建立連接的時候使用全量同步,流程是這樣的:第一:從節(jié)點請求主節(jié)點同步數(shù)據(jù),其中從節(jié)點會攜帶自己的replication id和offset偏移量。第二:主節(jié)點判斷是否是第一次請求,主要判斷的依據(jù)就是,主節(jié)點與從節(jié)點是否是同一個。replicationid,如果不是,就說明是第一次同步,那主節(jié)點就會把自己的replication id和offset發(fā)送給從節(jié)點,讓從節(jié)點與主節(jié)點的信息保持一致。第三:在同時主節(jié)點會執(zhí)行bgsave,生成rdb文件后,發(fā)送給從節(jié)點去執(zhí)行,從節(jié)點先把自己的數(shù)據(jù)清空,然后執(zhí)行主節(jié)點發(fā)送過來的rdb文件,這樣就保持了一致。當然,如果在rdb生成執(zhí)行期間,依然有請求到了主節(jié)點,而主節(jié)點會以命令的方式記錄到緩沖區(qū),緩沖區(qū)是一個日志文件,最后把這個日志文件發(fā)送給從節(jié)點,這樣就能保證主節(jié)點與從節(jié)點完全一致了,后期再同步數(shù)據(jù)的時候,都是依賴于這個日志文件,這個就是全量同步。增量同步指的是,當從節(jié)點服務重啟之后,數(shù)據(jù)就不一致了,所以這個時候,從節(jié)點會請求主節(jié)點同步數(shù)據(jù),主節(jié)點還是判斷不是第一次請求,不是第一次就獲取從節(jié)點的offset值,然后主節(jié)點從命令日志中獲取offset值之后的數(shù)據(jù),發(fā)送給從節(jié)點進行數(shù)據(jù)同步。

十一、哨兵模式,集群腦裂 (高可用)

1、哨兵的作用

Redis提供了哨兵(Sentinel)機制來實現(xiàn)主從集群的自動故障恢復。哨兵的結構和作用如下:

監(jiān)控: Sentinel會不斷檢查您的master和slave是否按預期工作。自動故障恢復:如果master故障,Sentinel會將一個slave提升為master。當故障實例恢復后也以新的master為主。通知:Sentinel充當Redis客戶端的服務發(fā)現(xiàn)來源,當集群發(fā)生故障轉移時,會將最新信息推送給Redis的客戶端。

?2、服務狀態(tài)監(jiān)控

Sentinel基于心跳機制監(jiān)測服務狀態(tài),每隔1秒向集群的每個實例發(fā)送ping命令

主觀下線: 如果某sentinel節(jié)點發(fā)現(xiàn)某實例未在規(guī)定時間響應,則認為該實例主觀下線??陀^下線: 若超過指定數(shù)量(quorum)的sentinel都認為該實例主觀下線,則該實例客觀下線。quorum值最好超過Sentinel實例數(shù)量的一半。

?哨兵選主規(guī)則

首先判斷主與從節(jié)點斷開時間長短如超過指定值就排該從節(jié)點。因為斷開時間越長,丟失的數(shù)據(jù)越多,所以選擇斷開時間短的,丟失數(shù)據(jù)少的節(jié)點為主節(jié)點。然后判斷從節(jié)點的slave-priority值,越小優(yōu)先級越高。如果slave-prority一樣,則判斷slave節(jié)點的offset值,越大優(yōu)先級越高。因為offset的值越大,說明該從節(jié)點與主節(jié)點的數(shù)據(jù)差越少,所以選offset大的為主節(jié)點。最后是判斷slave節(jié)點的運行id大小,越小優(yōu)先級越高。

3、Redis集群腦裂

這是正常情況的redis主從架構

假如此時因為網(wǎng)絡的原因?,將主節(jié)點和從節(jié)點分開來了。并且主節(jié)點是一個分區(qū),其他從節(jié)點是另外一個分區(qū)。這個時候從節(jié)點分區(qū)就會從從節(jié)點選出一個主節(jié)點,然后就會出現(xiàn)兩個master主節(jié)點,就好像腦裂了一樣。

不過老的master沒有掛,只是網(wǎng)絡出現(xiàn)的問題,客戶端還可以去對老的主節(jié)點進行寫數(shù)據(jù)。這就是腦裂的現(xiàn)象。

但是老的主節(jié)點寫入的數(shù)據(jù)不能同步到新的主節(jié)點。

此時網(wǎng)絡恢復了,哨兵會將老的master強制降為salve節(jié)點。這個savle就會送master中同步數(shù)據(jù),就會把自己的數(shù)據(jù)清空然后同步master的數(shù)據(jù)。

?然后客戶端連接新的master,變成正常情況。不過丟失的數(shù)據(jù)依舊丟失了

?解決方法:

redis中有兩個配置參數(shù)

min-replicas-to-write 1 表示最少的salve節(jié)點為1個。必須每個主節(jié)點至少有一個從節(jié)點,才可以接受客戶端的請求,否則失敗。min-replicas-max-lag 5表示數(shù)據(jù)復制和同步的延遲不能超過5秒。

4、概括?

怎么保證Redis的高并發(fā)高可用

哨兵模式:實現(xiàn)主從集群的自動故障恢復(監(jiān)控、自動故障恢復、通知)

你們使用redis是單點還是集群,哪種集群

主從(1主1從)+哨兵就可以了。單節(jié)點不超過10G內存,如果Redis內存不足則可以給不同服務分配獨立的Redis主從節(jié)點。

redis集群腦裂,該怎么解決呢?

集群腦裂是由于主節(jié)點和從節(jié)點和sentinel處于不同的網(wǎng)絡分區(qū),使得sentinel沒有能夠心跳感知到主節(jié)點,所以通過選舉的方式提升了一個從節(jié)點為主,這樣就存在了兩個master,就像大腦分裂了一樣,這樣會導致客戶端還在老的主節(jié)點那里寫入數(shù)據(jù),新節(jié)點無法同步數(shù)據(jù),當網(wǎng)絡恢復后,sentinel會將老的主節(jié)點降為從節(jié)點,這時再從新master同步數(shù)據(jù),就會導致數(shù)據(jù)丟失解決:我們可以修改redis的配置,可以設置最少的從節(jié)點數(shù)量以及縮短主從數(shù)據(jù)同步的延遲時間,達不到要求就拒絕請求就可以避免大量的數(shù)據(jù)丟失

5、面試官:怎么保證Redis的高并發(fā)高可用

首先可以搭建主從集群,再加上使用redis中的哨兵模式,哨兵模式可以實現(xiàn)主從集群的自動故障恢復,里面就包含了對主從服務的監(jiān)控、自動故障恢復、通知;如果master故障,Sentinel會將個slave提升為master。當故障實例恢復后也以新的master為主;同時Sentinel也充當Redis客戶端的服務發(fā)現(xiàn)來源,當集群發(fā)生故障轉移時,會將最新信息推送給Redis的客戶端,所以一般項目都會采用哨兵的模式來保證redis的高并發(fā)高可用。

6、面試官:你們使用redis是單點還是集群,哪種集群

嗯!,我們當時使用的是主從 (1主1從)加哨兵。一般單節(jié)點不超過10G內存,如果Redis內存不足則可以給不同服務分配獨立的Redis主從節(jié)點。盡量不做分片集群。因為集群維護起來比較麻煩,并且集群之間的心跳檢測和數(shù)據(jù)通信會消耗大量的網(wǎng)絡帶寬,也沒有辦法使用lua腳本和事務。

7、redis集群腦裂,該怎么解決呢?

嗯!這個在項目很少見,不過腦裂的問題是這樣的,我們現(xiàn)在用的是redis的哨兵模式集群的。有的時候由于網(wǎng)絡等原因可能會出現(xiàn)腦裂的情況,就是說,由于redis master節(jié)點和redis salve節(jié)點和sentinel處于不同的網(wǎng)絡分區(qū),使得sentinel沒有能夠心跳感知到master,所以通過選舉的方式提升了個salve為master,這樣就存在了兩個master,就像大腦分裂了一樣,這樣會導致客戶端還在old master那里寫入數(shù)據(jù),新節(jié)點無法同步數(shù)據(jù),當網(wǎng)絡恢復后,sentinel會將oldmaster降為salve,這時再從新master同步數(shù)據(jù),這會導致old master中的大量數(shù)據(jù)丟失。關于解決的話,我記得在redis的配置中可以設置: 第一可以設置最少的salve節(jié)點個數(shù),比如設置至/要有一個從節(jié)點才能同步數(shù)據(jù),第二個可以設置主從數(shù)據(jù)復制和同步的延遲時間,達不到要求就拒絕請求,就可以避免大量的數(shù)據(jù)丟失?。

十二、分片集群、數(shù)據(jù)讀寫規(guī)則

1、分片集群結構?

主從和哨兵可以解決高可用、高并發(fā)讀的問題。但是依然有兩個問題沒有解決:

海量數(shù)據(jù)存儲問題高并發(fā)寫的問題

使用分片集群可以解決上述問題,分片集群特征:

集群中有多個master,每個master保存不同數(shù)據(jù)。每個master都可以有多個slave節(jié)點。master之間通過ping監(jiān)測彼此健康狀態(tài)??蛻舳苏埱罂梢栽L問集群任意節(jié)點,最終都會被轉發(fā)到正確節(jié)點。

?2、分片集群架構——數(shù)據(jù)讀寫

Redis 分片集群引入了哈希槽的概念,Redis 集群有 16384 個哈希槽,每個key通過CRC16 校驗后對16384 取模來決定放置哪個槽,集群的每個節(jié)點負責一部分hash 槽。

?

對于每個master,會根據(jù)master的數(shù)量對哈希槽進行均分。然后對于每個寫或者讀的key經過CRC16的計算其hash值并取模16384就可以獲取所在的集群位置。?

3、概括

redis的分片集群有什么作用

集群中有多個master,每個master保存不同數(shù)據(jù)每個master都可以有多個slave節(jié)點master之間通過ping監(jiān)測彼此健康狀態(tài)客戶端請求可以訪問集群任意節(jié)點,最終都會被轉發(fā)到正確節(jié)點

Redis分片集群中數(shù)據(jù)是怎么存儲和讀取的?

Redis 分片集群引入了哈希槽的概念,Redis 集群有 16384 個哈希槽。將16384個插槽分配到不同的實例。讀寫數(shù)據(jù): 根據(jù)key的有效部分計算哈希值,對16384取余(有效部分,如果key前面有大括號,大括號的內容就是有效部分,如果沒有,則以kev本身做為有效部分)余數(shù)做為插槽,尋找插槽所在的實例。

?4、面試官: redis的分片集群有什么作用

分片集群主要解決的是,海量數(shù)據(jù)存儲的問題,集群中有多個master,每個master保存不同數(shù)據(jù),并且還可以給每個master設置多個slave節(jié)點,就可以繼續(xù)增大集群的高并發(fā)能力。同時每個master之間通過ping監(jiān)測彼此健康狀態(tài),就類似于哨兵模式了。當客戶端請求可以訪問集群任意節(jié)點,最終都會被轉發(fā)到正確節(jié)點

5、面試官: Redis分片集群中數(shù)據(jù)是怎么存儲和讀取的?

嗯~,在redis集群中是這樣的,Redis 集群引入了哈希槽的概念,有 16384 個哈希槽,集群中每個主節(jié)點綁定了一定范圍的哈希槽范圍,key通過 CRC16 校驗后對 16384 取模來決定放置哪個槽,通過槽找到對應的節(jié)點進行存儲。取值的邏輯是一樣的

十三、 Redis是單線程,為什么速度還這么快?

1、Redis是單線程的,但是為什么還那么快?

Redis是純內存操作,執(zhí)行速度非???采用單線程,避免不必要的上下文切換可競爭條件,多線程還要考慮線程安全問題 使用I/O多路復用模型,非阻塞IO

2、能解釋一下I/O多路復用模型?

用戶空間和內核空間常見的IO模型

阻塞IO (BlockingIO)非阻塞IO (Nonblocking IO)IO多路復用 (IO?Multiplexing)Redis網(wǎng)終模型

3、用戶空間和內核空間

Linux系統(tǒng)中一個進程使用的內存情況劃分兩部分: 內核空間、用戶空間

用戶空間:只能執(zhí)行受限的命令 (Ring3),而且不能直接調用系統(tǒng)資源必須通過內核提供的接口來訪問內核空間:可以執(zhí)行特權命令 (Ring0),調用一切系統(tǒng)資源

Linux系統(tǒng)為了提高lO效率,會在用戶空間和內核空間都加入緩沖區(qū)

寫數(shù)據(jù)時,要把用戶緩沖數(shù)據(jù)拷貝到內核緩沖區(qū),然后寫入設備讀數(shù)據(jù)時,要從設備讀取數(shù)據(jù)到內核緩沖區(qū),然后拷貝到用戶緩沖區(qū)?

但是會出現(xiàn)兩個問題

用戶空間和硬件之間隔著內核空間,如果用戶空間接受消息,但是內核空間沒有從硬件傳來的消息就會一直等待,這個等待時間就會造成時間浪費。用戶空間向硬件發(fā)送消息,就會將用戶緩沖區(qū)的數(shù)據(jù)拷貝到內核空間。這么一層一層的拷貝會造成巨大的資源浪費。

4、阻塞IO

顧名思義,阻塞IO就是兩個階段都必須阻塞等待:

階段一:

用戶進程嘗試讀取數(shù)據(jù)(比如網(wǎng)卡數(shù)據(jù))此時數(shù)據(jù)尚未到達,內核需要等待數(shù)據(jù)此時用戶進程也處于阻塞狀態(tài)階段二:

數(shù)據(jù)到達并拷貝到內核緩沖區(qū),代表已就緒將內核數(shù)據(jù)拷貝到用戶緩沖區(qū)拷貝過程中,用戶進程依然阻塞等待拷貝完成,用戶進程解除阻塞,處理數(shù)據(jù)

用戶想從內核獲取數(shù)據(jù):

用戶空間的用戶應用發(fā)送recvfrom函數(shù)嘗試進行系統(tǒng)調用讀取數(shù)據(jù),但是內核空間沒有數(shù)據(jù),那么該線程就會一直進行等待,用戶線程處于阻塞狀態(tài)。當內核空間有數(shù)據(jù)的時候,那么就需要將內核中的緩沖區(qū)的數(shù)據(jù)拷貝到用戶區(qū)的緩沖區(qū),在這個拷貝的過程中,用戶的進程處于阻塞狀態(tài)。當拷貝完成之后,用戶進程拿到數(shù)據(jù),這個阻塞狀態(tài)才會結束。

?可以看到,阻塞IO模型中,用戶進程在兩個階段都是阻塞狀態(tài)

5、非阻塞IO

顧名思義,非阻塞IO的recvfrom操作會立即返回結果而不是阻塞用戶進程。

階段一:

用戶進程嘗試讀取數(shù)據(jù)(比如網(wǎng)卡數(shù)據(jù))此時數(shù)據(jù)尚未到達,內核需要等待數(shù)據(jù)返回異常給用戶進程用戶進程拿到error后,再次嘗試讀取循環(huán)往復,直到數(shù)據(jù)就緒階段二

將內核數(shù)據(jù)拷貝到用戶緩沖區(qū)拷貝過程中,用戶進程依然阻塞等待拷貝完成,用戶進程解除阻塞,處理數(shù)據(jù)

流程:

用戶進程進行系統(tǒng)調用,但是內核空間沒有數(shù)據(jù)就會返回EWOULDBLOCK異常給用戶進程。用戶進程收到了異常后就會取消阻塞狀態(tài)然后再進行嘗試系統(tǒng)調用,一致循環(huán)下去,直到內核空間有數(shù)據(jù)。當內核空間有數(shù)據(jù)的時候就會將數(shù)據(jù)拷貝給用戶空間,這個拷貝的過程是阻塞狀態(tài)。當拷貝完成就會取消阻塞狀態(tài)。?

可以看到,非阻塞IO模型中,用戶進程在第一個階段是非阻塞,第二個階段是阻塞狀態(tài)。雖然是非阻塞,但性能并沒有得到提高。而且忙等機制會導致CPU空轉,CPU使用率暴增。

6、I/O多路復用

I/O多路復用:是利用單個線程來同時監(jiān)聽多個Socket,并在某個Socket可讀、可寫時得到通知,從而避免無效的等待,充分利用CPU資源。階段一:

用戶進程調用select,指定要監(jiān)聽的Socket集合內核監(jiān)聽對應的多個socket任意一個或多個socket數(shù)據(jù)就緒則返回readable此過程中用戶進程阻塞?階段二:

用戶進程找到就緒的socket依次調用recvfrom讀取數(shù)據(jù)內核將數(shù)據(jù)拷貝到用戶空間用戶進程處理數(shù)據(jù)

過程:

用戶進程會調用select函數(shù)去監(jiān)聽Socket集合,Socket集合中有多個socket。當某個socket可讀或者可寫的時候就會將該socket加入就緒隊列。然后就會返回readable給用戶線程。用戶線程收到readable就會立馬調用recvfrom函數(shù)將內核空間的數(shù)據(jù)拷貝到用戶空間,然后拷貝完成返回用戶線程,用戶線程收到返回后進行監(jiān)聽Socket集合中其他的可用socket,然后反復調用recvfrom,過程如上。

7、多路復用I/O通知方式

I/0多路復用是利用單個線程來同時監(jiān)聽多個Socket,并在某個Socket可讀、可寫時得到通知,從而避免無效的等待充分利用CPU資源。不過監(jiān)聽Socket的方式、通知的方式又有多種實現(xiàn),常見的有:?

selectpollepoll

差異:

select和poll只會通知用戶進程有Socket就緒,但不確定具體是哪個Socket,需要用戶進程逐個遍歷Socket來確認。epoll則會在通知用戶進程Socket就緒的同時,把已就緒的Socket寫入用戶空間?。用戶進程就可以直接看到是哪個Socket了。

8、Redis網(wǎng)絡模型

Redis通過I/O多路復用來提高網(wǎng)絡性能,并且支持各種不同的多路復用實現(xiàn),并且將這些實現(xiàn)進行封裝,提供了統(tǒng)一的高性能事件庫。

Redis6.0以后添加的多線程,其中分別為 命令回復處理器和Redis命令轉換這里添加了多線程。

流程:

redis通過I/O多路復用來進行對socket的監(jiān)聽,然后將socket分發(fā)到對應的處理器,這個過程稱為I/O多路復用+事件派發(fā)。

當監(jiān)聽到可用的socket的時候就會將通知用戶線程,然后用戶線程將內核空間的數(shù)據(jù)拷貝到用戶空間。拷貝后用戶線程接受其數(shù)據(jù),將數(shù)據(jù)轉化為redis命令。選擇執(zhí)行其命令把結果寫入緩沖區(qū),然后將緩沖區(qū)的信息發(fā)送給命令回復處理器。命令回去處理器將結果返回給客戶端。

9、概括

能解釋一下I/O多路復用模型?

I/O多路復用

是指利用單個線程來同時監(jiān)聽多個Socket,并在某個Socket可讀、可寫時得到通知,從而避免無效的等待,充分利用CPU資源。目前的/0多路復用都是采用的epoll模式實現(xiàn),它會在通知用戶進程Socket就緒的同時,把已就緒的Socket寫入用戶空間,不需要挨個遍歷Socket來判斷是否就緒,提升了性能。

Redis網(wǎng)絡模型

就是使用I/O多路復用結合事件的處理器來應對多個Socket請求命令回復處理器,在Redis6.0之后,為了提升更好的性能,使用了多線程來處理回復事件命令回復處理器。命令請求處理器,在Redis6.0之后,將命令的轉換使用了多線程,增加命令轉換速度,在命令執(zhí)行的時候,依然是單線程。

10、?面試官: Redis是單線程的,但是為什么還那么快?

完全基于內存的,C語言編寫。采用單線程,避免不必要的上下文切換可競爭條件。使用多路I/0復用模型,非阻塞IO。例如: bgsave 和 bgrewriteaof 都是在后臺執(zhí)行操作,不影響主線程的正常使用,不會產生阻塞。

11、面試官:能解釋一下I/O多路復用模型?

嗯~~,1/0多路復用是指利用單個線程來同時監(jiān)聽多個Socket,并在某個Socket可讀、可寫時得到通知,從而避免無效的等待,充分利用CPU資源。目前的1/0多路復用都是采用的epoll模式實現(xiàn),它會在通知用戶進程Socket就緒的同時,把已就緒的Socket寫入用戶空間,不需要挨個遍歷Socket來判斷是否就緒,提升了性能。其中Redis的網(wǎng)絡模型就是使用1/0多路復用結合事件的處理器來應對多個Socket請求,比如,提供了連接應答處理器、命令回復處理器,命令請求處理器。在Redis6.0之后,為了提升更好的性能,在命令回復處理器使用了多線程來處理回復事件,在命令請求處理器中,將命令的轉換使用了多線程,增加命令轉換速度,在命令執(zhí)行的時候,依然是單線程。

十四、Redis是什么?

Redis(Remote Dictionary Server)是一個使用 C 語言編寫的,高性能非關系型的鍵值對數(shù)據(jù)庫。與傳統(tǒng)數(shù)據(jù)庫不同的是,Redis 的數(shù)據(jù)是存在內存中的,所以讀寫速度非??欤粡V泛應用于緩存方向。Redis可以將數(shù)據(jù)寫入磁盤中,保證了數(shù)據(jù)的安全不丟失,而且Redis的操作是原子性的。

十五、Redis優(yōu)缺點?

1、優(yōu)點

基于內存操作,內存讀寫速度快。支持多種數(shù)據(jù)類型,包括String、Hash、List、Set、ZSet等。支持持久化。Redis支持RDB和AOF兩種持久化機制,持久化功能可以有效地避免數(shù)據(jù)丟失問題支持事務。Redis的所有操作都是原子性的,同時Redis還支持對幾個操作合并后的原子性執(zhí)行。支持持久化。Redis支持RDB和AOF兩種持久化機制,持久化功能可以有效地避免數(shù)據(jù)丟失問題Redis命令的處理是單線程的。Redis6.0引入了多線程,需要注意的是,多線程用于處理網(wǎng)絡數(shù)據(jù)的讀寫和協(xié)議解析,Redis命令執(zhí)行還是單線程的。

2、缺點

對結構化查詢的支持比較差。數(shù)據(jù)庫容量受到物理內存的限制,不適合用作海量數(shù)據(jù)的高性能讀寫,因此Redis適合的場景主要局限在較小數(shù)據(jù)量的操作。Redis 較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。

十六、Redis為什么這么快?

基于內存:Redis是使用內存存儲,沒有磁盤IO上的開銷。數(shù)據(jù)存在內存中,讀寫速度快。IO多路復用模型:Redis 采用 IO 多路復用技術。Redis 使用單線程來輪詢描述符,將數(shù)據(jù)庫的操作都轉換成了事件,不在網(wǎng)絡I/O上浪費過多的時間。高效的數(shù)據(jù)結構:Redis 每種數(shù)據(jù)類型底層都做了優(yōu)化,目的就是為了追求更快的速度。

十七、既然Redis那么快,為什么不用它做主數(shù)據(jù)庫,只用它做緩存?

事務處理:Redis只支持簡單的事務處理,對于復雜的事務無能為力,比如跨多個鍵的事務處理。數(shù)據(jù)持久化:Redis是內存數(shù)據(jù)庫,數(shù)據(jù)存儲在內存中,如果服務器崩潰或斷電,數(shù)據(jù)可能丟失。雖然Redis提供了數(shù)據(jù)持久化機制,但有一些限制。數(shù)據(jù)處理:Redis只支持一些簡單的數(shù)據(jù)結構,比如字符串、列表、哈希表等。如果需要處理復雜的數(shù)據(jù)結構,比如關系型數(shù)據(jù)庫中的表,那么Redis可能不是一個好的選擇。數(shù)據(jù)安全:Redis沒有提供像主數(shù)據(jù)庫那樣的安全機制,比如用戶認證、訪問控制等等。

雖然Redis非常快,但它還有一些限制,不能完全替代主數(shù)據(jù)庫。所以,使用Redis作為緩存是一種很好的方式,可以提高應用程序的性能,并減少數(shù)據(jù)庫的負載

十八、Redis應用場景有哪些?

緩存熱點數(shù)據(jù):緩解數(shù)據(jù)庫的壓力。利用 Redis 原子性的自增操作,可以實現(xiàn)計數(shù)器的功能,比如統(tǒng)計用戶點贊數(shù)、用戶訪問數(shù)等。分布式鎖:在分布式場景下,無法使用單機環(huán)境下的鎖來對多個節(jié)點上的進程進行同步??梢允褂?Redis 自帶的 SETNX 命令實現(xiàn)分布式鎖,除此之外,還可以使用官方提供的 RedLock 分布式鎖實現(xiàn)。簡單的消息隊列:可以使用Redis自身的發(fā)布/訂閱模式或者List來實現(xiàn)簡單的消息隊列,實現(xiàn)異步操作。限速器:可用于限制某個用戶訪問某個接口的頻率,比如秒殺場景用于防止用戶快速點擊帶來不必要的壓力。好友關系:利用集合的一些命令,比如交集、并集、差集等,實現(xiàn)共同好友、共同愛好之類的功能。

十九、Redis 數(shù)據(jù)類型有哪些?

1、基本數(shù)據(jù)類型:

String:最常用的一種數(shù)據(jù)類型,String類型的值可以是字符串、數(shù)字或者二進制,但值最大不能超過512MB。Hash:Hash 是一個鍵值對集合。Set:無序去重的集合。Set 提供了交集、并集等方法,對于實現(xiàn)共同好友、共同關注等功能特別方便。List:有序可重復的集合,底層是依賴雙向鏈表實現(xiàn)的。ZSet:有序Set。內部維護了一個score的參數(shù)來實現(xiàn)。適用于排行榜和帶權重的消息隊列等場景。

?2、特殊的數(shù)據(jù)類型:

Bitmap:位圖,可以認為是一個以位為單位數(shù)組,數(shù)組中的每個單元只能存0或者1,數(shù)組的下標在 Bitmap 中叫做偏移量。Bitmap的長度與集合中元素個數(shù)無關,而是與基數(shù)的上限有關。Hyperloglog。HyperLogLog 是用來做基數(shù)統(tǒng)計的算法,其優(yōu)點是,在輸入元素的數(shù)量或者體積非常非常大時,計算基數(shù)所需的空間總是固定的、并且是很小的。典型的使用場景是統(tǒng)計獨立訪客。Geospatial?:主要用于存儲地理位置信息,并對存儲的信息進行操作,適用場景如定位、附近的人等。

二十、Redis的內存用完了會怎樣?

如果達到設置的上限,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回)。

也可以配置內存淘汰機制,當Redis達到內存上限時會沖刷掉舊的內容。

二十一、keys命令存在的問題?

redis的單線程的。keys指令會導致線程阻塞一段時間,直到執(zhí)行完畢,服務才能恢復。scan采用漸進式遍歷的方式來解決keys命令可能帶來的阻塞問題,每次scan命令的時間復雜度是O(1),但是要真正實現(xiàn)keys的功能,需要執(zhí)行多次scan。

scan的缺點:在scan的過程中如果有鍵的變化(增加、刪除、修改),遍歷過程可能會有以下問題:新增的鍵可能沒有遍歷到,遍歷出了重復的鍵等情況,也就是說scan并不能保證完整的遍歷出來所有的鍵。

二十二、Redis常見性能問題和解決方案?

Master最好不要做任何持久化工作,包括內存快照和AOF日志文件,特別是不要啟用內存快照做持久化。如果數(shù)據(jù)比較關鍵,某個Slave開啟AOF備份數(shù)據(jù),策略為每秒同步一次。為了主從復制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個局域網(wǎng)內。盡量避免在壓力較大的主庫上增加從庫Master調用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內存資源,導致服務load過高,出現(xiàn)短暫服務暫?,F(xiàn)象。為了Master的穩(wěn)定性,主從復制不要用圖狀結構,用單向鏈表結構更穩(wěn)定,即主從關系為:Master<–Slave1<–Slave2<–Slave3…,這樣的結構也方便解決單點故障問題,實現(xiàn)Slave對Master的替換,也即,如果Master掛了,可以立馬啟用Slave1做Master,其他不變。

二十三、說說為什么Redis過期了為什么內存沒釋放?

1、可能是覆蓋之前的key,導致key過期時間發(fā)生了改變

當一個key在Redis中已經存在了,但是由于一些誤操作使得key過期時間發(fā)生了改變,從而導致這個key在應該過期的時間內并沒有過期,從而造成內存的占用。

2、Redis過期key的處理策略導致內存沒釋放

柚子快報邀請碼778899分享:面試篇:Redis

http://yzkb.51969.com/

推薦鏈接

評論可見,查看隱藏內容

本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19127830.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄