日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis 面试题总结

發布時間:2024/3/26 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis 面试题总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Redis是什么?

Redis 是一個 key-value 存儲系統,它支持存儲的 value 類型相對更多,包括 string、list、set、zset(sorted set --有序集合)和 hash。這些數據結構都支持 push/pop、add/remove 及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis 支持各種不同方式的排序。為了保證效率,數據都是緩存在內存中,Redis 會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。


Redis 都有哪些使用場景?

  • 緩存:這應該是 Redis 最主要的功能了,也是大型網站必備機制,合理地使用緩存不僅可以加 快數據的訪問速度,而且能夠有效地降低后端數據源的壓力。
  • 共享Session:對于一些依賴 session 功能的服務來說,如果需要從單機變成集群的話,可以選擇 redis 來統一管理 session。
  • 消息隊列系統:消息隊列系統可以說是一個大型網站的必備基礎組件,因為其具有業務 解耦、非實時業務削峰等特性。Redis提供了發布訂閱功能和阻塞隊列的功 能,雖然和專業的消息隊列比還不夠足夠強大,但是對于一般的消息隊列功 能基本可以滿足。比如在分布式爬蟲系統中,使用 redis 來統一管理 url隊列。
  • 分布式鎖:在分布式服務中??梢岳肦edis的setnx功能來編寫分布式的鎖,雖然這個可能不是太常用。 當然還有諸如排行榜、點贊功能都可以使用 Redis 來實現,但是 Redis 也不是什么都可以做,比如數據量特別大時,不適合 Redis,我們知道 Redis 是基于內存的,雖然內存很便宜,但是如果你每天的數據量特別大,比如幾億條的用戶行為日志數據,用 Redis 來存儲的話,成本相當的高。

