日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

10000字超全Redis面试题,再也不怕被问住了!

發布時間:2025/3/12 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10000字超全Redis面试题,再也不怕被问住了! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Redis 在當今的計算機行業,可以說是使用的最為廣泛的內存數據庫,幾乎所有的后端技術面試都會涉及到 Redis 相關的知識,正所謂知己知彼,百戰百勝。小白今天精心整理的超全的 Redis 面試題,希望可以幫助到在路上的你們~

什么是 Redis

Redis 是完全開源免費的,遵守 BSD 協議,是一個高性能的 key-value 數據庫

是一個使用 C 語言開發的數據庫,不過與傳統數據庫不同的是 Redis 的數據是存在內存中的,它是內存數據庫,所以讀寫速度非常快,因此 Redis 被廣泛應用于緩存方向

Redis 除了做緩存之外,也經常用來做分布式鎖,甚至是消息隊列

Redis 還支持事務 、持久化、Lua 腳本、多種集群方案等,可以使用眾多復雜的業務場景

常見的分布式緩存技術

緩存使用的比較多的主要是 Memcached 和 Redis。不過現在使用 Memcached 做緩存的比較少

Memcached 是分布式緩存最開始興起的時候比較常用的方案,后來隨著 Redis 的發展,Redis 逐漸成為了人們的首選

分布式緩存主要解決的是單機緩存的容量受服務器限制并且無法保存通用信息的問題。因為本地緩存只在當前服務里有效,比如如果你部署了兩個相同的服務,他們兩者之間的緩存數據是無法共享的

Memcached 與 Redis 的異同

