Redis對象類型

来源:https://www.cnblogs.com/winterfells/archive/2018/06/07/9152028.html
-Advertisement-
Play Games

Redis對象類型 Redis基於基礎的數據結構創建的對象: 字元串對象、 列表對象、 哈希對象、 集合對象 有序集合對象。 對象回收:Redis對象系統實現了基於引用計數技術的記憶體回收機制,當程式不再使用某個對象的時候,這個對象所占用的記憶體就會被自動釋放;Redis通過引用計數技術實現了對象共用機 ...


Redis對象類型

Redis基於基礎的數據結構創建的對象:

  • 字元串對象、
  • 列表對象、
  • 哈希對象、
  • 集合對象
  • 有序集合對象。

 

對象回收:Redis對象系統實現了基於引用計數技術的記憶體回收機制,當程式不再使用某個對象的時候,這個對象所占用的記憶體就會被自動釋放;Redis通過引用計數技術實現了對象共用機制,在適當的條件下通過讓多個資料庫鍵共用同一個記憶體對象來節約記憶體;

 

一、RedisObject

在server.h文件中,給出了RedisObject的結構體定義:

typedef struct redisObject {
    unsigned type:4;//類型
    unsigned encoding:4;//編碼
    unsigned lru:LRU_BITS; //訪問時間lru
    int refcount;// 引用計數refcount
    void *ptr;//指向底層實現數據結構的指針
} robj;
  • 類型type:

Redis的對象有五種類型,分別是string、hash、list、set和zset,type屬性就是用來標識著五種數據類型。type占用4個bit位,其取值和類型對應如下:

#define OBJ_STRING 0
#define OBJ_LIST 1
#define OBJ_SET 2
#define OBJ_ZSET 3
#define OBJ_HASH 4
  • 編碼類型encoding:

Redis對象的編碼方式由encoding參數指定,也就是表示ptr指向的數據以何種數據結構作為底層實現。該欄位也占用4個bit位。其取值和對應類型對應如下:

#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */

上述這幾種編碼類型與其底層實現如下表:

編碼類型 底層實現
OBJ_ENCODING_RAW 簡單動態字元串sds
OBJ_ENCODING_INT long類型的整數
OBJ_ENCODING_HT 字典dict
OBJ_ENCODING_LINKEDLIST 雙端隊列sdlist
OBJ_ENCODING_ZIPLIST 壓縮列表ziplist
OBJ_ENCODING_INTSET 整數集合intset
OBJ_ENCODING_SKIPLIST 跳躍表skiplist和字典dict
OBJ_ENCODING_EMBSTR EMBSTR編碼的簡單動態字元串sds
OBJ_ENCODING_QUICKLIST 由雙端鏈表和壓縮列表構成的快速列表

 

 

 

 

 

 

 

 

Redis的每一種對象類型可以對應不同的編碼方式,這就極大地提升了Redis的靈活性和效率。Redis可以根據不同的使用場景,來選擇合適的編碼方式,五種對象類型對應的底層編碼方式如下表所示:

對象類型 編碼方式

OBJ_STRING

字元串類型

OBJ_ENCODING_RAW ,OBJ_ENCODING_INT ,OBJ_ENCODING_EMBSTR

簡單動態字元串sds;long類型的整數;EMBSTR編碼的簡單動態字元串sds

OBJ_LIST

列表類型

OBJ_ENCODING_LINKEDLIST ,OBJ_ENCODING_ZIPLIST ,OBJ_ENCODING_QUICKLIST

雙端隊列sdlist;壓縮列表ziplist;由雙端鏈表和壓縮列表構成的快速列表

OBJ_SET

集合類型

OBJ_ENCODING_INTSET ,OBJ_ENCODING_HT

整數集合intset、字典dict

OBJ_ZSET

有序集合類型

OBJ_ENCODING_ZIPLIST ,OBJ_ENCODING_SKIPLIST

壓縮列表ziplist、跳躍表skiplist和字典dict

