久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Redis最常被問到問題有哪些

134次閱讀
沒有評論

共計 9667 個字符,預計需要花費 25 分鐘才能閱讀完成。

本文丸趣 TV 小編為大家詳細介紹“Redis 最常被問到問題有哪些”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Redis 最常被問到問題有哪些”文章能幫助大家解決疑惑,下面跟著丸趣 TV 小編的思路慢慢深入,一起來學習新知識吧。

1. 什么是 redis?

Redis 是一個基于內存的高性能 key-value 數據庫。

2.Reids 的特點

Redis 本質上是一個 Key-Value 類型的內存數據庫,很像 memcached,整個數據庫統統加載在內存當中進行操作,定期通過異步操作把數據庫數據 flush 到硬盤上進行保存。因為是純內存操作,Redis 的性能非常出色,每秒可以處理超過 10 萬次讀寫操作,是已知性能最快的 Key-Value DB。

Redis 的出色之處不僅僅是性能,Redis 最大的魅力是支持保存多種數據結構,此外單個 value 的最大限制是 1GB,不像 memcached 只能保存 1MB 的數據,因此 Redis 可以用來實現很多有用的功能,比方說用他的 List 來做 FIFO 雙向鏈表,實現一個輕量級的高性 能消息隊列服務,用他的 Set 可以做高性能的 tag 系統等等。另外 Redis 也可以對存入的 Key-Value 設置 expire 時間,因此也可以被當作一 個功能加強版的 memcached 來用。

Redis 的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,因此 Redis 適合的場景主要局限在較小數據量的高性能操作和運算上。

3. 使用 redis 有哪些好處?

 (1) 速度快,因為數據存在內存中,類似于 HashMap,HashMap 的優勢就是查找和操作的時間復雜度都是 O(1)

 (2) 支持豐富數據類型,支持 string,list,set,sorted set,hash 

1)String  常用命令:set/get/decr/incr/mget 等;  應用場景:String 是最常用的一種數據類型,普通的 key/value 存儲都可以歸為此類;  實現方式:String 在 redis 內部存儲默認就是一個字符串,被 redisObject 所引用,當遇到 incr、decr 等操作時會轉成數值型進行計算,此時 redisObject 的 encoding 字段為 int。 2)Hash  常用命令:hget/hset/hgetall 等   應用場景:我們要存儲一個用戶信息對象數據,其中包括用戶 ID、用戶姓名、年齡和生日,通過用戶 ID 我們希望獲取該用戶的姓名或者年齡或者生日;  實現方式:Redis 的 Hash 實際是內部存儲的 Value 為一個 HashMap,并提供了直接存取這個 Map 成員的接口。如圖所示,Key 是用戶 ID, value 是一個 Map。這個 Map 的 key 是成員的屬性名,value 是屬性值。這樣對數據的修改和存取都可以直接通過其內部 Map 的 Key(Redis 里稱內部 Map 的 key 為 field),  也就是通過  key(用戶 ID) + field(屬性標簽)  就可以操作對應屬性數據。當前 HashMap 的實現有兩種方式:當 HashMap 的成員比較少時 Redis 為了節省內存會采用類似一維數組的方式來緊湊存儲,而不會采用真正的 HashMap 結構,這時對應的 value 的 redisObject 的 encoding 為 zipmap,當成員數量增大時會自動轉成真正的 HashMap, 此時 encoding 為 ht。 hash 3)List  常用命令:lpush/rpush/lpop/rpop/lrange 等;  應用場景:Redis list 的應用場景非常多,也是 Redis 最重要的數據結構之一,比如 twitter 的關注列表,粉絲列表等都可以用 Redis 的 list 結構來實現;  實現方式:Redis list 的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis 內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。 4)Set  常用命令:sadd/spop/smembers/sunion 等;  應用場景:Redis set 對外提供的功能與 list 類似是一個列表的功能,特殊之處在于 set 是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據時,set 是一個很好的選擇,并且 set 提供了判斷某個成員是否在一個 set 集合內的重要接口,這個也是 list 所不能提供的;  實現方式:set  的內部實現是一個  value 永遠為 null 的 HashMap,實際就是通過計算 hash 的方式來快速排重的,這也是 set 能提供判斷一個成員是否在集合內的原因。 5)Sorted Set  常用命令:zadd/zrange/zrem/zcard 等;  應用場景:Redis sorted set 的使用場景與 set 類似,區別是 set 不是自動有序的,而 sorted set 可以通過用戶額外提供一個優先級 (score) 的參數來為成員排序,并且是插入有序的,即自動排序。當你需要一個有序的并且不重復的集合列表,那么可以選擇 sorted set 數據結構,比如 twitter  的 public timeline 可以以發表時間作為 score 來存儲,這樣獲取時就是自動按時間排好序的。  實現方式:Redis sorted set 的內部使用 HashMap 和跳躍表 (SkipList) 來保證數據的存儲和有序,HashMap 里放的是成員到 score 的映射,而跳躍表里存放的是所有的成員,排序依據是 HashMap 里存的 score, 使用跳躍表的結構可以獲得比較高的查找效率,并且在實現上比較簡單。

 (3) 支持事務,操作都是原子性,所謂的原子性就是對數據的更改要么全部執行,要么全部不執行

 (4) 豐富的特性:可用于緩存,消息,按 key 設置過期時間,過期后將會自動刪除