Redis為什么這么快?

  • 基于內存存儲實現
    我們都知道內存讀寫是比在磁盤快很多的,Redis基于內存存儲實現的數據庫,相對于數據存在磁盤的MySQL數據庫,省去磁盤I/O的消耗。

  • 高效的數據結構
    我們知道,MySQL 索引為了提高效率,選擇了 B+ 樹的數據結構。其實合理的數據結構,就是可以讓你的應用/程序更快。先看下 Redis 的數據結構&內部編碼圖:

    SDS簡單動態字符串

    • 字符串長度處理:Redis獲取字符串長度,時間復雜度為O(1),而C語言中,需要從頭開始遍歷,復雜度為O(n);
    • 空間預分配:字符串修改越頻繁的話,內存分配越頻繁,就會消耗性能,而SDS修改和空間擴充,會額外分配未使用的空間,減少性能損耗。
    • 惰性空間釋放:SDS 縮短時,不是回收多余的內存空間,而是free記錄下多余的空間,后續有變更,直接使用free中記錄的空間,減少分配。
    • 二進制安全:Redis可以存儲一些二進制數據,在C語言中字符串遇到’\0’會結束,而 SDS中標志字符串結束的是len屬性。
  • 合理的數據編碼
    Redis 支持多種數據數據類型,每種基本類型,可能對多種數據結構。什么時候,使用什么樣數據結構,使用什么樣編碼,是 redis 設計者總結優化的結果。
    • String:如果存儲數字的話,是用int類型的編碼;如果存儲非數字,小于等于39字節的字符串,是embstr;大于 39 個字節,則是 raw 編碼。
    • List:如果列表的元素個數小于 512 個,列表每個元素的值都小于 64 字節(默認),使用 ziplist 編碼,否則使用 linkedlist 編碼
    • Hash:哈希類型元素個數小于512 個,所有值小于 64 字節的話,使用ziplist編碼,否則使用 hashtable 編碼。
    • Set:如果集合中的元素都是整數且元素個數小于 512 個,使用 intset 編碼,否則使用 hashtable 編碼。
    • Zset:當有序集合的元素個數小于 128 個,每個元素的值小于 64 字節時,使用 ziplist 編碼,否則使用skiplist(跳躍表)編碼

    3.4 合理的線程模型
    I/O 多路復用

    多路I/O復用技術可以讓單個線程高效的處理多個連接請求,而Redis使用用epoll作為I/O多路復用技術的實現。并且,Redis自身的事件處理模型將epoll中的連接、讀寫、關閉都轉換為事件,不在網絡I/O上浪費過多的時間。

    什么是I/O多路復用?
    I/O :網絡 I/O
    多路 :多個網絡連接
    復用:復用同一個線程。
    IO多路復用其實就是一種同步 IO 模型,它實現了一個線程可以監視多個文件句柄;一旦某個文件句柄就緒,就能夠通知應用程序進行相應的讀寫操作;而沒有文件句柄就緒時,就會阻塞應用程序,交出 cpu。

    單線程模型
    Redis是單線程模型的,而單線程避免了CPU不必要的上下文切換和競爭鎖的消耗。也正因為是單線程,如果某個命令執行過長(如hgetall命令),會造成阻塞。
    Redis是面向快速執行場景的數據庫,所以要慎用如 smembers 和 lrange、hgetall 等命令。
    Redis 6.0 引入了多線程提速,它的執行命令操作內存的仍然是個單線程。

  • 虛擬內存機制
    Redis直接自己構建了VM機制 ,不會像一般的系統會調用系統函數處理,會浪費一定的時間去移動和請求。
  • Redis的虛擬內存機制是啥呢?

    虛擬內存機制就是暫時把不經常訪問的數據(冷數據)從內存交換到磁盤中,從而騰出寶貴的內存空間用于其它需要訪問的數據(熱數據)。通過 VM 功能可以實現冷熱數據分離,使熱數據仍在內存中、冷數據保存到磁盤。這樣就可以避免因為內存不足而造成訪問速度下降的問題。


    Redis支持的數據類型?

    String(字符串)

    格式: set key value、get key

    string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。
    string類型是Redis最基本的數據類型,一個鍵最大能存儲512MB。
    應用場景:共享session、分布式鎖,計數器、限流。
    內部編碼有3種,int(8字節長整型)/embstr(小于等于39字節字符串)/raw(大于39個字節字符串)
    C語言的字符串是char[]實現的,而Redis使用SDS(simple dynamic string) 封裝,sds源碼如下:

    struct sdshdr{ unsigned int len; // 標記buf的長度 unsigned int free; //標記buf中未使用的元素個數 char buf[]; // 存放元素的坑 }

    SDS 結構圖如下:

    Redis為什么選擇SDS結構,而C語言原生的char[]不香嗎?
    舉例其中一點,SDS中,O(1) 時間復雜度,就可以獲取字符串長度;而 C 字符串,需要遍歷整個字符串,時間復雜度為 O(n)

    Hash(哈希)

    格式: hset key field value 、hget key field

    Redis hash 是一個鍵值 ( key=>value ) 對集合。
    Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用于存儲對象。

    List(列表)

    Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)

    格式: lpush name value
    在 key 對應 list 的頭部添加字符串元素

    格式: rpush name value
    在 key 對應 list 的尾部添加字符串元素

    格式: lrem name index
    key 對應 list 中刪除 count 個和 value 相同的元素

    格式: llen name
    返回 key 對應 list 的長度

    Set(集合)

    格式: sadd name value

    Redis的Set是string類型的無序集合。
    集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是 O(1)。

    zset (sorted set:有序集合)
    格式: zadd name score value

    zset 和 set 一樣也是 string 類型元素的集合,且不允許重復的成員。
    不同的是每個元素都會關聯一個 double 類型的分數。redis 正是通過分數來為集合中的成員進行從小到大的排序。

    zset的成員是唯一的,但分數(score)卻可以重復。


    Redis為什么是單線程的?

    • 代碼更清晰,處理邏輯更簡單;
    • 不用考慮各種鎖的問題,不存在加鎖和釋放鎖的操作,沒有因為可能出現死鎖而導致的性能問題;
    • 不存在多線程切換而消耗 CPU;
    • 無法發揮多核 CPU 的優勢,但可以采用多開幾個 Redis 實例來完善;

    Redis真的是單線程的嗎?

    Redis6.0 之前是單線程的,Redis6.0 之后開始支持多線程;
    redis 內部使用了基于 epoll 的多路服用,也可以多部署幾個 redis 服務器解決單線程的問題;
    redis 主要的性能瓶頸是內存和網絡;
    內存好說,加內存條就行了,而網絡才是大麻煩,所以 redis6 引入了多線程的概念,
    redis6.0在網絡 IO 處理方面引入了多線程,如網絡數據的讀寫和協議解析等,需要注意的是,執行命令的核心模塊還是單線程的。


    Redis 持久化?

    redis提供了兩種持久化的方式,分別是 RDB(Redis DataBase)和 AOF(Append Only File)。

    • RDB,簡而言之,就是在不同的時間點,將 redis 存儲的數據生成快照并存儲到磁盤等介質上;
    • AOF,則是換了一個角度來實現持久化,那就是將redis執行過的所有寫指令記錄下來,在下次 redis 重新啟動時,只要把這些寫指令從前到后再重復執行一遍,就可以實現數據恢復了。

    RDB 持久化

    是指在指定的時間間隔內,執行指定次數的寫操作,將內存中的數據集快照寫入磁盤中,它是Redis默認的持久化方式。執行完操作后,在指定目錄下會生成一個dump.rdb文件,Redis 重啟的時候,通過加載dump.rdb文件來恢復數據。RDB觸發機制主要有以下幾種:

    RDB 的優點

    • 適合大規模的數據恢復場景,如備份,全量復制等

    RDB缺點

    • 沒辦法做到實時持久化/秒級持久化。
    • 新老版本存在RDB格式兼容問題

    在生成 RDB期間,Redis 可以同時處理寫請求么?
    可以的,Redis提供兩個指令生成RDB,分別是 save 和 bgsave

    • 如果是 save 指令,會阻塞,因為是主線程執行的。
    • 如果是 bgsave 指令,是 fork 一個子進程來寫入 RDB 文件的,快照持久化完全交給子進程來處理,父進程則可以繼續處理客戶端的請求。

    AOF(append only file) 持久化

    采用日志的形式來記錄每個寫操作,追加到文件中,重啟時再重新執行AOF文件中的命令來恢復數據。它主要解決數據持久化的實時性問題。默認是不開啟的。

    AOF的工作流程如下

    AOF的優點

    數據的一致性和完整性更高
    AOF的缺點

    AOF記錄的內容越多,文件越大,數據恢復變慢。

    其實 RDB 和 AOF 兩種方式也可以同時使用,在這種情況下,如果 redis 重啟的話,則會優先采用 AOF 方式來進行數據恢復,這是因為 AOF 方式的數據恢復完整度更高。

    如果你沒有數據持久化的需求,也完全可以關閉 RDB 和 AOF 方式,這樣的話,redis 將變成一個純內存數據庫。


    緩存穿透/緩存雪崩?如何解決?

    一個常見的緩存使用方式:讀請求來了,先查下緩存,緩存有值命中,就直接返回;緩存沒命中,就去查數據庫,然后把數據庫的值更新到緩存,再返回。

    緩存穿透

    一般的緩存系統,都是按照 key 去緩存查詢,如果不存在對應的 value,就應該去后端系統查找(比如DB 數據庫)。一些惡意的請求會故意查詢不存在的 key,請求量很大,就會對后端系統造成很大的壓力。這就叫做緩存穿透。

    緩存穿透一般都是這幾種情況產生的:

    業務不合理的設計,比如大多數用戶都沒開守護,但是你的每個請求都去緩存,查詢某個userid查詢有沒有守護。
    業務/運維/開發失誤的操作,比如緩存和數據庫的數據都被誤刪除了。
    黑客非法請求攻擊,比如黑客故意捏造大量非法請求,以讀取不存在的業務數據。

    如何解決?

    • 如果是非法請求,我們在API入口,對參數進行校驗,過濾非法值。
    • 對查詢結果為空的情況也進行緩存,緩存時間設置短一點,或者該 key 對應的數據 insert 之后清理緩存。
    • 對一定不存在的 key 進行過濾??梢园阉械目赡艽嬖诘?key 放到一個大的 Bitmap 中,查詢時通過該Bitmap 過濾。

    緩存雪崩

    當緩存服務器重啟或者大量緩存集中在某一時間段失效,這樣在失效的時候,會給后端系統帶來很大的壓力,導致系統崩潰。

    如何解決?

    • 在緩存失效后,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個 key 只允許一個線程查詢數據和寫緩存,其它線程等待;
    • 做二級緩存,A1 為原始緩存,A2 為拷貝緩存,A1 失效時,可以訪問 A2,A1 緩存失效時間設置為短期,A2 設置為長期;
    • 不同的 key,設置不同的過期時間,讓緩存失效的時間盡量均勻;

    緩存擊穿

    指熱點 key 在某個時間點過期的時候,而恰好在這個時間點對這個 Key 有大量的并發請求過來,從而大量的請求打到 DB。

    緩存擊穿和緩存雪崩看著有點像,其實它兩區別是,緩存雪奔是指數據庫壓力過大甚至 down 機,緩存擊穿只是大量并發請求到了 DB 數據庫層面??梢哉J為擊穿是緩存雪崩的一個子集吧

    如何解決?

    • 使用互斥鎖方案。緩存失效時,不是立即去加載 DB 數據,而是先使用某些帶成功返回的原子操作命令,如(Redis的setnx)去操作,成功的時候,再去加載 DB 數據庫數據和設置緩存。否則就去重試獲取緩存。
    • “永不過期”,是指沒有設置過期時間,但是熱點數據快要過期時,異步線程去更新和設置過期時間。

    怎么保證緩存和數據庫數據的一致性?

    1、淘汰緩存

    數據如果比較復雜,進行緩存的更新操作就會變得異常復雜,因此一般推薦選擇淘汰緩存,而不是更新緩存。

    2、選擇先淘汰緩存,再更新數據庫

    假如先更新數據庫,再淘汰緩存,如果淘汰緩存失敗,那么后面的請求都會得到臟數據,直至緩存過期。

    假如先淘汰緩存再更新數據庫,如果更新數據庫失敗,只會產生一次緩存穿透,相比較而言,后者對業務則沒有本質上的影響。

    3、延時雙刪策略

    如下場景:同時有一個請求 A 進行更新操作,另一個請求 B 進行查詢操作。

  • 請求 A 進行寫操作,刪除緩存
  • 請求 B 查詢發現緩存不存在
  • 請求 B 去數據庫查詢得到舊值
  • 請求 B 將舊值寫入緩存
  • 請求 A 將新值寫入數據庫
  • public void write(String key,Object data){redisUtils.del(key);db.update(data);Thread.Sleep(100);redisUtils.del(key); }

    這么做,可以將1秒內所造成的緩存臟數據,再次刪除。這個時間設定可根據俄業務場景進行一個調節。

    4、數據庫讀寫分離的場景

    兩個請求,一個請求 A 進行更新操作,另一個請求B進行查詢操作。

  • 請求 A 進行寫操作,刪除緩存
  • 請求 A 將數據寫入數據庫了,
  • 請求 B 查詢緩存發現,緩存沒有值
  • 請求 B 去從庫查詢,這時,還沒有完成主從同步,因此查詢到的是舊值
  • 請求 B 將舊值寫入緩存
  • 數據庫完成主從同步,從庫變為新值
    依舊采用延時雙刪策略解決此問題。

  • Redis 有哪些架構模式

    單機版

    特點:

    • 簡單

    問題:

    • 內存容量有限
    • 處理能力有限
    • 無法高可用。

    主從模式

    Redis 的復制(replication)功能允許用戶根據一個 Redis 服務器來創建任意多個該服務器的復制品,其中被復制的服務器為主服務器(master),而通過復制創建出來的服務器復制品則為從服務器(slave)。

    只要主從服務器之間的網絡連接正常,主從服務器兩者會具有相同的數據,主服務器就會一直將發生在自己身上的數據更新同步給 從服務器,從而一直保證主從服務器的數據相同。

    特點:

    • master/slave 角色
    • master/slave 數據相同
    • 降低 master 讀壓力在轉交從庫

    問題:

    • 無法保證高可用
    • 沒有解決 master 寫的壓力

    哨兵模式

    Redis sentinel 是一個分布式系統中監控 redis 主從服務器,并在主服務器下線時自動進行故障轉移。其中三個特性:

    • 監控(Monitoring):Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。
    • 提醒(Notification):當被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。
    • 自動故障遷移(Automatic failover):當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作。

    特點:

    • 保證高可用
    • 監控各個節點
    • 自動故障遷移

    缺點:

    • 主從模式,切換需要時間丟數據
    • 沒有解決 master 寫的壓力

    集群(代理型)

    Twemproxy 是一個 Twitter 開源的一個 redis 和 memcache 快速/輕量級代理服務器;Twemproxy 是一個快速的單線程代理程序,支持 Memcached ASCII 協議和 redis 協議。

    特點:

    • 多種 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins
    • 支持失敗節點自動刪除
    • 后端 Sharding 分片邏輯對業務透明,業務方的讀寫方式和操作單個 Redis 一致

    缺點:

    • 增加了新的 proxy,需要維護其高可用。
    • failover 邏輯需要自己實現,其本身不能支持故障的自動轉移可擴展性差,進行擴縮容都需要手動干預

    集群(直連型)## 標題

    從 redis 3.0 之后版本支持 redis-cluster 集群,Redis-Cluster 采用無中心結構,每個節點保存數據和整個集群狀態,每個節點都和其他所有節點連接。

    特點:

    • 無中心架構(不存在哪個節點影響性能瓶頸),少了 proxy 層。
    • 數據按照 slot 存儲分布在多個節點,節點間數據共享,可動態調整數據分布。
    • 可擴展性,可線性擴展到 1000 個節點,節點可動態添加或刪除。
    • 高可用性,部分節點不可用時,集群仍可用。通過增加 Slave 做備份數據副本
    • 實現故障自動 failover,節點之間通過 gossip 協議交換狀態信息,用投票機制完成 Slave到 Master 的角色提升。

    缺點:

    • 資源隔離性較差,容易出現相互影響的情況。
    • 數據通過異步復制,不保證數據的強一致性
    • 高可用Redis架構分析搭建,可以參考:

    Redis 過期鍵的刪除策略?

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

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

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

    Redis 有哪幾種數據淘汰策略?

  • volatile-lru:當內存不足以容納新寫入數據時,從設置了過期時間的key中使用LRU(最近最少使用)算法進行淘汰;
  • allkeys-lru:當內存不足以容納新寫入數據時,從所有key中使用LRU(最近最少使用)算法進行淘汰。
  • volatile-lfu:4.0版本新增,當內存不足以容納新寫入數據時,在過期的key中,使用LFU算法進行刪除key。
  • allkeys-lfu:4.0版本新增,當內存不足以容納新寫入數據時,從所有key中使用LFU算法進行淘汰
  • volatile-random:當內存不足以容納新寫入數據時,從設置了過期時間的key中,隨機淘汰數據;。
  • allkeys-random:當內存不足以容納新寫入數據時,從所有key中隨機淘汰數據。
  • volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的key中,根據過期時間進行淘汰,越早過期的優先被淘汰;
  • noeviction:默認策略,當內存不足以容納新寫入數據時,新寫入操作會報錯。

  • 熱 Key 問題,如何解決

    什么是熱Key呢?在Redis中,我們把訪問頻率高的key,稱為熱點key。

    **熱點Key是怎么產生的呢?**主要原因有兩個:

    • 用戶消費的數據遠大于生產的數據,如秒殺、熱點新聞等讀多寫少的場景。
    • 請求分片集中,超過單 Redis 服務器的性能,比如固定名稱 key,Hash 落入同一臺服務器,瞬間訪問量極大,超過機器瓶頸,產生熱點 Key 問題。

    那么在日常開發中,如何識別到熱點key呢?

    • 憑經驗判斷哪些是熱Key;
    • 客戶端統計上報;
    • 服務代理層上報

    如何解決熱key問題?

    • Redis 集群擴容:增加分片副本,均衡讀流量;
    • 將熱 key 分散到不同的服務器中;
    • 使用二級緩存,即 JVM 本地緩存,減少 Redis 的讀請求。

    MySQL 與 Redis 如何保證雙寫一致性

    • 緩存延時雙刪
    • 刪除緩存重試機制
    • 讀取 biglog 異步刪除緩存

    延時雙刪

    什么是延時雙刪呢?流程圖如下:

    延時雙刪流程

  • 先刪除緩存
  • 再更新數據庫
  • 休眠一會(比如1秒),再次刪除緩存。
    這個休眠一會,一般多久呢?都是1秒?
  • 這個休眠時間 = 讀業務邏輯數據的耗時 + 幾百毫秒。為了確保讀請求結束,寫請求可以刪除讀請求可能帶來的緩存臟數據。

    這種方案還算可以,只有休眠那一會(比如就那1秒),可能有臟數據,一般業務也會接受的。但是如果第二次刪除緩存失敗呢?緩存和數據庫的數據還是可能不一致,對吧?給 Key 設置一個自然的 expire 過期時間,讓它自動過期怎樣?那業務要接受過期時間內,數據的不一致咯?還是有其他更佳方案呢?

    刪除緩存重試機制

    因為延時雙刪可能會存在第二步的刪除緩存失敗,導致的數據不一致問題??梢允褂眠@個方案優化:刪除失敗就多刪除幾次呀,保證刪除緩存成功就可以了呀~ 所以可以引入刪除緩存重試機制

    刪除緩存重試流程

  • 寫請求更新數據庫
  • 緩存因為某些原因,刪除失敗
  • 把刪除失敗的key放到消息隊列
  • 消費消息隊列的消息,獲取要刪除的key
  • 重試刪除緩存操作
  • 讀取biglog異步刪除緩存

    重試刪除緩存機制還可以吧,就是會造成好多業務代碼入侵。其實,還可以這樣優化:通過數據庫的binlog 來異步淘汰 key。

    以mysql為例吧

    • 可以使用阿里的canal將binlog日志采集發送到MQ隊列里面
    • 然后通過ACK機制確認處理這條更新消息,刪除緩存,保證數據緩存一致性

    Redis 事務機制

    Redis 通過 MULTI、EXEC、WATCH 等一組命令集合,來實現事務機制。事務支持一次執行多個命令,一個事務中所有命令都會被序列化。在事務執行過程,會按照順序串行化執行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中。

    簡言之,Redis事務就是順序性、一次性、排他性的執行一個隊列中的一系列命令。

    Redis執行事務的流程如下:

  • 開始事務(MULTI)
  • 命令入隊
  • 執行事務(EXEC)、撤銷事務(DISCARD )
  • Redis 的 Hash 沖突

    Redis 作為一個 K-V 的內存數據庫,它使用用一張全局的哈希來保存所有的鍵值對。這張哈希表,有多個哈希桶組成,哈希桶中的 entry 元素保存了 key 和 value 指針,其中 key 指向了實際的鍵,value 指向了實際的值。

    哈希表查找速率很快的,有點類似于Java中的HashMap,它讓我們在O(1) 的時間復雜度快速找到鍵值對。首先通過key計算哈希值,找到對應的哈希桶位置,然后定位到entry,在entry找到對應的數據。

    什么是哈希沖突?

    哈希沖突:通過不同的key,計算出一樣的哈希值,導致落在同一個哈希桶中。

    Redis為了解決哈希沖突,采用了鏈式哈希。鏈式哈希是指同一個哈希桶中,多個元素用一個鏈表來保存,它們之間依次用指針連接。

    有些讀者可能還會有疑問:哈希沖突鏈上的元素只能通過指針逐一查找再操作。當往哈希表插入數據很多,沖突也會越多,沖突鏈表就會越長,那查詢效率就會降低了。

    為了保持高效,Redis 會對哈希表做rehash操作,也就是增加哈希桶,減少沖突。為了rehash更高效,Redis還默認使用了兩個全局哈希表,一個用于當前使用,稱為主哈希表,一個用于擴容,稱為備用哈希表。


    Redis底層,使用的什么通訊協議?

    RESP,英文全稱是Redis Serialization Protocol,它是專門為 redis 設計的一套序列化協議. 這個協議其實在 redis 的 1.2 版本時就已經出現了,但是到了redis2.0 才最終成為 redis 通訊協議的標準。

    RESP主要有實現簡單、解析速度快、可讀性好等優點。

    總結

    以上是生活随笔為你收集整理的Redis 面试题总结的全部內容,希望文章能夠幫你解決所遇到的問題。

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