
8月準備Java面試Redis這一塊是繞不開的高頻考點。無論是校招還是社招Redis 都是面試官最喜歡深挖的方向它不像 MySQL 那樣以背 SQL 為主而是可以通過數據結構、緩存設計、分布式鎖、集群方案層層遞進地考察候選人的實戰能力。網上關于 Redis 面試題的資料很零散不少文章只給結論不給原理看完記住結論面試官多問一句“為什么”就容易露餡。這篇文章會把 Redis 面試中最核心的知識點整理成一套完整的復習體系按照“概念-數據結構-持久化-緩存問題-分布式鎖-集群-排錯-復習路線”的順序展開。每部分都會給出面試中高頻的問題、標準的回答思路、容易踩的坑以及配套的命令和代碼示例。不管你是剛開始準備面試還是已經進入沖刺階段都可以直接對照這篇文章查漏補缺。先把這份內容存下面試前翻一遍確實能少走很多彎路。1. 先搞清楚 Redis 在面試中到底考什么1.1 Redis 是什么為什么面試必考RedisRemote Dictionary Server是一個基于內存的鍵值型 NoSQL 數據庫。它的核心特點是所有數據都存儲在內存中所以讀寫速度非常快官方給出的基準測試中單實例 QPS 可以達到 10 萬級別。同時它支持持久化、過期策略、發布訂閱、事務、Lua 腳本、分布式鎖、集群擴展等豐富的功能所以在互聯網項目中Redis 主要用于緩存、會話共享、排行榜、分布式鎖、消息隊列等場景。面試中考察 Redis本質上是從三個維度進行面試者是否掌握 Redis 的數據模型和常用命令。面試者是否理解 Redis 的底層機制比如持久化、淘汰策略、線程模型。面試者是否具備在真實項目中解決緩存問題、設計分布式方案的能力。這三個維度由淺入深正好對應面試官追問的節奏。如果只是背題不深入很容易在追問環節被識別出來。1.2 Redis 和 MySQL 有什么區別這是面試開場高頻題。標準的回答思路是MySQL 是關系型數據庫數據存儲在磁盤上支持復雜的 SQL 查詢、事務 ACID、表關聯。Redis 是基于內存的鍵值存儲讀寫速度快但一般不作為唯一數據源而是作為緩存層加速訪問。Redis 支持的數據類型更豐富如 String、Hash、List、Set、ZSet每種類型都有自己的適用場景。MySQL 的數據一致性由事務保證Redis 在持久化上存在丟數據的可能取決于持久化策略所以兩者一般是配合使用?;卮饡r要強調“Redis 不是用來替代 MySQL 的而是為了提升系統的讀取性能”。如果面試官問“為什么不直接用 Redis 存所有數據”可以從成本、內存容量、事務能力、持久化能力等方面回答。1.3 Redis 為什么快這個問題基本必問回答要點可以歸納為四點純內存操作。數據放在內存中讀寫不涉及磁盤 IO。單線程模型。Redis 網絡請求處理使用單線程避免了多線程上下文切換和鎖競爭的開銷。注意Redis 6.0 之后引入了多線程 IO但核心命令執行仍然是單線程的。IO 多路復用。Redis 基于 epoll 實現 IO 多路復用可以在一個線程里處理多個連接的讀寫事件。高效的數據結構。Redis 底層使用 SDS、跳表、壓縮列表、哈希表等高效結構在不同數據量和場景下自動選擇最優編碼。面試官可能會追問“單線程為什么還這么快”核心原因就是 CPU 不是瓶頸內存和網絡的 IO 才是瓶頸而單線程避免了鎖和上下文切換。2. Redis 核心數據結構與常見面試問題2.1 String 字符串String 是 Redis 最基礎的數據類型value 最大能存儲 512MB。底層實現是 SDSSimple Dynamic String相比 C 字符串SDS 可以 O(1) 獲取長度、避免緩沖區溢出、減少內存重分配次數。常用命令SET key value GET key INCR key DECR key EXPIRE key seconds SETEX key seconds valueString 的典型應用場景緩存用戶信息、配置數據。計數器如點贊數、訪問量。分布式 ID 生成利用 INCR 命令生成遞增序列。分布式鎖的SET key value NX EX也是基于 String 實現的。面試題舉例“String 的底層實現是什么和傳統 C 字符串有什么不同”回答時把 SDS 的動態擴容、二進制安全、獲取長度 O(1) 這三個特點說出來即可。2.2 Hash 哈希Hash 類型是一個 string 類型的 field 和 value 的映射表適合存儲對象數據。比如一個用戶對象包含 id、name、age如果用 String 存儲需要序列化整個對象更新某個字段要重新寫入整個對象用 Hash 則可以直接更新某個字段。常用命令HSET user:1001 name zhangsan HGET user:1001 name HGETALL user:1001 HDEL user:1001 name HINCRBY user:1001 age 1Hash 底層在數據量小的時候使用壓縮列表ziplist數據量大時轉為哈希表hashtable。因為 Redis 3.2 之后引入了 listpack不同版本的編碼細節略有差異但面試中掌握“小數據量壓縮存儲、大數據量哈希表”這個思路就夠了。面試題舉例“Hash 和 String 都存對象怎么選”一般推薦對象字段頻繁修改、只需要部分字段時用 Hash對象整體讀取、轉發給前端時用 String JSON 更省內存且直觀。2.3 List 列表List 是簡單的字符串列表按照插入順序排序可以從頭部或尾部添加元素。底層在元素少時使用壓縮列表元素多時轉為雙向鏈表quicklist 是 Redis 3.2 之后引入的混合結構。常用命令LPUSH key value [value ...] RPUSH key value [value ...] LPOP key RPOP key LRANGE key start stop LLEN key典型應用場景消息隊列LPUSH BRPOP 實現簡單的生產消費模型。最新動態列表用 LPUSH 把新數據放到頭部用 LRANGE 分頁查詢。時間線列表關注的人發布動態后推送到自己的 List 中。面試題舉例“List 和 Stream 做消息隊列有什么區別”List 結構簡單但無法支持消費組、消息確認等特性Redis Stream5.0 引入支持消費者組、消息持久化、ACK 確認更適合可靠性要求更高的場景。2.4 Set 集合Set 是無序、不可重復的字符串集合。集合操作支持交集、并集、差集這是它在業務中最大的價值。常用命令SADD key member [member ...] SMEMBERS key SREM key member SISMEMBER key member SINTER key1 key2 # 交集 SUNION key1 key2 # 并集 SDIFF key1 key2 # 差集典型應用場景抽獎去重用戶參與抽獎SADD 時自動去重。共同關注用 SINTER 獲取兩個用戶的共同關注列表。標簽系統給文章打標簽用 SMEMBERS 查詢標簽用 SINTER 查同時包含多個標簽的文章。2.5 ZSet 有序集合ZSet 在 Set 的基礎上給每個成員增加了一個 score分值Redis 根據 score 自動排序。底層實現是跳表skiplist加哈希表。常用命令ZADD key score member ZRANGE key start stop ZREVRANGE key start stop ZSCORE key member ZINCRBY key increment member ZRANK key member典型應用場景排行榜。比如游戲積分排行榜、商品銷量榜用 ZINCRBY 增加分數用 ZREVRANGE 獲取 Top N。延遲隊列。把任務執行時間作為 score用一個線程輪詢 ZRANGEBYSCORE 獲取到期的任務?;瑒哟翱谙蘖?。用 score 存時間戳通過 ZRANGEBYSCORE 統計時間窗口內的請求數。面試中經常追問“ZSet 的底層結構為什么用跳表而不是紅黑樹”回答要點跳表實現簡單、支持范圍查詢、在有序集合的場景下性能足夠O(log N)而且跳表更適合做范圍查找ZSet 的核心操作就是按分數范圍取數據。2.6 其他高級數據類型面試加分項Bitmap位圖用位操作存儲布爾型數據典型場景是用戶簽到、在線狀態。HyperLogLog去重計數內存極小適合統計 UV。GEO地理位置存儲適合“附近的人”功能。Stream可靠消息隊列支持消費者組。這部分可以展示知識廣度面試官如果追問能說出“GEO 底層基于 ZSet 實現每個位置的經緯度會被編碼為 score”這種程度就夠用了。3. Redis 持久化機制RDB 和 AOF3.1 為什么需要持久化Redis 是內存型數據庫如果進程異常退出或服務器宕機內存中的數據會全部丟失。持久化的目的就是把內存中的數據保存到磁盤上使 Redis 重啟時能夠恢復數據。面試中問到持久化通常圍繞兩個問題RDB 和 AOF 分別是什么如何選擇3.2 RDB 快照持久化RDBRedis DataBase是在指定時間間隔內將內存中的數據集快照寫入磁盤生成一個二進制的 dump.rdb 文件。觸發方式# 手動觸發 SAVE BGSAVE # 自動觸發在 redis.conf 中配置 save 900 1 save 300 10 save 60 10000SAVE 會阻塞 Redis 主進程BGSAVE 會 fork 子進程來生成 RDB主進程繼續處理命令。面試中需要說清楚RDB 的優點是文件緊湊、恢復速度快、適合做備份和災難恢復缺點是可能丟失最后一次快照之后的數據同時 fork 子進程在大數據量下會有短暫的阻塞。3.3 AOF 追加持久化AOFAppend Of File會把每次寫命令追加到 aof 文件末尾。Redis 重啟時通過重新執行 AOF 文件中的命令來恢復數據。AOF 默認是關閉的開啟配置appendonly yes appendfilename appendonly.aof appendfsync always appendfsync everysec appendfsync no配置項說明always每次寫入都同步到磁盤數據最安全性能最差。everysec每秒同步一次最多丟失 1 秒數據是推薦配置。no由操作系統決定什么時候同步性能好但安全性不可控。為了避免 AOF 文件過大Redis 提供了 AOF 重寫機制通過BGREWRITEAOF命令或自動觸發用盡可能少的命令來記錄當前數據集。3.4 RDB 和 AOF 怎么選對比項RDBAOF文件大小二進制壓縮文件小記錄寫命令文件較大恢復速度快較慢數據安全性可能丟較多數據最多丟 1 秒everysec對性能影響fork 子進程可能瞬間阻塞寫頻率高時影響較大生產環境常用的方案是同時開啟 RDB 和 AOF。Redis 優先使用 AOF 恢復數據因為 AOF 數據更完整同時利用 RDB 做定期備份。如果對數據丟失容忍度很低必須開啟 AOF 并設置 appendfsync everysec。4. 緩存設計穿透、擊穿、雪崩與解決方案4.1 緩存穿透緩存穿透是指查詢一個不存在的數據緩存中沒有數據庫中也沒有導致每次請求都直接打到數據庫。如果有惡意攻擊者持續構造不存在的 key數據庫壓力驟增。解決方案緩存空值查詢結果為空也緩存設置較短的過期時間。布隆過濾器把所有可能存在的數據哈希到一個 bitmap 中請求先經過布隆過濾器過濾掉大部分不存在的 key。參數校驗在接口層攔截明顯不合法的請求。示例代碼緩存空值使用 Spring Data Redispublic Object getData(String key) { Object value redisTemplate.opsForValue().get(key); if (value ! null) { return value; } // 模擬從數據庫查詢 Object dbValue queryFromDB(key); if (dbValue null) { // 緩存空值防止穿透過期時間設置短一些 redisTemplate.opsForValue().set(key, , 60, TimeUnit.SECONDS); } else { redisTemplate.opsForValue().set(key, dbValue, 30, TimeUnit.MINUTES); } return dbValue; }4.2 緩存擊穿緩存擊穿是指某個熱點 key 剛好在過期時間失效此時大量并發請求同時查詢這個 key緩存未命中請求全部打到數據庫。解決方案互斥鎖只允許一個線程查數據庫并重建緩存其他線程等待。邏輯過期緩存中不設置物理過期時間而是存儲一個邏輯過期時間字段查詢時判斷是否過期如果過期則異步重建緩存。熱點數據永不過期在 value 中保存過期時間業務層判斷后異步更新。這里給出基于互斥鎖的簡化示例public String getHotData(String key) { String value redisTemplate.opsForValue().get(key); if (value ! null) { return value; } String lockKey lock: key; boolean locked redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 3, TimeUnit.SECONDS); if (locked) { try { value queryFromDB(key); redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES); return value; } finally { redisTemplate.delete(lockKey); } } else { // 等待其他線程寫入緩存 try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return getHotData(key); } }互斥鎖方案簡單有效代價是緩存重建期間有少量線程等待。實際項目中要重點關注鎖的釋放避免因異常導致鎖無法釋放。4.3 緩存雪崩緩存雪崩是指大量 key 在同一時間失效或者 Redis 服務宕機導致所有請求直接打到數據庫。解決方案過期時間隨機化在設置過期時間時加上一個隨機值避免同一時間大面積失效。Redis 集群高可用使用主從復制、哨兵或 Cluster 模式避免單點故障。多級緩存本地緩存如 Caffeine Redis 緩存即使 Redis 不可用本地緩存也能扛一部分流量。服務降級在數據庫層增加限流和降級策略保護數據庫不被壓垮。面試中更好的回答是“緩存雪崩的重點不是如何保證 Redis 不宕機而是要在 Redis 不可用或緩存大規模失效時系統依然能通過降級、限流、多級緩存等手段保持可用?!?.4 緩存一致性問題只要用 Redis 做緩存就繞不開“緩存和數據庫數據不一致”的問題。常見的方案Cache Aside Pattern旁路緩存讀的時候先讀緩存緩存沒有則讀數據庫并回填寫的時候先更新數據庫再刪除緩存。延遲雙刪更新數據庫后刪除緩存等一段時間再次刪除避免并發下讀到舊數據?;?Canal 監聽 MySQL binlog異步更新緩存。面試中不要只說一個方案要能分析利弊。比較推薦的回答一般業務采用 Cache Aside 模式更新時“先更新數據庫再刪除緩存”如果要求更高的一致性可以引入分布式事務或 binlog 異步同步但這會增加系統復雜度需要根據業務權衡。5. Redis 分布式鎖5.1 為什么要用分布式鎖在分布式系統中多個服務實例同時操作共享資源時Java 的synchronized和ReentrantLock只能鎖住當前 JVM 內的線程無法跨進程互斥。分布式鎖就是讓多個進程之間通過 Redis 實現互斥訪問。5.2 基于 Redis 實現分布式鎖的演進最早的方案是使用SETNX加鎖然后EXPIRE設置過期時間但這兩個命令不是原子的如果在 SETNX 之后、EXPIRE 之前進程崩潰鎖就會永遠不釋放。后來 Redis 官方推薦使用SET key value NX EX seconds一條命令完成加鎖和過期時間設置。加鎖命令SET lock:order:1001 uuid_value NX EX 30釋放鎖時不能直接DEL因為如果鎖已經過期另一個線程獲取了同一把鎖當前線程再執行 DEL 就會誤刪別人的鎖。所以釋放鎖需要先比較 value 是否還是自己的再刪除這個過程要用 Lua 腳本保證原子性-- 釋放鎖的 Lua 腳本 if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 endJava 中通過 Spring Data Redis 執行 Lua 腳本private static final String UNLOCK_SCRIPT if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end; public void unlock(String lockKey, String requestId) { DefaultRedisScriptLong script new DefaultRedisScript(UNLOCK_SCRIPT, Long.class); redisTemplate.execute(script, Arrays.asList(lockKey), requestId); }5.3 Redisson 與看門狗機制手寫分布式鎖需要處理各種邊界條件生產環境推薦使用 Redisson。Redisson 提供了RLock內部通過 Lua 腳本實現加鎖、解鎖、重入還提供了看門狗機制如果鎖的持有者沒有顯式釋放鎖看門狗會每隔一段時間自動續期防止業務沒執行完鎖就過期了。RLock lock redissonClient.getLock(lock:order:1001); try { // 嘗試加鎖最多等待 5 秒鎖有效期默認 30 秒看門狗會自動續期 if (lock.tryLock(5, TimeUnit.SECONDS)) { // 業務邏輯 } } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } }5.4 RedLock 有必要用嗎RedLock 是 Redis 官方提出的多節點分布式鎖算法要求向多個獨立的 Redis 主節點加鎖超過半數成功才算加鎖成功。面試中經常被問到但實際項目中較少使用因為 RedLock 依賴時鐘同步、網絡延遲實現復雜且在多主切換下仍存在一致性問題。推薦回答思路“單節點 Redis 鎖 Redisson 的看門狗在絕大多數業務中已經夠用如果要更強的安全性優先考慮 ZooKeeper 或 etcd 的分布式鎖而不是 RedLock?!?. Redis 集群與可用性6.1 主從復制Redis 主從復制是指一臺主節點Master將數據同步到多臺從節點Slave實現讀寫分離和容災。主節點負責寫操作從節點負責讀操作數據由主節點單向同步到從節點。順序上主從復制分為兩個階段全量復制從節點首次同步時主節點生成 RDB 快照并發送給從節點。增量復制后續主節點把寫命令發送給從節點。從節點斷開重連后主節點通過復制積壓緩沖區同步斷連期間的數據。配置方式# 從節點配置 replicaof 127.0.0.1 63796.2 哨兵模式主從復制解決了數據備份和讀寫分離但主節點宕機后需要人工把某個從節點提升為主節點。哨兵Sentinel可以自動監控主節點和從節點的健康狀態在主節點故障時自動完成故障轉移從剩余從節點中選舉新的主節點。哨兵的關鍵作用監控檢查主從節點的運行狀態。通知節點故障時通知其他實例。自動故障轉移主節點不可用時自動選舉新的主節點。配置中心客戶端通過哨兵獲取當前主節點地址。6.3 Cluster 集群模式Redis Cluster 是 Redis 3.0 引入的分布式解決方案能夠將數據自動分片到多個節點上每個節點保存一部分數據。Redis Cluster 采用無中心化架構節點之間通過 Gossip 協議通信。分片原理整個數據空間被劃分為 16384 個哈希槽slot。每個節點負責一部分 slot例如三主節點分別負責 0~5460、5461~10922、10923~16383。計算 key 的 CRC16 值然后對 16384 取模得到該 key 應該存儲到哪個 slot。Cluster 模式的優勢是支持水平擴展性能隨節點增加而提升。需要注意的坑是 Cluster 模式下不支持多 key 操作除非這些 key 在同一個 slot因此需要使用 Hash Tag 技術讓相關 key 落到同一個槽位。面試常見問題“為什么 Redis Cluster 是 16384 個槽”常見的解釋是16384 個槽在保證數據分布均勻的同時可以使節點間心跳消息中的位圖更小減少帶寬消耗且對于常用規模的集群已經足夠。6.4 一致性哈希和哈希槽可能被追問“Redis 為什么不用一致性哈?!?。一致性哈希是分布式緩存中常用的分片算法如 Memcached但 Redis Cluster 選擇哈希槽的原因主要有哈希槽將數據分成固定數量的槽位節點增減時只需要遷移部分槽位數據遷移范圍可控。槽位和節點的映射關系明確客戶端可以精確計算 key 所在節點。數據遷移時是以槽為單位進行操作粒度更清晰。7. Redis 內存淘汰與常見問題排查7.1 過期刪除策略Redis 的過期刪除策略是“惰性刪除 定期刪除”的結合惰性刪除訪問 key 時檢查是否過期過期則刪除。優點是不占用額外 CPU缺點是過期 key 可能長期占用內存。定期刪除Redis 每隔一段時間隨機抽取一部分設置了過期時間的 key刪除其中已過期的 key。7.2 內存淘汰策略當 Redis 內存達到maxmemory限制后會根據配置的maxmemory-policy進行淘汰。常見配置項策略含義noeviction不淘汰寫入時報錯allkeys-lru從所有 key 中按 LRU 淘汰volatile-lru從設置了過期時間的 key 中按 LRU 淘汰allkeys-lfu從所有 key 中按 LFU 淘汰volatile-lfu從設置了過期時間的 key 中按 LFU 淘汰allkeys-random從所有 key 中隨機淘汰volatile-ttl從設置了過期時間且剩余時間最短的 key 中淘汰面試中回答“生產環境推薦哪種策略”時不要直接說“用 allkeys-lru”。正確的思路是優先給每個 key 設置合理的過期時間根據業務是否允許緩存丟失決定使用 volatile-lru 還是 allkeys-lru如果業務數據要求嚴格不淘汰則使用 noeviction 并做好告警。7.3 內存不足報錯 OutOfMemoryErrorJVM 項目和 Redis 都會出現內存不足的報錯。熱詞中出現的java: outofmemoryerror: insufficient memory屬于 JVM 啟動時內存不足常見原因是啟動 JVM 時指定的 -Xmx 大于物理內存。服務器內存被其他進程占用剩余可用內存不足。系統沒有足夠交換空間。排查方法# 查看系統內存 free -h # 查看 Java 進程內存占用 ps aux | grep java jmap -heap pid如果 Redis 本身內存不足可以檢查maxmemory配置、大 key、連接數、內存碎片率必要時擴容或清理大 key。7.4 連接失敗和超時Redis 連接失敗通常表現為ERR max number of clients reached或RedisConnectionFailureException。排查思路檢查 Redis 服務是否啟動redis-cli ping。檢查端口連通性telnet 127.0.0.1 6379。檢查客戶端最大連接數配置CONFIG GET maxclients。檢查防火墻和遠程訪問配置bind、protected-mode。檢查業務代碼是否存在連接池泄漏用完連接沒有釋放。Spring Boot 中可以通過配置連接池參數優化spring.redis.hostlocalhost spring.redis.port6379 spring.redis.lettuce.pool.max-active50 spring.redis.lettuce.pool.max-idle20 spring.redis.lettuce.pool.min-idle5 spring.redis.lettuce.pool.max-wait3000ms7.5 熱詞背后的 Redis 高頻面試題庫根據搜索熱詞高頻被搜的還有redis 下載、windows 安裝 redis、docker 安裝 redis 主從、redis desktop manager 可視化客戶端、redis 緩存治理。這些屬于環境搭建和運維工具建議在復習基礎知識的同時把本機環境搭好用 Redis Desktop Manager 或 Another Redis Desktop Manager 連一次能加深對 Redis 數據結構的印象。8. 三天沖刺計劃與復習建議8.1 第 1 天數據結構與基礎命令把 String、Hash、List、Set、ZSet 的常用命令全部敲一遍。理解每個類型的底層編碼和適用場景。用 Spring Data Redis 寫一個增刪改查的小 Demo。當天結束前完成自測能默寫每種數據類型至少兩個應用場景。8.2 第 2 天持久化、緩存問題與分布式鎖配置 RDB 和 AOF觀察 dump.rdb 和 appendonly.aof 文件的生成。手寫緩存穿透、擊穿、雪崩的解決方案示例。手寫 SET NX EX 分布式鎖和 Lua 解鎖腳本。看完 Redisson 官方文檔了解 RLock 基本用法。8.3 第 3 天集群、運維與面試模擬用 Docker 搭建一主兩從、哨兵或 Cluster 環境。檢查 Redis 日志分析主從復制和故障轉移的過程。把高頻面試題制作成卡片按“先結論后原理再舉例”的方式模擬作答。# Docker 搭建 Redis 主從示例 docker run -d --name redis-master -p 6379:6379 redis:latest docker run -d --name redis-slave1 -p 6380:6379 --link redis-master \ redis:latest redis-server --replicaof redis-master 6379 docker run -d --name redis-slave2 -p 6381:6379 --link redis-master \ redis:latest redis-server --replicaof redis-master 63798.4 面試答題的通用模板面試中回答 Redis 相關問題時推薦采用“結論先行展開原理結合實際場景”的結構先給結論用一兩句話說清楚是什么比如“緩存雪崩是指大量 key 同時過期導致請求打到數據庫”。展開原因和原理說明為什么會出現。給出解決方案結合自己的項目經驗描述實際是怎么處理的。如果被追問說明方案的優缺點和備選方案。8.5 面試中避免踩的坑只背結論不解釋原理。面試官只要追問“為什么”就會暴露。忽略版本差異。Redis 6.0 引入了多線程 IO5.0 引入了 Stream不同版本支持的配置和行為有差異回答時注明“以 Redis 6.x/7.x 為例”。不區分單機和生產環境。面試官問分布式鎖就不要只說SETNX一條命令完事要聊到鎖釋放的原子性、看門狗、集群下的問題??照劯卟l。說“我們項目用了 Redis”時至少能說出具體存了什么、為什么用 Hash 而不是 String、過期時間怎么設置的。9. Redis 面試中容易被忽略的細節9.1 Redis 是單線程的為什么還要用連接池雖然是單線程處理命令但每個客戶端連接都需要占用一個文件描述符建立和斷開連接也有開銷。連接池的作用是復用已經建立的連接減少 TCP 握手和 Redis 處理連接事件的消耗讓業務代碼在高并發下不至于頻繁創建連接。9.2 大 key 和熱 key 問題大 key 是指 value 非常大例如一個 List 有幾百萬個元素或包含大量元素的 key。大 key 會造成阻塞、內存不均、網絡擁塞。熱 key 是指被高頻訪問的 key可能單點壓力過大。解決方案大 key 拆分將大對象的字段拆分到多個 Hash key 中。對大 key 使用 SCAN 命令掃描避免使用 KEYS。熱 key 加本地緩存或副本分散讀壓力。使用redis-cli --bigkeys掃描大 key。9.3 為什么生產環境禁止使用 KEYS 命令KEYS 命令會遍歷所有 key在數據量大的情況下阻塞 Redis 主線程導致整個實例不可服務。推薦使用 SCAN 命令分批迭代不會阻塞。SCAN 0 MATCH user:* COUNT 1009.4 Redis 事務和 Lua 腳本Redis 事務通過 MULTI、EXEC、DISCARD 實現和 MySQL 事務不同Redis 事務不支持回滾只是把命令按順序打包執行。如果在事務中發現命令語法錯誤事務會中斷如果運行時錯誤如對字符串執行 INCR其他命令仍會執行。Lua 腳本則可以通過EVAL和EVALSHA將一段邏輯在服務端原子執行在分布式鎖、限流等場景中非常常用。10. 實戰踩坑記錄10.1 緩存和數據庫一致性出問題業務中曾經出現過修改用戶信息后緩存里還是舊數據的情況。原因是代碼里先刪緩存再更新數據庫并發情況下另一個線程先查數據庫還沒寫完然后更新線程把舊數據又寫回緩存。后來統一改成“先更新數據庫再刪除緩存”并加上延遲雙刪兜底才基本解決了問題。10.2 分布式鎖導致的死鎖手寫分布式鎖時使用 SETNX 加鎖后忘記設置過期時間在業務出現異常時鎖沒有被釋放其他線程一直拿不到鎖。排查發現鎖的 value 沒有區分線程釋放鎖時直接 DEL導致誤刪了其他線程的鎖。后來統一改為隨機 UUID 作為 value并用 Lua 腳本校驗后刪除。10.3 Redis 連接數被打滿上線后發現大量報錯ERR max number of clients reached原因是項目使用redisTemplate時沒有配置連接池的最大值默認連接數不夠同時部分請求執行很慢連接被長期占用。解決方式是調大連接池最大連接數并優化慢查詢排查業務代碼中是否有大量不必要的 Redis 操作。11. 常見問題速查表下面這張表匯總了 Redis 面試中最高頻的 12 個問題可以作為考前最后一天的速查清單問題核心回答要點Redis 為什么快內存存儲、單線程、IO 多路復用、高效數據結構Redis 有哪些數據類型String、Hash、List、Set、ZSet、Bitmap、HyperLogLog、GEO、StreamString 底層是什么SDSO(1) 獲取長度、避免緩沖區溢出、動態擴容ZSet 底層為什么要用跳表實現簡單、支持范圍查詢、O(log N) 性能RDB 和 AOF 怎么選同時開啟AOF 恢復為主RDB 做備份什么是緩存穿透查詢不存在的數據布隆過濾器或緩存空值什么是緩存擊穿熱點 key 失效互斥鎖或邏輯過期什么是緩存雪崩大量 key 同時失效或 Redis 宕機過期時間隨機化、集群高可用分布式鎖怎么實現SET NX EX Lua 解鎖生產用 RedissonRedis 集群有幾種主從、哨兵、Cluster演進關系Cluster 數據分片怎么分CRC16(key) % 16384 定位哈希槽Redis 內存滿了怎么辦maxmemory-policy 配置淘汰策略推薦 volatile-lru 或 allkeys-lru這份速查表里的每個問題都應該能展開講 3 到 5 分鐘。Redis 面試題表面上看是背考點實際上考的是對緩存設計和分布式場景的理解。把數據結構、持久化、緩存問題、分布式鎖、集群模式這幾條主線串起來配合手寫命令和代碼3 天時間足夠把 Redis 這一塊準備得比較扎實。面試時如果能隨口說出 LInux 下的 redis-cli 命令以及 Spring Boot 中如何配置連接池會明顯比只會背概念的候選人更有競爭力。這份清單可以先存下來每天過一遍8 月面試時不慌。