OBJ_HASH

哈希類型

OBJ_ENCODING_ZIPLIST ,OBJ_ENCODING_HT

壓縮列表ziplist、字典dict

 

 

 

 

 

 

 

 

 

 

 

  • 訪問時間lru

lru表示該對象最後一次被訪問的時間,其占用24個bit位。保存該值的目的是為了計算該對象的空轉時長,便於後續根據空轉時長來決定是否釋放該鍵,回收記憶體。鍵的空轉時長還有另外一項作用:如果伺服器打開了maxmemory選項,並且伺服器用於回收記憶體的演算法為volatile-lru或者allkeys-lru,那麼當伺服器占用的記憶體數超過了maxmemory選項所設置的上限值時,空轉時長較高的那部分鍵會優先被伺服器釋放,從而回收記憶體。

  • 引用計數refcount

C語言不具備自動記憶體回收機制,所以Redis對每一個對象設定了引用計數refcount欄位,程式通過該欄位的信息,在適當的時候自動釋放記憶體進行記憶體回收。此功能與C++的智能指針相似。

  1. 當創建一個對象時,其引用計數初始化為1;
  2. 當這個對象被一個新程式使用時,其引用計數加1;
  3. 當這個對象不再被一個程式使用時,其引用計數減1;
  4. 當引用計數為0時,釋放該對象,回收記憶體。

 

二、t_String 字元串類型

字元串是Redis中最為常見的數據存儲類型,其底層實現是簡單動態字元串sds,因此,該字元串類型是二進位安全的,這就意味著它可以接受任何格式的數據。另外,Redis規定,字元串類型最多可以容納的數據長度為512M。Redis提供了下列函數,來檢測字元串鍵的大小。

static int checkStringLength(client *c, long long size) {
    // 超出了512M,就直接報錯
    if (size > 512*1024*1024) {
        addReplyError(c,"string exceeds maximum allowed size (512MB)");
        return C_ERR;
    }
    return C_OK;
}

字元串對象的編碼可以是int、raw或者embstr。

  • 如果一個字元串對象保存的是整數值,並且這個整數值可以用long類型來表示,那麼字元串對象會將整數值保存在字元串對象結構的ptr屬性裡面(將void*轉換成long),並將字元串對象的編碼設置為int。

  •  如果字元串對象保存的是一個字元串值,並且這個字元串值的長度大於32位元組,那麼字元串對象將使用一個簡單動態字元串(SDS)來保存這個字元串值,並將對象的編碼設置為raw。

 

  • 如果字元串對象保存的是一個字元串值,並且這個字元串值的長度小於等於32位元組,那麼字元串對象將使用embstr編碼的方式來保存這個字元串值。embstr編碼是專門用於保存短字元串的一種優化編碼方式,embstr編碼則通過調用一次記憶體分配函數來分配一塊連續的空間,空間中依次包含redisObject和sdshdr兩個結構。

 

三、t_list 列表對象類型

 

當列表對象可以同時滿足以下兩個條件時,列表對象使用ziplist編碼:

  • 列表對象保存的所有字元串元素的長度都小於64位元組;
  • 列表對象保存的元素數量小於512個;

不能滿足這兩個條件的列表對象需要使用linkedlist編碼。

以上兩個條件的上限值是可以修改的,配置文件中關於list-max-ziplist-value選項和list-max-ziplist-entries

  • ziplist編碼的列表對象使用壓縮列表作為底層實現,每個壓縮列表節點(entry)保存了一個列表元素。

 

  • 另一方面,linkedlist編碼的列表對象使用雙端鏈表作為底層實現,每個雙端鏈表節點(node)都保存了一個字元串對象,而每個字元串對象都保存了一個列表元素。

 

四、t_hash 哈希對象類型

 當哈希對象可以同時滿足以下兩個條件時,哈希對象使用ziplist編碼:

  1. 哈希對象保存的所有鍵值對的鍵和值的字元串長度都小於64位元組;
  2. 哈希對象保存的鍵值對數量小於512個;

