自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Redis高頻面試題總結(jié)

開發(fā) 前端 Redis
通過面試多家大型互聯(lián)網(wǎng)企業(yè),總結(jié)了如下的高頻面試題目,包括:redis 過期鍵的刪除策略;Redus的淘汰策略等等。

通過面試多家大型互聯(lián)網(wǎng)企業(yè),總結(jié)了如下的高頻面試題目:

1、redis 過期鍵的刪除策略?

  • 定時(shí)刪除:在設(shè)置鍵的過期時(shí)間的同時(shí),創(chuàng)建一個(gè)定時(shí)器 timer). 讓定時(shí)器在鍵 的過期時(shí)間來臨時(shí),立即執(zhí)行對(duì)鍵的刪除操作。
  • 惰性刪除:放任鍵過期不管,但是每次從鍵空間中獲取鍵時(shí),都檢查取得的鍵是 否過期,如果過期的話,就刪除該鍵;如果沒有過期,就返回該鍵。
  • 定期刪除:每隔一段時(shí)間程序就對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次檢查,刪除里面的過期鍵

2、Redus的淘汰策略

redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時(shí)候,就會(huì)施行 數(shù)據(jù)淘汰策略 。redis 提供6種數(shù)據(jù)淘汰策略:

通過淘汰策略也能保證Redis中緩存的都是熱點(diǎn)數(shù)據(jù)。

一個(gè)客戶端運(yùn)行了新的命令,添加了新的數(shù)據(jù)。Redi 檢查內(nèi)存使用情況,如果大于 maxmemory 的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收。

注意這里的 6 種機(jī)制,volatile 和 allkeys 規(guī)定了是對(duì)已設(shè)置過期時(shí)間的數(shù)據(jù)集淘汰數(shù)據(jù)還是從全部數(shù)據(jù)集淘汰數(shù)據(jù),后面的 lru、ttl 以及 random 是三種不同的淘汰策略,再加上一種 no-enviction 永不回收的策略。

使用策略規(guī)則:如果數(shù)據(jù)呈現(xiàn)冪律分布,也就是一部分?jǐn)?shù)據(jù)訪問頻率高,一部分?jǐn)?shù)據(jù)訪問頻率低,則使用 allkeys-lru;如果數(shù)據(jù)呈現(xiàn)平等分布,也就是所有的數(shù)據(jù)訪問頻率都相同,則使用

  1. allkeys-random 

3、Redis分布式鎖的實(shí)現(xiàn)

Redis的分布式緩存特性使其成為了分布式鎖的一種基礎(chǔ)實(shí)現(xiàn)。通過Redis中是否存在某個(gè)鎖ID,則可以判斷是否上鎖。為了保證判斷鎖是否存在的原子性,保證只有一個(gè)線程獲取同一把鎖,Redis有 SETNX (即SET if Note Exists)和 GETSET (先寫新值,返回舊值,原子性操作,可以用于分辨是不是首次操作)操作。

(1)關(guān)于setnx:

  • 將 key 的值設(shè)為 value ,當(dāng)且僅當(dāng) key 不存在,返回值為1。
  • 若給定的 key 已經(jīng)存在,則setnx不做任何動(dòng)作,返回值為0。

(2)關(guān)于set:一般操作

  • ex seconds - seconds:設(shè)置失效時(shí)長(zhǎng),單位秒
  • px - milliseconds:設(shè)置失效時(shí)長(zhǎng),單位毫秒
  • nx - key不存在時(shí)設(shè)置value,成功返回OK,失敗返回(nil)
  • xx - key存在時(shí)設(shè)置value,成功返回OK,失敗返回(nil)

