Redis核心架構

一、核心模塊如圖?

圖1-10

  • Client 客戶端,官方提供了 C 語言開發的客戶端,可以發送命令,性能分析和測試等。
  • 網絡層事件驅動模型,基于 I/O 多路復用,封裝了一個短小精悍的高性能 ae 庫,全稱是 a simple event-driven programming library
    • 在 ae 這個庫里面,我通過 aeApiState 結構體對 epoll、select、kqueue、evport四種 I/O 多路復用的實現進行適配,讓上層調用方感知不到在不同操作系統實現 I/O 多路復用的差異。
    • Redis 中的事件可以分兩大類:一類是網絡連接、讀、寫事件;另一類是時間事件,比如定時執行 rehash 、RDB 內存快照生成,過期鍵值對清理操作。
  • 命令解析和執行層,負責執行客戶端的各種命令,比如 SET、DEL、GET等。
  • 內存分配和回收,為數據分配內存,提供不同的數據結構保存數據。
  • 持久化層,提供了 RDB 內存快照文件 和 AOF 兩種持久化策略,實現數據可靠性。
  • 高可用模塊,提供了副本、哨兵、集群實現高可用。
  • 監控與統計,提供了一些監控工具和性能分析工具,比如監控內存使用、基準測試、內存碎片、bigkey 統計、慢指令查詢等。

二、數據存儲原理

????????在掌握存儲原理之前,先看一下全局架構圖,后邊慢慢分析他們的作用。

????????如圖 是由 redisDb、dict、dictEntry、redisObejct 關系圖:

圖1-11

1.redisServer

????????每個被啟動的服務我都會抽象成一個 redisServer,源碼定在server.hredisServer 結構體。結構體字段很多,不再一一列舉,部分核心字段如下。

truct redisServer {pid_t pid;  /* 主進程 pid. */pthread_t main_thread_id; /* 主線程 id */char *configfile;  /*redis.conf 文件絕對路徑*/redisDb *db; /* 存儲鍵值對數據的 redisDb 實例 */int dbnum;  /* DB 個數 */dict *commands; /* 當前實例能處理的命令表,key 是命令名,value 是執行命令的入口 */aeEventLoop *el;/* 事件循環處理 */int sentinel_mode;  /* true 則表示作為哨兵實例啟動 *//* 網絡相關 */int port;/* TCP 監聽端口 */list *clients; /* 連接當前實例的客戶端列表 */list *clients_to_close; /* 待關閉的客戶端列表 */client *current_client; /* 當前執行命令的客戶端*/
};

????????這個結構體包含了存儲鍵值對的數據庫實例、redis.conf 文件路徑、命令列表、加載的 Modules、網絡監聽、客戶端列表、RDB AOF 加載信息、配置信息、RDB 持久化、主從復制、客戶端緩存、數據結構壓縮、pub/sub、Cluster、哨兵等一系列 Redis 實例運行的必要信息。

????????接下來我們分別看下他們之間的關系和作用。

2.redisDb

????????其中redisDb *db指針非常重要,它指向了一個長度為 dbnum(默認 16)的 redisDb 數組,它是整個存儲的核心,我就是用這玩意來存儲鍵值對。

typedef struct redisDb {dict *dict;dict *expires;dict *blocking_keys;dict *ready_keys;dict *watched_keys;int id;long long avg_ttl;unsigned long expires_cursor;list *defrag_later;clusterSlotToKeyMapping *slots_to_keys;
} redisDb;

????????dict 和 expires

  • dict 和 expires 是最重要的兩個屬性,底層數據結構是字典,分別用于存儲鍵值對數據和 key 的過期時間。
  • expires,底層數據結構是 dict 字典,存儲每個 key 的過期時間。

3.dict

????????Redis 使用 dict 結構來保存所有的鍵值對(key-value)數據,這是一個散列表,所以 key 查詢時間復雜度是 O(1) 。

struct dict {dictType *type;dictEntry **ht_table[2];unsigned long ht_used[2];long rehashidx;int16_t pauserehash;signed char ht_size_exp[2];
};

dict 的結構體里,有 dictType *type**ht_table[2]long rehashidx 三個很重要的結構。

  • type 存儲了 hash 函數,key 和 value 的復制等函數;
  • ht_table[2],長度為 2 的數組,默認使用 ht_table[0] 存儲鍵值對數據。我會使用 ht_table[1] 來配合實現漸進式 reahsh 操作。
  • rehashidx 是一個整數值,用于標記是否正在執行 rehash 操作,-1 表示沒有進行 rehash。如果正在執行 rehash,那么其值表示當前 rehash 操作執行的 ht_table[1] 中的 dictEntry 數組的索引。

????????重點關注 ht_table 數組,數組每個位置叫做哈希桶,就是這玩意保存了所有鍵值對,每個哈希桶的類型是 dictEntry。

MySQL:“Redis 支持那么多的數據類型,哈希桶咋保存?”

????????他的玄機就在 dictEntry 中,每個 dict 有兩個 ht_table,用于存儲鍵值對數據和實現漸進式 rehash。