4.redis 相比 memcached 有哪些優勢?

(1) memcached 所有的值均是簡單的字符串,redis 作為其替代者,支持更為豐富的數據類型

(2) redis 的速度比 memcached 快很多 (3) redis 可以持久化其數據

5.Memcache 與 Redis 的區別都有哪些? 

(1)、存儲方式 Memecache 把數據全部存在內存之中,斷電后會掛掉,數據不能超過內存大小。Redis 有部份存在硬盤上,這樣能保證數據的持久性。

(2)、數據支持類型 Memcache 對數據類型支持相對簡單。Redis 有復雜的數據類型。

(3)、使用底層模型不同 它們之間底層實現方式 以及與客戶端之間通信的應用協議不一樣。Redis 直接自己構建了 VM 機制,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求。

6.redis 適用于的場景?

Redis 最適合所有數據 in-momory 的場景,如:

(1)、會話緩存(Session Cache)

最常用的一種使用 Redis 的情景是會話緩存(session cache)。用 Redis 緩存會話比其他存儲(如 Memcached)的優勢在于:Redis 提供持久化

(2)、全頁緩存(FPC)

除基本的會話 token 之外,Redis 還提供很簡便的 FPC 平臺。回到一致性問題,即使重啟了 Redis 實例,因為有磁盤的持久化,用戶也不會看到頁面加載速度的下降,這是一個極大改進,類似 PHP 本地 FPC。

(3)、隊列

Reids 在內存存儲引擎領域的一大優點是提供 list 和 set 操作,這使得 Redis 能作為一個很好的消息隊列平臺來使用。Redis 作為隊列使用的操作,就類似于本地程序語言(如 Python)對 list 的 push/pop 操作。

如果你快速的在 Google 中搜索“Redis queues”,你馬上就能找到大量的開源項目,這些項目的目的就是利用 Redis 創建非常好的后端工具,以滿足各種隊列需求。例如,Celery 有一個后臺就是使用 Redis 作為 broker,你可以從這里去查看。

(4),排行榜 / 計數器

Redis 在內存中對數字進行遞增或遞減的操作實現的非常好。集合(Set)和有序集合(Sorted Set)也使得我們在執行這些操作的時候變的非常簡單,Redis 只是正好提供了這兩種數據結構。所以,我們要從排序集合中獲取到排名最靠前的 10 個用戶 ndash; 我們稱之為“user_scores”,我們只需要像下面一樣執行即可:

當然,這是假定你是根據你用戶的分數做遞增的排序。如果你想返回用戶及用戶的分數,你需要這樣執行:

ZRANGE user_scores 0 10 WITHSCORES

Agora Games 就是一個很好的例子,用 Ruby 實現的,它的排行榜就是使用 Redis 來存儲數據的,你可以在這里看到。

(5)、發布 / 訂閱

最后(但肯定不是最不重要的)是 Redis 的發布 / 訂閱功能。發布 / 訂閱的使用場景確實非常多。

7、redis 的緩存失效策略和主鍵失效機制

作為緩存系統都要定期清理無效數據,就需要一個主鍵失效和淘汰策略.

在 Redis 當中,有生存期的 key 被稱為 volatile。在創建緩存時,要為給定的 key 設置生存期,當 key 過期的時候(生存期為 0),它可能會被刪除。

1、影響生存時間的一些操作

生存時間可以通過使用 DEL 命令來刪除整個 key 來移除,或者被 SET 和 GETSET 命令覆蓋原來的數據,也就是說,修改 key 對應的 value 和使用另外相同的 key 和 value 來覆蓋以后,當前數據的生存時間不同。

比如說,對一個 key 執行 INCR 命令,對一個列表進行 LPUSH 命令,或者對一個哈希表執行 HSET 命令,這類操作都不會修改 key 本身的生存時間。另一方面,如果使用 RENAME 對一個 key 進行改名,那么改名后的 key 的生存時間和改名前一樣。

RENAME 命令的另一種可能是,嘗試將一個帶生存時間的 key 改名成另一個帶生存時間的 another_key,這時舊的 another_key (以及它的生存時間)會被刪除,然后舊的 key 會改名為 another_key,因此,新的 another_key 的生存時間也和原本的 key 一樣。使用 PERSIST 命令可以在不刪除 key 的情況下,移除 key 的生存時間,讓 key 重新成為一個 persistent key。

2、如何更新生存時間

可以對一個已經帶有生存時間的 key 執行 EXPIRE 命令,新指定的生存時間會取代舊的生存時間。過期時間的精度已經被控制在 1ms 之內,主鍵失效的時間復雜度是 O(1),

EXPIRE 和 TTL 命令搭配使用,TTL 可以查看 key 的當前生存時間。設置成功返回 1;當 key 不存在或者不能為 key 設置生存時間時,返回 0。

最大緩存配置

在 redis 中,允許用戶設置最大使用內存大小

server.maxmemory

默認為 0,沒有指定最大緩存,如果有新的數據添加,超過最大內存,則會使 redis 崩潰,所以一定要設置。redis 內存數據集大小上升到一定大小的時候,就會實行數據淘汰策略。

redis 提供 6 種數據淘汰策略:

. volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰

. volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰

. volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰

. allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰

. allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰

. no-enviction(驅逐):禁止驅逐數據

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

使用策略規則:

1、如果數據呈現冪律分布,也就是一部分數據訪問頻率高,一部分數據訪問頻率低,則使用 allkeys-lru

2、如果數據呈現平等分布,也就是所有的數據訪問頻率都相同,則使用 allkeys-random

三種數據淘汰策略:

ttl 和 random 比較容易理解,實現也會比較簡單。主要是 Lru 最近最少使用淘汰策略,設計上會對 key 按失效時間排序,然后取最先失效的 key 進行淘汰

8. 為什么 redis 需要把所有數據放到內存中?

Redis 為了達到最快的讀寫速度將數據都讀到內存中,并通過異步的方式將數據寫入磁盤。所以 redis 具有快速和數據持久化的特征。如果不將數據放在內存中,磁盤 I / O 速度為嚴重影響 redis 的性能。在內存越來越便宜的今天,redis 將會越來越受歡迎。

如果設置了最大使用的內存,則數據已有記錄數達到內存限值后不能繼續插入新值。

9.Redis 是單進程單線程的

redis 利用隊列技術將并發訪問變為串行訪問,消除了傳統數據庫串行控制的開銷

10.redis 的并發競爭問題如何解決?