為了防止主機(jī)宕機(jī)或網(wǎng)絡(luò)斷開之后的死鎖,Redis沒有ZK那種天然的實(shí)現(xiàn)方式,只能依賴設(shè)置超時(shí)時(shí)間來規(guī)避。所以如果使用setnx來實(shí)現(xiàn)分布式鎖,則實(shí)現(xiàn)步驟如下:

  • 先拿 setnx 來爭(zhēng)搶鎖,搶到之后,再用 expire 給鎖加一個(gè)過期時(shí)間防止鎖忘記了釋放。
  • 如果在 setnx 之后,執(zhí)行 expire 之前進(jìn)程意外 crash 或重啟維護(hù), 那么就需要把 setnx 和 expire 合成一條指令來用。

Redis 的 setnx 命令是當(dāng) key 不存在時(shí)設(shè)置 key ,但 setnx 不能同時(shí)完成 expire 設(shè)置失效時(shí)長(zhǎng),不能保證 setnx 和 expire 的原子性。我們可以使用 set 命令完成 setnx 和 expire 的操作,并且這種操作是原子操作。舉個(gè)例子如下:

 

  1. 案例:設(shè)置name=p7+,失效時(shí)長(zhǎng)100s,不存在時(shí)設(shè)置 
  2. 1.1.1.1:6379> set name p7+ ex 100 nx 
  3. OK 
  4. 1.1.1.1:6379> get name 
  5. "p7+" 
  6. 1.1.1.1:6379> ttl name 
  7. (integer) 94 

從上面可以看出,多個(gè)命令放在同一個(gè) redis 連接中并且 redis 是單線程的,因此上面的操作可以看成 setnx 和 expire 的結(jié)合體,是原子性的。

4、Redis的Reactor模式

Redis基于Reactor模式開發(fā)了網(wǎng)絡(luò)事件處理器,這個(gè)處理器被稱為文件事件處理器。它的組成結(jié)構(gòu)為4部分:多個(gè)套接字、IO多路復(fù)用程序、文件事件分派器、事件處理器。

因?yàn)槲募录峙善麝?duì)列的消費(fèi)是單線程的,所以Redis才叫單線程模型。

5、redis支持事務(wù)回滾嗎?

“ 不支持回滾動(dòng)作,redis是支持簡(jiǎn)單事務(wù)模式,只能discard,不能rollback ”

Redis在執(zhí)行事務(wù)命令的時(shí)候,在命令入隊(duì)的時(shí)候, Redis 就會(huì)檢測(cè)事務(wù)的命令是否正確,如果不正確則會(huì)產(chǎn)生錯(cuò)誤。無論之前和之后的命令都會(huì)被事務(wù)所回滾,就變?yōu)槭裁炊紱]有執(zhí)行。

當(dāng)命令格式正確,而因?yàn)椴僮鲾?shù)據(jù)結(jié)構(gòu)引起的錯(cuò)誤 ,則該命令執(zhí)行出現(xiàn)錯(cuò)誤,而其之前和之后的命令都會(huì)被正常執(zhí)行。這點(diǎn)和數(shù)據(jù)庫(kù)很不一樣,這是需注意的地方。

對(duì)于一些重要的操作,我們必須通過程序去檢測(cè)數(shù)據(jù)的正確性,以保證 Redis 事務(wù)的正確執(zhí)行,避免出現(xiàn)數(shù)據(jù)不一致的情況。 Redis 之所以保持這樣簡(jiǎn)易的事務(wù),完全是為了保證移動(dòng)互聯(lián)網(wǎng)的核心問題一性能。

6、Redis的事務(wù)機(jī)制及CAS

watch指令在redis事物中提供了CAS的行為。為了檢測(cè)被watch的keys在是否有多個(gè)clients同時(shí)改變引起沖突,這些keys將會(huì)被監(jiān)控。如果至少有一個(gè)被監(jiān)控的key在執(zhí)行exec命令前被修改,整個(gè)事物將會(huì)回滾,不執(zhí)行任何動(dòng)作,從而保證原子性操作,并且執(zhí)行exec會(huì)得到null的回復(fù)。