不能滿足這兩個條件的哈希對象需要使用hashtable編碼。

這兩個條件的上限值是可以修改的,配置文件中關於hash-max-ziplist-value選項和hash-max-ziplist-entrie

 

  • ziplist編碼的哈希對象使用壓縮列表作為底層實現

每當有新的鍵值對要加入到哈希對象時,程式會先將保存了鍵的壓縮列表節點推入到壓縮列表表尾,然後再將保存了值的壓縮列表節點推入到壓縮列表表尾,因此:

  1. 保存了同一鍵值對的兩個節點總是緊挨在一起,保存鍵的節點在前,保存值的節點在後;
  2. 先添加到哈希對象中的鍵值對會被放在壓縮列表的表頭方向,而後來添加到哈希對象中的鍵值對會被放在壓縮列表的表尾方向。

  •  hashtable編碼的哈希對象使用字典作為底層實現
  1. 字典的每個鍵都是一個字元串對象,對象中保存了鍵值對的鍵;
  2. 字典的每個值都是一個字元串對象,對象中保存了鍵值對的值。

 

 

 

五、t_set 集合對象類型

集合對象的編碼可以是intset或者hashtable。

當集合對象可以同時滿足以下兩個條件時,對象使用intset編碼:

  1. 集合對象保存的所有元素都是整數值;
  2. 集合對象保存的元素數量不超過512個。

不能滿足這兩個條件的集合對象需要使用hashtable編碼。第二個條件的上限值是可以修改的,配置文件中關於set-max-intset-entries選項的說明

  • intset編碼的集合對象使用整數集合作為底層實現,集合對象包含的所有元素都被保存在整數集合裡面。

  • 另一方面,hashtable編碼的集合對象使用字典作為底層實現,字典的每個鍵都是一個字元串對象,每個字元串對象包含了一個集合元素,而字典的值則全部被設置為NULL。

 

六、t_zset 集合對象類型

  • ziplist編碼的壓縮列表對象使用壓縮列表作為底層實現,每個集合元素使用兩個緊挨在一起的壓縮列表節點來保存,第一個節點保存元素的成員(member),而第二個元素則保存元素的分值(score)。

  壓縮列表內的集合元素按分值從小到大進行排序,分值較小的元素被放置在靠近表頭的方向,而分值較大的元素則被放置在靠近表尾的方向。

 

  •  zset結構中的zsl跳躍表

         zsl跳躍表按分值從小到大保存了所有集合元素,每個跳躍表節點都保存了一個集合元素。每個跳躍表節點都保存了一個集合元素:跳躍表節點的object屬性保存了元素的成員,而跳躍表節點的score屬性則保存了元素的分值。通過這個跳躍表,程式可以對有序集合進行範圍型操作。

   除此之外,zset結構中的dict字典為有序集合創建了一個從成員到分值的映射,字典中的每個鍵值對都保存了一個集合元素:字典的鍵保存了元素的成員,而字典的值則保存了元素的分值。通過這個字典,程式可以用O(1)複雜度查找給定成員的分值,ZSCORE命令就是根據這一特性實現的,而很多其他有序集合命令都在實現的內部用到了這一特性。

  在理論上,有序集合可以單獨使用字典或者跳躍表的其中一種數據結構來實現,但無論單獨使用字典還是跳躍表,在性能上對比起同時使用字典和跳躍表都會有所降低。舉個例子,如果我們只使用字典來實現有序集合,那麼雖然以O(1)複雜度查找成員的分值這一特性會被保留,但是,因為字典以無序的方式來保存集合元素,所以每次在執行範圍型操作——比如ZRANK、ZRANGE等命令時,程式都需要對字典保存的所有元素進行排序,完成這種排序需要至少O(NlogN)時間複雜度,以及額外的O(N)記憶體空間(因為要創建一個數組來保存排序後的元素)。

         另一方面,如果我們只使用跳躍表來實現有序集合,那麼跳躍表執行範圍型操作的所有優點都會被保留,但因為沒有了字典,所以根據成員查找分值這一操作的複雜度將從O(1)上升為O(logN)。因為以上原因,為了讓有序集合的查找和範圍型操作都儘可能快地執行,Redis選擇了同時使用字典和跳躍表兩種數據結構來實現有序集合。

 