typedef struct dictEntry {void *key;union {// 指向實際 value 的指針void *val;uint64_t u64;int64_t s64;double d;} v;// 散列表沖突生成的鏈表struct dictEntry *next;void *metadata[];
} dictEntry;
  • *key 指向鍵值對的鍵的指針,指向一個 sds 對象,key 都是 string 類型。
  • v 是鍵值對的 value 值,是個 union(聯合體),當它的值是 uint64_t、int64_t 或 double 數字類型時,就不再需要額外的存儲,這有利于減少內存碎片。(為了節省內存操碎了心)當值為非數字類型,就是用 val 指針存儲。
  • *next指向另一個 dictEntry 結構, 多個 dictEntry 可以通過 next 指針串連成鏈表, 從這里可以看出, ht_table 使用鏈地址法來處理鍵碰撞:當多個不同的鍵擁有相同的哈希值時,哈希表用一個鏈表將這些鍵連接起來。

4.redisObject

????????dictEntry*val 指針指向的值實際上是一個 redisObject 結構體,這是一個非常重要的結構體。

????????我的 key 是字符串類型,而 value 可以是 String、Lists、Set、Sorted Set、Hashes 等數據類型。

????????鍵值對的值都被包裝成 redisObject 對象, redisObjectserver.h 中定義。

typedef struct redisObject {unsigned type:4;unsigned encoding:4;unsigned lru:LRU_BITS;int refcount;void *ptr;
} robj;
  • type:記錄了對象的類型,string、set、hash 、Lis、Sorted Set 等,根據該類型來確定是哪種數據類型,這樣我才知道該使用什么指令執行嘛。
  • encoding:編碼方式,表示 ptr 指向的數據類型具體數據結構,即這個對象使用了什么數據結構作為底層實現保存數據。同一個對象使用不同編碼內存占用存在明顯差異,節省內存,這玩意功不可沒。
  • lru:LRU_BITS:LRU 策略下對象最后一次被訪問的時間,如果是 LFU 策略,那么低 8 位表示訪問頻率,高 16 位表示訪問時間。
  • refcount :表示引用計數,由于 C 語言并不具備內存回收功能,所以 Redis 在自己的對象系統中添加了這個屬性,當一個對象的引用計數為 0 時,則表示該對象已經不被任何對象引用,則可以進行垃圾回收了。
  • ptr 指針:指向值的指針,對象的底層實現數據結構。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/93257.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/93257.shtml
英文地址,請注明出處:http://en.pswp.cn/web/93257.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python爬蟲大師課:HTTP協議深度解析與工業級請求封裝

Python爬蟲大師課:HTTP協議深度解析與工業級請求封裝 從零構建企業級爬蟲框架(附完整源碼) 一、爬蟲基礎:網絡世界的通行證 ??HTTP協議核心數據??: 全球網站數量:20億 HTTP請求占比:83% …

機器學習——PCA(主成分分析)降維

PCA(主成分分析)降維詳解一、什么是 PCAPCA(Principal Component Analysis,主成分分析)是一種常用的數據降維方法。它通過線性變換將原始的高維數據映射到低維空間,同時盡可能保留原數據的主要信息&#xf…

把 AI 裝進“冰箱貼”——基于超低功耗語音合成的小屏電子價簽

標簽:電子價簽、語音合成、TTS、超低功耗、電子墨水、BLE、離線語音 ---- 1. 背景:價簽也要開口說話? 超市做促銷,顧客拿價簽一掃,“今日番茄 2.99 元/斤,會員再享 9 折” 直接語音播放。 硬件限制&#xf…

挖漏洞是什么意思?挖漏洞賺錢入門到精通,收藏這篇就夠了!

挖漏洞是什么意思?挖漏洞賺錢入門到精通,收藏這篇就夠了! 什么是漏洞挖掘 漏洞挖掘是指通過分析軟件、系統或網絡中存在的安全漏洞來發現并利用這些漏洞。漏洞挖掘是信息安全領域的一項重要工作,可以幫助企業和組織提高系統的安…

如何理解AP中SM中宿主進程?

在AUTOSAR Adaptive Platform(AP)中,狀態管理(State Management, SM)的宿主進程(Host Process) 是實現狀態機運行的核心載體,其本質與運作機制可通過以下結構化解析深入理解&#xf…

無人機光電探測模塊技術分析

一、技術要點1. 多光譜成像技術 可見光與紅外融合:白天依賴可見光高分辨率成像(識別外形、顏色),夜間或低光照條件下切換至紅外熱成像(捕捉0.5℃級溫差),通過雙波段互補提升全天候能力。 激光…

第40周——GAN入門

目錄 目錄 目錄 前言 一、定義超參數 二、下載數據 三、配置數據 四、定義鑒別器 五、訓練模型并保存 總結 前言 🍨 本文為🔗365天深度學習訓練營中的學習記錄博客🍖 原作者:K同學啊 一、定義超參數 import argparse import os i…

Nginx性能優化與安全配置:打造高性能Web服務器

系列文章索引: 第一篇:《Nginx入門與安裝詳解:從零開始搭建高性能Web服務器》第二篇:《Nginx基礎配置詳解:nginx.conf核心配置與虛擬主機實戰》第三篇:《Nginx代理配置詳解:正向代理與反向代理…

二分算法(模板)

例題1: 704. 二分查找 - 力扣(LeetCode) 算法原理:(二分) 通過遍歷也可以通過,但是二分更優且數據量越大越能體現。 二分思路: 1.mid1 (left right)/2 與 mid2 right (right …

VUE3 學習筆記2 computed、watch、生命周期、hooks、其他組合式API

computed 計算屬性在vue3中,雖然也能寫vue2的computed,但還是更推薦使用vue3語法的computed。在Vue3中,計算屬性是組合式API,要想使用computed,需要先對computed進行引入:import { computed } from vuecomp…

【java面試day13】mysql-定位慢查詢

文章目錄問題💬 Question 1相關知識問題 💬 Question 1 Q:這條sql語句執行很慢,你如何分析呢? A:當一條 SQL 執行較慢時,可以先使用 EXPLAIN 查看執行計劃,通過 key 和 key_len 判…

3分鐘解鎖網頁“硬盤“能力:離線運行VSCode的新一代Web存儲技術

Hi,我是前端人類學(之前叫布蘭妮甜)! “這不是瀏覽器,這是裝了個硬盤。” —— 用戶對現代Web應用能力的驚嘆 隨著Origin Private File System和IndexedDB Stream等新技術的出現,Web應用現在可以在用戶的設…

LT6911GXD,HD-DVI2.1/DP1.4a/Type-C 轉 Dual-port MIPI/LVDS with Audio 帶音頻

簡介LT6911GXD是一款高性能HD-DVI2.1/DP1.4a/Type-c轉Dual-port MIPI/LVDS芯片,兼容 HDMI2.1、HDMI2.0b、HDMI1.4、DVI1.0、DisplayPort 1.4a、eDP1.4b 等多種視頻接口標準。支持4K(38402160)60Hz的DSC直通。應用場景AR/VR設備LT6911GXD 支持高達 4K(384…

【100頁PPT】數字化轉型某著名企業集團信息化頂層規劃方案(附下載方式)

篇幅所限,本文只提供部分資料內容,完整資料請看下面鏈接 https://download.csdn.net/download/2501_92808811/91662628 資料解讀:數字化轉型某著名企業集團信息化頂層規劃方案 詳細資料請看本解讀文章的最后內容 作為企業數字化轉型領域的…

高精度標準鋼卷尺優質廠家、選購建議

高精度標準鋼卷尺的優質廠家通常具備精湛工藝與權威精度認證等特征,能為產品質量提供保障。其選購需兼顧精度標識、使用場景、結構細節等多方面,具體介紹如下:一、高精度標準鋼卷尺優質廠家**1、河南普天同創:**PTTC-C5標準鋼卷尺…

38 C++ STL模板庫7-迭代器

C STL模板庫7-迭代器 文章目錄C STL模板庫7-迭代器一、迭代器的核心作用二、迭代器的五大分類與操作三、關鍵用法與代碼示例1. 迭代器的原理2. 迭代器用法與示例3. 迭代工具用法示例4. 使用技巧迭代器是C中連接容器與算法的通用接口,提供了一種訪問容器元素的統一方…

【0基礎3ds Max】學習計劃

3ds Max 作為一款功能強大的專業 3D 計算機圖形軟件,在影視動畫、游戲開發、建筑可視化、產品設計和工業設計等眾多領域有著廣泛的應用。 目錄前言一、第一階段:基礎認知(第 1 - 2 周)?二、第二階段:建模技術學習&…

用 Enigma Virtual Box 將 Qt 程序打包成單 exe

上一篇介紹了用windeployqt生成可運行的多文件程序,但一堆文件分發起來不夠方便。有沒有辦法將所有文件合并成一個 exe? 答案是肯定的 用Enigma Virtual Box工具就能實現。本文就來講解如何用它將 Qt 多文件程序打包為單一 exe,讓分發更輕松。 其中的 一定要選 第二個 一…

【LeetCode 熱題 100】45. 跳躍游戲 II

Problem: 45. 跳躍游戲 II 給定一個長度為 n 的 0 索引整數數組 nums。初始位置為 nums[0]。 每個元素 nums[i] 表示從索引 i 向后跳轉的最大長度。換句話說&#xff0c;如果你在索引 i 處&#xff0c;你可以跳轉到任意 (i j) 處&#xff1a; 0 < j < nums[i] 且 i j &…

池式管理之線程池

1.初識線程池問&#xff1a;線程池是什么&#xff1f;答&#xff1a;維持管理一定數量的線程的池式結構。&#xff08;維持&#xff1a;線程復用 。 管理&#xff1a;沒有收到任務的線程處于阻塞休眠狀態不參與cpu調度 。一定數量&#xff1a;數量太多的線程會給操作系統帶來線…