7、Redis和Memcached的區(qū)別

Redis的特性:

  • 速度快,因?yàn)閿?shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1)
  • 支持豐富數(shù)據(jù)類型,支持字符串、鏈表、哈希、集合和有序集合
  • 支持事務(wù),操作都是原子性,所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行,要么全部不執(zhí)行
  • 豐富的特性:可用于緩存,消息,按key設(shè)置過期時(shí)間,過期后將會(huì)自動(dòng)刪除

與Memcached的區(qū)別在于:

  • 存儲(chǔ)方式 Memecache把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會(huì)掛掉,數(shù)據(jù)不能超過內(nèi)存大小。Redis有部分存在硬盤上,這樣能保證數(shù)據(jù)的持久性。
  • 數(shù)據(jù)支持類型 Memcache對(duì)數(shù)據(jù)類型支持相對(duì)簡(jiǎn)單。Redis有復(fù)雜的數(shù)據(jù)類型。
  • 使用底層模型不同 它們之間底層實(shí)現(xiàn)方式 以及與客戶端之間通信的應(yīng)用協(xié)議不一樣。

Redis直接自己構(gòu)建了VM(Virtual Memory)機(jī)制 ,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話(例如java調(diào)用自己的API),會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求。

8、緩存穿透、緩存擊穿和緩存雪崩

(1)緩存穿透

查詢不存在的數(shù)據(jù),緩存中沒有數(shù)據(jù),數(shù)據(jù)庫(kù)也沒有數(shù)據(jù)。因此所有的請(qǐng)求都訪問到了數(shù)據(jù)庫(kù),給數(shù)據(jù)庫(kù)造成了壓力。解決方法如下:

采用布隆過濾器,將所有可能存在的數(shù)據(jù),哈希到一個(gè)很大的 bitmap 中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被 bitmap 攔截調(diào),從而避免了對(duì)數(shù)據(jù)庫(kù)的查詢壓力。

如果查詢的數(shù)據(jù)為空,那么直接將空數(shù)據(jù)也緩存起來并設(shè)置較短的過期時(shí)間。這樣下次訪問的時(shí)候,就直接返回空值。

(2)緩存擊穿

緩存擊穿是指緩存過期之后,瞬時(shí)間并發(fā)客戶端特別多查詢同一條數(shù)據(jù)的情況下,導(dǎo)致數(shù)據(jù)庫(kù)壓力過大。業(yè)界比較常用的做法,是使用mutex。簡(jiǎn)單地來說,就是在緩存失效的時(shí)候(判斷拿出來的值為空),不是立即去load db,

而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者M(jìn)emcache的ADD)去set一個(gè)mutex key,當(dāng)操作返回成功時(shí),

再進(jìn)行l(wèi)oad db的操作并回設(shè)緩存;否則,就重試整個(gè)get緩存的方法。類似下面的代碼:

 

  1. public String get(String key) { 
  2.     String value = redis.get(key); 
  3.     if (value == null) { // 代表緩存值過期 
  4.         // 設(shè)置3min的超時(shí),防止del操作失敗的時(shí)候,下次緩存過期一直不能load db 
  5.         if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { // 代表設(shè)置成功 
  6.             value = db.get(key); 
  7.             redis.set(key, value, expire_secs); 
  8.             redis.del(key_mutex); 
  9.         } 
  10.         // 這個(gè)時(shí)候代表同時(shí)候的其他線程已經(jīng)load db并回設(shè)到緩存了, 
  11.         // 這時(shí)候重試獲取緩存值即可 
  12.         else { 
  13.             sleep(50); 
  14.             get(key); // 重試 
  15.         } 
  16.     } else { 
  17.         return value; 
  18.     } 

(3)緩存雪崩

雪崩就是指緩存中大批量熱點(diǎn)數(shù)據(jù)過期后系統(tǒng)涌入大量查詢請(qǐng)求,因?yàn)榇蟛糠謹(jǐn)?shù)據(jù)在Redis層已經(jīng)失效,請(qǐng)求滲透到數(shù)據(jù)庫(kù)層,大批量請(qǐng)求猶如洪水一般涌入,引起數(shù)據(jù)庫(kù)壓力造成查詢堵塞甚至宕機(jī)。