七、類型檢查與命令多態 

Redis中用於操作鍵的命令基本上可以分為兩種類型。

  • 其中一種命令可以對任何類型的鍵執行,比如說DEL命令、EXPIRE命令、RENAME命令、TYPE命令、OBJECT命令等;
  • 而另一種命令只能對特定類型的鍵執行,比如說:

  ❑SET、GET、APPEND、STRLEN等命令只能對字元串鍵執行;

  ❑HDEL、HSET、HGET、HLEN等命令只能對哈希鍵執行;

  ❑RPUSH、LPOP、LINSERT、LLEN等命令只能對列表鍵執行;

  ❑SADD、SPOP、SINTER、SCARD等命令只能對集合鍵執行;

  ❑ZADD、ZCARD、ZRANK、ZSCORE等命令只能對有序集合鍵執行;

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Win xp重置 編輯 要為 Windows XP 重置 Winsock,請按照下列步驟操作: 1.單擊“開始”,運行中輸入cmd。 2.然後輸入命令 netsh winsock reset。 3.重啟電腦。 Win7重置 編輯 要為 Windows 7 重置 Winsock,請按照下列步驟操作: ...
  • vim按d表示剪切按dd剪切一行vim命令:命令模式 /關鍵字 n繼續向下查找 vim的多行註釋:1.按ctrl + v進入 visual block模式2.按上下選中要註釋的行3.按大寫字母I,再插入註釋符,例如//4.按兩下esc5.按ctrl + v進入 visual block模式,按箭頭選 ...
  • ELK:Elasticsearch Logstash Kibana Elasticsearch:是基於JSON的分散式搜索和分析引擎,專為實現水平擴展、高可用和管理便捷性而設計 Logstash:是動態數據收集管道,擁有可擴展的插件生態系統 Kibana:能夠已圖形化呈現數據,並且具有可擴展的用戶界 ...
  • 1.yum install epel-release(安裝epel(Extra Packages for Enterprise Linux)) 2.yum repolist(確保epel添加到yum的源裡邊,如果沒有刪除epel-release重新安裝) 3.yum install nginx(安裝 ...
  • Shell編程之條件語句 學習目標: 掌握shell腳本條件測試 掌握if語句編程 目錄結構: 條件測試 條件測試概述 l 對特定的條件進行判斷,以決定如何執行操作 l 測試的方法 方法1:test 條件表達式 方法2:【條件表達式】 l 當條件成立時,測試語句的返回值為0,否則為其他數值 條件測試 ...
  • 一、現象描述 今天在調試兩台物理機,做完配置重啟主機後,發現一臺伺服器網路無法ssh連接,通過ILO進去ifconfig發現eth0配置的IP地址等信息丟失,手動重啟後,可以ssh連接,但過一段時間,ssh又再次登錄失敗,ifconfig eth0的相關信息也丟失。 二、錯誤原因 centos 6. ...
  • 深圳銳科光電科技有限公司的DALI色溫模塊符合IEC62386-102和IEC62386-207(LED模塊)和IEC62386-209(色溫)標準,同時支持DT6(LED模塊)和DT8(顏色控制-色溫)協議。採用了原裝進口ST單片機晶元,完美相容TRIDONIC(銳高)、OSRAM(歐司朗)、PH... ...
  • druid為各種場景提供了豐富的查詢類型。 查詢由各種JSON屬性組合而成,不同類型的查詢,JSON屬性不同,下麵主要介紹常用的查詢類型。 1. Components Datasources 一個數據源等價於druid表。此外,一個查詢也可以作為數據源,提供類似於子查詢的功能。查詢數據源目前只支持G ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...