Redis 為單進程單線程模式,采用隊列模式將并發訪問變為串行訪問。Redis 本身沒有鎖的概念,Redis 對于多個客戶端連接并不存在競爭,但是在 Jedis 客戶端對 Redis 進行并發訪問時會發生連接超時、數據轉換錯誤、阻塞、客戶端關閉連接等問題,這些問題均是

由于客戶端連接混亂造成。對此有 2 種解決方法:

1. 客戶端角度,為保證每個客戶端間正常有序與 Redis 進行通信,對連接進行池化,同時對客戶端讀寫 Redis 操作采用內部鎖 synchronized。

2. 服務器角度,利用 setnx 實現鎖。

注:對于第一種,需要應用程序自己處理資源的同步,可以使用的方法比較通俗,可以使用 synchronized 也可以使用 lock;第二種需要用到 Redis 的 setnx 命令,但是需要注意一些問題。

11、redis 常見性能問題和解決方案:

1).Master 寫內存快照,save 命令調度 rdbSave 函數,會阻塞主線程的工作,當快照比較大時對性能影響是非常大的,會間斷性暫停服務,所以 Master 最好不要寫內存快照。

2).Master AOF 持久化,如果不重寫 AOF 文件,這個持久化方式對性能的影響是最小的,但是 AOF 文件會不斷增大,AOF 文件過大會影響 Master 重啟的恢復速度。Master 最好不要做任何持久化工作,包括內存快照和 AOF 日志文件,特別是不要啟用內存快照做持久

化, 如果數據比較關鍵,某個 Slave 開啟 AOF 備份數據,策略為每秒同步一次。

3).Master 調用 BGREWRITEAOF 重寫 AOF 文件,AOF 在重寫的時候會占大量的 CPU 和內存資源,導致服務 load 過高,出現短暫服務暫停現象。

4). Redis 主從復制的性能問題,為了主從復制的速度和連接的穩定性,Slave 和 Master 最好在同一個局域網內。

12.redis 事物的了解 CAS(check-and-set 操作實現樂觀鎖)?

和眾多其它數據庫一樣,Redis 作為 NoSQL 數據庫也同樣提供了事務機制。在 Redis 中,MULTI/EXEC/DISCARD/WATCH 這四個命令是我們實現事務的基石。相信對有關系型數據庫開發經驗的開發者而言這一概念并不陌生,即便如此,我們還是會簡要的列出

Redis 中

事務的實現特征:

1). 在事務中的所有命令都將會被串行化的順序執行,事務執行期間,Redis 不會再為其它客戶端的請求提供任何服務,從而保證了事物中的所有命令被原子的執行。

2). 和關系型數據庫中的事務相比,在 Redis 事務中如果有某一條命令執行失敗,其后的命令仍然會被繼續執行。

3). 我們可以通過 MULTI 命令開啟一個事務,有關系型數據庫開發經驗的人可以將其理解為 BEGIN TRANSACTION 語句。在該語句之后執行的命令都將被視為事務之內的操作,最后我們可以通過執行 EXEC/DISCARD 命令來提交 / 回滾該事務內的所有操作。這兩個 Redis 命令可被視為等同于關系型數據庫中的 COMMIT/ROLLBACK 語句。

4). 在事務開啟之前,如果客戶端與服務器之間出現通訊故障并導致網絡斷開,其后所有待執行的語句都將不會被服務器執行。然而如果網絡中斷事件是發生在客戶端執行 EXEC 命令之后,那么該事務中的所有命令都會被服務器執行。

5). 當使用 Append-Only 模式時,Redis 會通過調用系統函數 write 將該事務內的所有寫操作在本次調用中全部寫入磁盤。然而如果在寫入的過程中出現系統崩潰,如電源故障導致的宕機,那么此時也許只有部分數據被寫入到磁盤,而另外一部分數據卻已經丟失。Redis 服務器會在重新啟動時執行一系列必要的一致性檢測,一旦發現類似問題,就會立即退出并給出相應的錯誤提示。此時,我們就要充分利用 Redis 工具包中提供的 redis-check-aof 工具,該工具可以幫助我們定位到數據不一致的錯誤,并將已經寫入的部分數據進行回滾。修復之后我們就可以再次重新啟動 Redis 服務器了。