解決辦法:

將緩存失效時(shí)間分散開,比如每個(gè)key的過期時(shí)間是隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過期現(xiàn)象發(fā)生,這樣不會(huì)出現(xiàn)同一時(shí)間全部請(qǐng)求都落在數(shù)據(jù)庫(kù)層,如果緩存數(shù)據(jù)庫(kù)是分布式部署,將熱點(diǎn)數(shù)據(jù)均勻分布在不同Redis和數(shù)據(jù)庫(kù)中,有效分擔(dān)壓力,別一個(gè)人扛。

讓Redis數(shù)據(jù)永不過期(如果業(yè)務(wù)準(zhǔn)許)。

9、Redis數(shù)據(jù)傾斜

1、存在bigkey:業(yè)務(wù)層避免創(chuàng)建bigkey,把集合類型的bigkey拆分成多個(gè)小集合,分散保存bigkey 保存了大量集合元素(集合類型),會(huì)導(dǎo)致這個(gè)實(shí)例的數(shù)據(jù)量增加,內(nèi)存資源消耗也相應(yīng)增加。bigkey 的操作一般都會(huì)造成實(shí)例 IO 線程阻塞,如果 bigkey 的訪問量比較大,就會(huì)影響到這個(gè)實(shí)例上的其它請(qǐng)求被處理的速度。

2、slot手工分配不均勻:避免把較多的slot分配到一個(gè)實(shí)例上,進(jìn)行槽的遷移

3、存在熱點(diǎn)數(shù)據(jù):采用帶有不同key前綴的多副本方法。 我們把熱點(diǎn)數(shù)據(jù)復(fù)制多份,在每一個(gè)數(shù)據(jù)副本的 key 中增加一個(gè)隨機(jī)前綴,讓它和其它副本數(shù)據(jù)不會(huì)被映射到同一個(gè) Slot 中。這樣一來, 熱點(diǎn)數(shù)據(jù)既有多個(gè)副本可以同時(shí)服務(wù)請(qǐng)求,同時(shí),這些副本數(shù)據(jù)的 key 又不一樣,會(huì)被映射到不同的 Slot 中。在給這些 Slot 分配實(shí)例時(shí), 我們也要注意把它們分配到不同的實(shí)例上,那么,熱點(diǎn)數(shù)據(jù)的訪問壓力就被分散到不同的實(shí)例上了。 熱點(diǎn)數(shù)據(jù)多副本方法只能針對(duì)只讀的熱點(diǎn)數(shù)據(jù)。如果熱點(diǎn)數(shù)據(jù)是有讀有寫的話,就不適合采用多副本方法了,因?yàn)橐WC多副本間的數(shù)據(jù)一致性,會(huì)帶來額外的開銷。

10、為什么Redis單線程模型也能效率這么高?

  • 純內(nèi)存操作;
  • 核心是基于非阻塞的IO多路復(fù)用機(jī)制;
  • 底層使用C語(yǔ)言實(shí)現(xiàn),一般來說,C 語(yǔ)言實(shí)現(xiàn)的程序"距離"操作系統(tǒng)更近,執(zhí)行速度相對(duì)會(huì)更快;
  • 單線程同時(shí)也避免了多線程的上下文頻繁切換問題,預(yù)防了多線程可能產(chǎn)生的競(jìng)爭(zhēng)問題。

11、Redis做異步和延時(shí)隊(duì)列?