共同點

  • 都是基于內存的數據庫,一般都用來當作緩存使用

  • 都有過期策略

  • 兩者的性能都非常高

  • 異同點

  • Redis 支持更豐富的數據類型,Memcached 只支持最簡單的 k/v 數據類型,所有的值均是簡單的字符串

  • Redis 支持數據的持久化,而 Memecache 把數據全部存在內存之中,重啟之后數據丟失

  • Redis 有災難恢復機制,因為可以把緩存中的數據持久化到磁盤上

  • Redis 在服務器內存使用完之后,可以將不用的數據放到磁盤上。但 Memcached 在服務器內存使用完之后,就會直接報異常

  • Memcached 沒有原生的集群模式,需要依靠客戶端來實現往集群中分片寫入數據;但 Redis目前是原生支持 cluster 模式的

  • Memcached 是多線程,非阻塞 IO 復用的網絡模型;Redis 使用單線程的多路 IO 復用模型

  • Redis 支持發布訂閱模型、Lua 腳本、事務等功能,而 Memcached 不支持。并且,Redis 支持更多的編程語言

  • Memcached 過期數據的刪除策略只用了惰性刪除,而 Redis 同時使用了惰性刪除與定期刪除

  • Redis 的數據類型

    Redis 支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及 zsetsorted set:有序集合)

    實際中我們最為常用的還是 string 類型,不過還有幾種高級數據類型我們也需要了解掌握:BloomFilter,RedisSearch,Redis-ML,還有更高級的數據類型,BloomFilter,RedisSearch,Redis-ML 如果使用過,那么在面試官眼里都是加分項!

    緩存數據的處理流程

    緩存的簡單處理流程如下:

  • 如果用戶請求的數據命中緩存,就直接返回

  • 緩存中不存在的話,查看數據庫中是否存在

  • 如果數據庫中存在,則更新緩存中的數據

  • 如果數據庫中不存在,則返回空數據

  • 上圖就是一個最為簡易的緩存流程圖,從圖中我們也可以看出在使用緩存時的一系列注意事項,比如當緩存失效時,如何更好的保護數據庫,如何保證數據庫與緩存數據一致等

    Redis 運行模式(單進程還是單線程)

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

    一個字符串能存儲的最大容量

    512 M

    為什么要使用緩存

    高性能

    將高頻訪問的數據放進緩存,保證高頻操作可以快速響應,提高系統響應速度和用戶體驗

    高并發

    一般像 MySQL 這類數據庫的 QPS 大概都在 1w 左右(4 核 8g) ,但是使用 Redis 緩存之后很容易達到 10w+,甚至最高能達到 30w+(redis 集群的話會更高)

    QPS(Query Per Second):服務器每秒可以執行的查詢次數

    所以增加緩存可以大大提高系統的并發能力

    具體說說 Redis 可以做什么

    緩存

    緩存機制幾乎在所有的大型網站都有使用,合理地使用緩存不僅可以加 快數據的訪問速度,而且能夠有效地降低后端數據源的壓力。Redis提供了鍵值過期時間設置,并且也提供了靈活控制最大內存和內存溢出后的淘汰策略。可以這么說,一個合理的緩存設計能夠很好的為一個網站的穩定保駕護航

    排行榜系統

    排行榜系統幾乎存在于所有的網站,例如按照熱度排名的排行榜,按照 發布時間的排行榜,按照各種復雜維度計算出的排行榜,Redis提供了列表和有序集合數據結構,合理地使用這些數據結構可以很方便地構建各種排行榜系統

    計數器應用

    計數器在網站中的作用至關重要,例如視頻網站有播放數、電商網站有 瀏覽數,為了保證數據的實時性,每一次播放和瀏覽都要做加1的操作,如果并發量很大對于傳統關系型數據的性能是一種挑戰。Redis天然支持計數功能而且計數的性能也非常好,可以說是計數器系統的重要選擇

    社交網絡

    贊/踩、粉絲、共同好友/喜好、推送、下拉刷新等是社交網站的必備功能,由于社交網站訪問量通常比較大,而且傳統的關系型數據不太適合保存這種類型的數據,Redis 提供的數據結構可以相對比較容易地實現這些功能

    消息隊列系統

    消息隊列系統可以說是一個大型網站的必備基礎組件,因為其具有業務 解耦、非實時業務削峰等特性。Redis 提供了發布訂閱功能和阻塞隊列的功能,雖然和專業的消息隊列比還不夠足夠強大,但是對于一般的消息隊列功能基本可以滿足

    哪些是 Redis 不可以(不擅長)做的

    我們可以站在數據規模和數據冷熱的角度來進行分析

    站在數據規模的角度看,數據可以分為大規模數據和小規模數據,我們 知道 Redis 的數據是存放在內存中的,雖然現在內存已經足夠便宜,但是如果數據量非常大,例如每天有幾億的用戶行為數據,使用 Redis 來存儲的話,基本上是個無底洞,經濟成本相當的高

    站在數據冷熱的角度看,數據分為熱數據和冷數據,熱數據通常是指需 要頻繁操作的數據,反之為冷數據,例如對于視頻網站來說,視頻基本信息基本上在各個業務線都是經常要操作的數據,而用戶的觀看記錄不一定是經常需要訪問的數據,這里暫且不討論兩者數據規模的差異,單純站在數據冷熱的角度上看,視頻信息屬于熱數據,用戶觀看記錄屬于冷數據。如果將這些冷數據放在 Redis 中,基本上是對于內存的一種浪費,但是對于一些熱數據可以放在 Redis 中加速讀寫,也可以減輕后端存儲的負載,可以說是事半功倍

    Redis 常見數據結構與使用場景

    String

    String 數據結構是簡單的 key-value 類型,也是我們平時使用的最多的數據類型

    常用命令:set,get,strlen,exists,decr,incr,setex 等等

    應用場景:一般常用在需要計數的場景,比如用戶的訪問次數、熱點文章的點贊轉發數量等等

    基本操作

    127.0.0.1:6379> set key value # 設置 key-value 類型的值 OK 127.0.0.1:6379> get key # 根據 key 獲得對應的 value "value" 127.0.0.1:6379> exists key # 判斷某個 key 是否存在 (integer) 1 127.0.0.1:6379> strlen key # 返回 key 所儲存的字符串值的長度 (integer) 5 127.0.0.1:6379> del key # 刪除某個 key 對應的值 (integer) 1 127.0.0.1:6379> get key (nil)Copy to clipboardErrorCopied

    批量設置

    127.0.0.1:6379> mset key1 value1 key2 value2 # 批量設置 key-value 類型的值 OK 127.0.0.1:6379> mget key1 key2 # 批量獲取多個 key 對應的 value 1) "value1" 2) "value2"Copy to clipboardErrorCopied

    計數器設置

    127.0.0.1:6379> set number 1 OK 127.0.0.1:6379> incr number # 將 key 中儲存的數字值增一 (integer) 2 127.0.0.1:6379> get number "2" 127.0.0.1:6379> decr number # 將 key 中儲存的數字值減一 (integer) 1 127.0.0.1:6379> get number "1"Copy to clipboardErrorCopied

    過期設置

    127.0.0.1:6379> expire key 60 # 數據在 60s 后過期 (integer) 1 127.0.0.1:6379> setex key 60 value # 數據在 60s 后過期 (setex:[set] + [ex]pire) OK 127.0.0.1:6379> ttl key # 查看數據還有多久過期 (integer) 56Copy to clipboardErrorCopied

    list

    list 即是鏈表,鏈表是一種非常常見的數據結構,特點是易于數據元素的插入和刪除并且可以靈活調整鏈表長度,但是鏈表的隨機訪問困難

    常用命令:rpush,lpop,lpush,rpop,lrange,llen 等

    應用場景:發布與訂閱或者說消息隊列、慢查詢等

    隊列和棧的實現

    通過 rpush/lpop 實現隊列

    127.0.0.1:6379> rpush myList value1 # 向 list 的頭部(右邊)添加元素 (integer) 1 127.0.0.1:6379> rpush myList value2 value3 # 向 list 的頭部(最右邊)添加多個元素 (integer) 3 127.0.0.1:6379> lpop myList # 將 list 的尾部(最左邊)元素取出 "value1" 127.0.0.1:6379> lrange myList 0 1 # 查看對應下標的 list 列表, 0 為 start,1為 end 1) "value2" 2) "value3" 127.0.0.1:6379> lrange myList 0 -1 # 查看列表中的所有元素,-1表示倒數第一 1) "value2" 2) "value3"Copy to clipboardErrorCopied

    通過 rpush/rpop 實現棧

    127.0.0.1:6379> rpush myList2 value1 value2 value3 (integer) 3 127.0.0.1:6379> rpop myList2 # 將 list的頭部(最右邊)元素取出 "value3"Copy to clipboardErrorCopied

    hash

    hash 類似于 JDK1.8 前的 HashMap,內部實現也差不多(數組 + 鏈表),不過 Redis 的 hash 做了更多優化。另外 hash 是一個 string 類型的 field 和 value 的映射表,特別適合用于存 儲對象,比如我們可以用 hash 數據結構來存儲用戶信息,商品信息等等

    常用命令:hset,hmset,hexists,hget,hgetall,hkeys,hvals 等

    應用場景:系統中對象數據的存儲

    127.0.0.1:6379> hmset userInfoKey name "guide" description "dev" age "24" OK 127.0.0.1:6379> hexists userInfoKey name # 查看 key 對應的 value 中指定的字段是否存在 (integer) 1 127.0.0.1:6379> hget userInfoKey name # 獲取存儲在哈希表中指定字段的值 "guide" 127.0.0.1:6379> hget userInfoKey age "24" 127.0.0.1:6379> hgetall userInfoKey # 獲取在哈希表中指定 key 的所有字段和值 1) "name" 2) "guide" 3) "description" 4) "dev" 5) "age" 6) "24" 127.0.0.1:6379> hkeys userInfoKey # 獲取 key 列表 1) "name" 2) "description" 3) "age" 127.0.0.1:6379> hvals userInfoKey # 獲取 value 列表 1) "guide" 2) "dev" 3) "24" 127.0.0.1:6379> hset userInfoKey name "GuideGeGe" # 修改某個字段對應的值 127.0.0.1:6379> hget userInfoKey name "GuideGeGe"Copy to clipboardErrorCopied

    set

    set 類似于 Java 中的 HashSet,Redis 中的 set 類型是一種無序集合,集合中的元素沒有先后順序。當你需要存儲一個列表數據,又不希望出現重復數據時,set 是一個很好的選擇,并且 set 提供了判斷某個成員是否在一個 set 集合內的重要接口,這個也是 list 所不能提供的。可以基于 set 輕易實現交集、并集、差集的操作。如:可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis 可以非常方便的實現如共同關注、共同粉絲、共同喜好等功能

    常用命令:sadd,spop,smembers,sismember,scard,sinterstore,sunion 等

    應用場景:需要存放的數據不能重復以及需要獲取多個數據源交集和并集等場景

    127.0.0.1:6379> sadd mySet value1 value2 # 添加元素進去 (integer) 2 127.0.0.1:6379> sadd mySet value1 # 不允許有重復元素 (integer) 0 127.0.0.1:6379> smembers mySet # 查看 set 中所有的元素 1) "value1" 2) "value2" 127.0.0.1:6379> scard mySet # 查看 set 的長度 (integer) 2 127.0.0.1:6379> sismember mySet value1 # 檢查某個元素是否存在set 中,只能接收單個元素 (integer) 1 127.0.0.1:6379> sadd mySet2 value2 value3 (integer) 2 127.0.0.1:6379> sinterstore mySet3 mySet mySet2 # 獲取 mySet 和 mySet2 的交集并存放 在 mySet3 中 (integer) 1 127.0.0.1:6379> smembers mySet3 1) "value2"Copy to clipboardErrorCopied

    sorted set

    和 set 相比,sorted set 增加了一個權重參數 score,使得集合中的元素能夠按 score 進行有序排列,還可以通過 score 的范圍來獲取元素的列表

    常用命令:zadd,zcard,zscore,zrange,zrevrange,zrem 等

    應用場景:需要對數據根據某個權重進行排序的場景。比如在直播系統中,實時排行信息包含直播間在線用戶列表,各種禮物排行榜,彈幕消息等信息

    127.0.0.1:6379> zadd myZset 3.0 value1 # 添加元素到 sorted set 中 3.0 為權重 (integer) 1 127.0.0.1:6379> zadd myZset 2.0 value2 1.0 value3 # 一次添加多個元素 (integer) 2 127.0.0.1:6379> zcard myZset # 查看 sorted set 中的元素數量 (integer) 3 127.0.0.1:6379> zscore myZset value1 # 查看某個 value 的權重 "3" 127.0.0.1:6379> zrange myZset 0 -1 # 順序輸出某個范圍區間的元素,0 -1 表示輸出所有元素 1) "value3" 2) "value2" 3) "value1" 127.0.0.1:6379> zrange myZset 0 1 # 順序輸出某個范圍區間的元素,0 為 start 1 為 stop 1) "value3" 2) "value2" 127.0.0.1:6379> zrevrange myZset 0 1 # 逆序輸出某個范圍區間的元素,0 為 start 1 為 stop 1) "value1" 2) "value2"Copy to clipboardErrorCopied

    bitmap

    bitmap 存儲的是連續的二進制數字(0 和 1),通過 bitmap, 只需要一個 bit 位來表示某個元素對應的值或者狀態,key 就是對應元素本身。我們知道 8 個 bit 可以組成一個 byte,所以 bitmap 本身會極大的節省儲存空間

    常用命令:setbit 、 getbit 、 bitcount 、 bitop

    應用場景:適合需要保存狀態信息(比如是否簽到、是否登錄...)并需要進一步對這些信息進行分析的場景。比如用戶簽到情況、活躍用戶情況、用戶行為統計

    # SETBIT 會返回之前位的值(默認是 0)這里會生成 7 個位 127.0.0.1:6379> setbit mykey 7 1 (integer) 0 127.0.0.1:6379> setbit mykey 7 0 (integer) 1 127.0.0.1:6379> getbit mykey 7 (integer) 0 127.0.0.1:6379> setbit mykey 6 1 (integer) 0 127.0.0.1:6379> setbit mykey 8 1 (integer) 0 # 通過 bitcount 統計被被設置為 1 的位的數量。 127.0.0.1:6379> bitcount mykey (integer) 2Copy to clipboardErrorCopied

    Redis 為什么不用多線程以及為什么 Redis6.0 之后又引入了多線程

    使用單線程的原因

  • 單線程編程更容易并且更容易維護

  • Redis 的性能瓶頸不在 CPU ,主要在內存和網絡

  • 多線程就會存在死鎖、線程上下文切換等問題,甚至會影響性能

  • Redis6.0 引入多線程主要是為了提高網絡 IO 讀寫性能,因為這個是 Redis 中的一個性能瓶頸

    雖然 Redis6.0 引入了多線程,但是 Redis 的多線程只是在網絡數據的讀寫這類耗時操作上使用了,執行命令仍然是單線程順序執行

    設置緩存過期的作用

    因為內存是有限的,如果緩存中的所有數據都是一直保存的話,很快就會 Out of memory 了

    Redis 中除了字符串類型有自己獨有設置過期時間的命令 setex 外,其他方法都需要依靠 expire 命令來設置過期時間 。另外 persist 命令可以移除一個鍵的過期時間

    還有一種情況需要設置過期時間,當我們的業務場景就是需要某個數據只在某一時間段內存在,比如我們的短信驗證碼可能只在 1 分鐘內有效,用戶登錄的 token 可能只在 1 天內有效,此時設置過期時間就能比較好的處理,如果使用傳統的數據庫來處理的話,一般都是自己判斷過期,這樣更麻煩并且性能要差很多

    Redis 過期刪除策略

  • 定時刪除:在設置鍵的過期時間的同時,創建一個定時器 time,讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作

  • 惰性刪除:放任鍵過期不管,但是每次從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵;如果沒有過期,就返回該鍵

  • 定期刪除:每隔一段時間程序就對數據庫進行一次檢查,刪除里面的過期鍵。至于要刪除多少過期鍵,以及要檢查多少個數據庫,則由算法決定

  • 更新策略對比

    Redis 內存淘汰機制

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

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

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

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

  • allkeys-lru(least recently used):當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最常用的)

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

  • no-eviction:禁止驅逐數據,也就是說當內存不足以容納新寫入數據時,新寫入操作會報錯

  • 4.0 版本后增加以下兩種:

  • volatile-lfu(least frequently used):從已設置過期時間的數據集(server.db[i].expires)中挑選最不經常使用的數據淘汰

  • allkeys-lfu(least frequently used):當內存不足以容納新寫入數據時,在鍵空間中,移除最不經常使用的 key

  • 使用策略的規則:

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

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

    Redis 持久化

    Redis 的一種持久化方式叫快照(snapshotting,RDB),另一種方式是只追加文件(append-only file, AOF)

    快照(snapshotting)持久化(RDB)

    Redis 可以通過創建快照來獲得存儲在內存里面的數據在某個時間點上的副本。Redis 創建快照之后,可以對快照進行備份,可以將快照復制到其他服務器從而創建具有相同數據的服務器副本(Redis 主從結構,主要用來提高 Redis 性能),還可以將快照留在原地以便重啟服務器的時候使用

    AOF(append-only file)持久化

    與快照持久化相比,AOF 持久化的實時性更好,因此已成為主流的持久化方案,是指所有的命令行記錄以 Redis 命令請求協議的格式完全持久化存儲)保存為 aof 文件

    默認沒有開啟 AOF,可以通過如下命令開啟

    appendonly yesCopy to clipboardErrorCopied

    兩種持久化方案對比:

    Redis 常見的性能問題

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

  • 如果數據比較重要,需要在某個 Slave 開啟 AOF 備份數據,策略設置為每秒同步一次

  • 為了主從復制的速度和連接的穩定性,Master 和 Slave 最好在同一個局域網

  • 盡量避免在壓力很大的主庫上增加從庫

  • 主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1<- Slave2 <- Slave3…這樣的結構方便解決單點故障問題,實現 Slave 對 Master 的替換。如果 Master 掛了,可以立刻啟用 Slave1 做 Master,其他不變

  • Redis 同步機制

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

    Redis 主從同步有新舊兩種方案,具體看下面圖示

    老方案:

    新方案:

    Pipeline 的好處

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

    緩存穿透

    緩存穿透說簡單點就是大量請求的 key 根本不存在于緩存中,導致請求直接到了數據庫上,根本沒有經過緩存這一層。比如某個攻擊者故意制造我們緩存中不存在的 key 發起大量請求,導致大量請求落到數據庫上,使得數據庫由于性能的原因崩潰,導致系統異常

    緩存穿透問題產生

    解決辦法:

  • 緩存無效 key

  • 如果緩存和數據庫都查不到某個 key 的數據就寫一個到 Redis 中去并設置過期時間,可以解決請求的 key 變化不頻繁的情況,如果攻擊者的惡意攻擊,每次構建不同的請求 key,會導致 Redis 中緩存大量無效的 key 。很明顯,這種方案并不能從根本上解決此問題

  • 使用布隆過濾器

  • 布隆過濾器是一個非常神奇的數據結構,通過它我們可以非常方便地判斷一個給定數據是否存在于海量數據中

    具體是這樣做的:把所有可能存在的請求的值都存放在布隆過濾器中,當用戶請求過來,先判斷用戶發來的請求的值是否存在于布隆過濾器中。不存在的話,直接返回請求參數錯誤信息給客戶端,存在的話才會走下面的流程

    緩存雪崩

    緩存雪崩描述的就是這樣一個簡單的場景:緩存在同一時間大面積的失效,后面的請求都直接落到了數據庫上,造成數據庫短時間內承受大量請求

    還有一種緩存雪崩的場景是:有一些被大量訪問數據(熱點緩存)在某一時刻大面積失效,導致對應的請求直接落到了數據庫上

    以上兩種常見,就好比雪崩一樣,摧枯拉朽之勢,數據庫的壓力可想而知,可能直接就被這么多請求弄宕機了

    解決辦法

    針對 Redis 服務不可用的情況:

  • 采用 Redis 集群,避免單機出現問題整個緩存服務都沒辦法使用

  • 限流,避免同時處理大量的請求

  • 針對熱點緩存失效的情況:

  • 設置不同的失效時間比如隨機設置緩存的失效時間

  • 緩存永不失效

  • 緩存擊穿

    如果緩存中的某個熱點數據過期了,此時大量的請求訪問了該熱點數據,就無法從緩存中讀取,直接訪問數據庫,數據庫很容易就被高并發的請求沖垮,這就是緩存擊穿的問題

    擊穿其實可以看做是雪崩的一個子集,解決方法一般有兩種,設置熱點數據永不過期和設置互斥鎖

    所謂的互斥鎖,就是保證同一時間只有一個業務線程更新緩存,對于沒有獲取互斥鎖的請求,要么等待鎖釋放后重新讀取緩存,要么就返回空值或者默認值

    如何保證緩存和數據庫的數據一致性

    其實這是一個非常龐大且復雜的問題,根本不是一兩句話能夠說清楚的,如果要完全規避一致性問題,那么整個系統也會變得非常復雜

    一般來說可以進行如下處理:更新 DB,然后刪除 cache

    當然此時有可能遇到更新 DB 成功,但是刪除 cache 失敗的情況,處理辦法大致有兩種:

  • 緩存失效時間變短(不推薦,治標不治本) :我們讓緩存數據的過期時間變短,這樣的話緩存就會從數據庫中加載數據。另外,這種解決辦法對于先操作緩存后操作數據庫的場景不適用

  • 增加 cache 更新重試機制(常用):如果 cache 服務當前不可用導致緩存刪除失敗的話,我們就隔一段時間進行重試,重試次數可以自己定。如果多次重試還是失敗的話,我們可以把當前更新失敗的 key 存入隊列中,等緩存服務可用之后,再將緩存中對應的 key 刪除即可

  • 簡單介紹 Redis 事物

    Redis 事務可以一次執行多個命令,并且帶有以下三個重要的保證:

    • 批量操作在發送 EXEC 命令前被放入隊列緩存

    • 收到 EXEC 命令后進入事務執行,事務中任意命令執行失敗,其余的命令依然被執行

    • 在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中

    一個事務從開始到執行會經歷以下三個階段:

    • 開始事務

    • 命令入隊

    • 執行事務

    命令:

    • DISCARD 取消事務,放棄執行事務塊內的所有命令

    • EXEC 執行所有事務塊內的命令

    • MULTI 標記一個事務塊的開始

    • UNWATCH 取消 WATCH 命令對所有 key 的監視

    • WATCH key [key ...] 監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷

    Redis 集群

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

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

    集群之間是異步復制的,最大節點個數為16384個,Redis 集群目前無法做數據庫選擇,默認在 0 數據庫

    為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有 N-1 個復制品

    Redis 并不能保證數據的強一致性,這意味著在實際中集群在特定的條件下可能會丟失寫操作

    Redis 內存優化

    盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數少)使用的內存非常小,所以你應該盡可能的將你的數據模型抽象到一個散列表里面。比如你的 web 系統中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設置單獨的 key,而是應該把這個用戶的所有信息存儲到一張散列表里面

    一個 Redis 實例最多能存放多少的 keys?各數據類型最多能存放多少元素

    理論上 Redis 可以處理多達 232 的 keys,并且在實際中進行了測試,每個實例至少存放了 2 億 5 千萬的 keys。任何 list、set、和 sorted set 都可以放 232 個元素。換句話說,Redis 的存儲極限是系統中的可用內存值

    如何保證 Redis 中的20W數據都是數據庫中200W數據的熱點數據

    正確設置內存淘汰策略,當 Redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略,從而剩下的數據就是熱點數據

    如何將10W個以某個固定前綴開頭的key全部找出

    使用 keys 指令可以掃出指定模式的 key 列表,但是,keys 指令會導致線程阻塞一段時間,此時整個 Redis 系統不再能接受其他指令

    這個時候可以使用 scan 指令,scan 指令可以無阻塞的提取出指定模式的 key 列表,但是會有一定的重復概率,在客戶端做一次去重就可以了,但是整體所花費的時間會比直接用 keys 指令長,但是安全性更高!

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

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

    Redis 分布式鎖

    通過 SETNX 來爭搶鎖,再用 EXPIRE 給鎖加一個過期時間,當然為了保證 SETNX 和 EXPIRE 原子性執行,在 Redis 2.6.12 之后,Redis 擴展了 SET 命令的參數,用這一條命令就可以了:

    127.0.0.1:6379> SET lock 1 EX 10 NX OK

    好了,這就是今天的內容,如果你覺得對你有所幫助,就點贊+在看支持一下吧~

    往期精彩回顧適合初學者入門人工智能的路線及資料下載中國大學慕課《機器學習》(黃海廣主講)機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載本站qq群955171419,加入微信群請掃碼:

    總結

    以上是生活随笔為你收集整理的10000字超全Redis面试题,再也不怕被问住了!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。