13.WATCH 命令和基于 CAS 的樂觀鎖?

在 Redis 的事務中,WATCH 命令可用于提供 CAS(check-and-set)功能。假設我們通過 WATCH 命令在事務執行之前監控了多個 Keys,倘若在 WATCH 之后有任何 Key 的值發生了變化,EXEC 命令執行的事務都將被放棄,同時返回 Null multi-bulk 應答以通知調用者事務

執行失敗。例如,我們再次假設 Redis 中并未提供 incr 命令來完成鍵值的原子性遞增,如果要實現該功能,我們只能自行編寫相應的代碼。其偽碼如下:

val = GET mykey

val = val + 1

SET mykey $val

以上代碼只有在單連接的情況下才可以保證執行結果是正確的,因為如果在同一時刻有多個客戶端在同時執行該段代碼,那么就會出現多線程程序中經常出現的一種錯誤場景 – 競態爭用(race condition)。比如,客戶端 A 和 B 都在同一時刻讀取了 mykey 的原有值,假設該值為 10,此后兩個客戶端又均將該值加一后 set 回 Redis 服務器,這樣就會導致 mykey 的結果為 11,而不是我們認為的 12。為了解決類似的問題,我們需要借助 WATCH 命令的幫助,見如下代碼:

WATCH mykey

val = GET mykey

val = val + 1

MULTI

SET mykey $val

EXEC

和此前代碼不同的是,新代碼在獲取 mykey 的值之前先通過 WATCH 命令監控了該鍵,此后又將 set 命令包圍在事務中,這樣就可以有效的保證每個連接在執行 EXEC 之前,如果當前連接獲取的 mykey 的值被其它連接的客戶端修改,那么當前連接的 EXEC 命令將執行失敗。這樣調用者在判斷返回值后就可以獲悉 val 是否被重新設置成功。

14. 使用過 Redis 分布式鎖么,它是什么回事?

先拿 setnx 來爭搶鎖,搶到之后,再用 expire 給鎖加一個過期時間防止鎖忘記了釋放。

這時候對方會告訴你說你回答得不錯,然后接著問如果在 setnx 之后執行 expire 之前進程意外 crash 或者要重啟維護了,那會怎么樣?

這時候你要給予驚訝的反饋:唉,是喔,這個鎖就永遠得不到釋放了。緊接著你需要抓一抓自己得腦袋,故作思考片刻,好像接下來的結果是你主動思考出來的,然后回答:我記得 set 指令有非常復雜的參數,這個應該是可以同時把 setnx 和 expire 合成一條指令來用的!對方這時會顯露笑容,心里開始默念:摁,這小子還不錯。

15. 假如 Redis 里面有 1 億個 key,其中有 10w 個 key 是以某個固定的已知的前綴開頭的,如果將它們全部找出來?

使用 keys 指令可以掃出指定模式的 key 列表。

對方接著追問:如果這個 redis 正在給線上的業務提供服務,那使用 keys 指令會有什么問題?

這個時候你要回答 redis 關鍵的一個特性:redis 的單線程的。keys 指令會導致線程阻塞一段時間,線上服務會停頓,直到指令執行完畢,服務才能恢復。這個時候可以使用 scan 指令,scan 指令可以無阻塞的提取出指定模式的 key 列表,但是會有一定的重復概率,在客戶端做一次去重就可以了,但是整體所花費的時間會比直接用 keys 指令長。

16. 使用過 Redis 做異步隊列么,你是怎么用的?

一般使用 list 結構作為隊列,rpush 生產消息,lpop 消費消息。當 lpop 沒有消息的時候,要適當 sleep 一會再重試。

如果對方追問可不可以不用 sleep 呢?list 還有個指令叫 blpop,在沒有消息的時候,它會阻塞住直到消息到來。