一般使用 list 結(jié)構(gòu)作為隊(duì)列,rpush 生產(chǎn)消息,lpop 消費(fèi)消息。當(dāng) lpop 沒有消息的時(shí)候,要適當(dāng) sleep 一會(huì)再重試。如果對(duì)方追問可不可以不用 sleep 呢?list 還有個(gè)指令叫 blpop,在沒有消息的時(shí)候,它會(huì)阻塞住直到消息到來。如果對(duì) 方追問能不能生產(chǎn)一次消費(fèi)多次呢?使用 pub/sub 主題訂閱者模式,可以實(shí)現(xiàn) 1:N 的消息隊(duì)列。

使用 zset(有序集合),拿時(shí)間戳作為score,消息內(nèi)容作為 key 調(diào)用 zadd 來生產(chǎn)消息,消費(fèi)者用 zrangebyscore 指令獲取 N 秒之前的數(shù)據(jù)輪詢進(jìn)行處理。

12、Redis的集群策略

(1)Redis主從同步Redis的主從結(jié)構(gòu)一主一從,一主多從或級(jí)聯(lián)結(jié)構(gòu),復(fù)制類型可以根據(jù)是否是全量而分為全量同步和增量同步。

(2)Redis哨兵 在主從復(fù)制實(shí)現(xiàn)之后,如果想對(duì)master進(jìn)行監(jiān)控,Redis提供了一種哨兵機(jī)制,哨兵的含義就是監(jiān)控Redis系統(tǒng)的運(yùn)行狀態(tài),并做相應(yīng)的響應(yīng)。Redis Sentinal 著眼于高可用,在 master 宕機(jī)時(shí)會(huì)自動(dòng)將 slave 提升為master,繼續(xù)提供服務(wù)。

(3)Redis Cluster 著眼于擴(kuò)展性,在單個(gè) redis 內(nèi)存不足時(shí),使用 Cluster 進(jìn)行分片存儲(chǔ)。在redis-cluster架構(gòu)中,redis-master節(jié)點(diǎn)一般用于接收讀寫,而redis-slave節(jié)點(diǎn)則一般只用于備份,其與對(duì)應(yīng)的master擁有相同的slot集合,若某個(gè)redis-master意外失效,則再將其對(duì)應(yīng)的slave進(jìn)行升級(jí)為臨時(shí)redis-master。

13、 Redis 的同步機(jī)制

Redis 可以使用主從同步,從從同步。第一次同步時(shí),主節(jié)點(diǎn)做一次 bgsave,并同時(shí)將后續(xù)修改操作記錄到內(nèi)存 buffer,待完成后將 rdb 文件全量同步到復(fù)制節(jié)點(diǎn),復(fù)制節(jié)點(diǎn)接受完成后將 rdb 鏡像加載到內(nèi)存。加載完成后,再通知主節(jié)點(diǎn)

將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過程。

責(zé)任編輯:未麗燕 來源: 博客園精華區(qū)
相關(guān)推薦

2019-12-26 09:52:33

Redis集群線程

2021-01-22 11:58:30

MySQL數(shù)據(jù)庫(kù)開發(fā)

2021-08-05 05:04:50

熱部署模型字節(jié)

2022-08-22 18:57:29

React前端面試

2019-11-26 10:30:11

CSS前端面試題

2020-08-31 12:20:07

Python面試題代碼

2020-03-03 17:47:07

UDP TCP面試題

2016-03-03 10:07:39

ios內(nèi)存管理面試總結(jié)

2024-04-15 08:34:43

2024-04-28 08:23:18

2021-12-08 11:18:21

Spring Bean面試題生命周期

2022-04-15 09:23:29

Kubernetes面試題

2020-06-04 14:40:40

面試題Vue前端

2009-08-28 09:29:02

2023-11-13 07:37:36

JS面試題線程

2011-03-24 13:27:37

SQL

2009-09-08 17:50:01

2024-07-24 08:38:07

2025-03-11 06:28:21

2021-11-02 10:10:38

面試元素語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)