如果對方追問能不能生產一次消費多次呢?使用 pub/sub 主題訂閱者模式,可以實現 1:N 的消息隊列。

如果對方追問 pub/sub 有什么缺點?在消費者下線的情況下,生產的消息會丟失,得使用專業的消息隊列如 rabbitmq 等。

如果對方追問 redis 如何實現延時隊列?我估計現在你很想把面試官一棒打死如果你手上有一根棒球棍的話,怎么問的這么詳細。但是你很克制,然后神態自若的回答道:使用 sortedset,拿時間戳作為 score,消息內容作為 key 調用 zadd 來生產消息,消費者用 zrangebyscore 指令獲取 N 秒之前的數據輪詢進行處理。

到這里,面試官暗地里已經對你豎起了大拇指。但是他不知道的是此刻你卻豎起了中指,在椅子背后。

17. 如果有大量的 key 需要設置同一時間過期,一般需要注意什么?

如果大量的 key 過期時間設置的過于集中,到過期的那個時間點,redis 可能會出現短暫的卡頓現象。一般需要在時間上加一個隨機值,使得過期時間分散一些。

18.Redis 如何做持久化的?

bgsave 做鏡像全量持久化,aof 做增量持久化。因為 bgsave 會耗費較長時間,不夠實時,在停機的時候會導致大量丟失數據,所以需要 aof 來配合使用。在 redis 實例重啟時,會使用 bgsave 持久化文件重新構建內存,再使用 aof 重放近期的操作指令來實現完整恢復重啟之前的狀態。

對方追問那如果突然機器掉電會怎樣?取決于 aof 日志 sync 屬性的配置,如果不要求性能,在每條寫指令時都 sync 一下磁盤,就不會丟失數據。但是在高性能的要求下每次都 sync 是不現實的,一般都使用定時 sync,比如 1s1 次,這個時候最多就會丟失 1s 的數據。

對方追問 bgsave 的原理是什么?你給出兩個詞匯就可以了,fork 和 cow。fork 是指 redis 通過創建子進程來進行 bgsave 操作,cow 指的是 copy on write,子進程創建后,父子進程共享數據段,父進程繼續提供讀寫服務,寫臟的頁面數據會逐漸和子進程分離開來。

19.Pipeline 有什么好處,為什么要用 pipeline?

可以將多次 IO 往返的時間縮減為一次,前提是 pipeline 執行的指令之間沒有因果相關性。使用 redis-benchmark 進行壓測的時候可以發現影響 redis 的 QPS 峰值的一個重要因素是 pipeline 批次指令的數目。

20.Redis 的同步機制了解么?

Redis 可以使用主從同步,從從同步。第一次同步時,主節點做一次 bgsave,并同時將后續修改操作記錄到內存 buffer,待完成后將 rdb 文件全量同步到復制節點,復制節點接受完成后將 rdb 鏡像加載到內存。加載完成后,再通知主節點將期間修改的操作記錄同步到復制節點進行重放就完成了同步過程。

21. 是否使用過 Redis 集群,集群的原理是什么?

Redis Sentinal 著眼于高可用,在 master 宕機時會自動將 slave 提升為 master,繼續提供服務。

Redis Cluster 著眼于擴展性,在單個 redis 內存不足時,使用 Cluster 進行分片存儲。

讀到這里,這篇“Redis 最常被問到問題有哪些”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-15發表,共計9667字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 新巴尔虎左旗| 武平县| 青田县| 东至县| 绩溪县| 合江县| 乐陵市| 安徽省| 安庆市| 潜山县| 广元市| 清水河县| 临漳县| 无为县| 石泉县| 临沧市| 遂溪县| 安阳县| 玉环县| 泽库县| 赫章县| 肥东县| 电白县| 甘孜| 搜索| 池州市| 朔州市| 大田县| 长治市| 龙胜| 江川县| 荥经县| 永嘉县| 基隆市| 寿光市| 磴口县| 苍梧县| 巴林右旗| 获嘉县| 淳化县| 呈贡县|