Redis的五大數據類型的數據結構

来源:https://www.cnblogs.com/fhey/archive/2023/08/29/17666010.html
-Advertisement-
Play Games

概述 Redis底層有六種數據類型包括:簡單動態字元串、雙向鏈表、壓縮列表、哈希表、跳錶和整數數組。這六種數據結構五大數據類型關係如下: String:簡單動態字元串 List:雙向鏈表、壓縮列表 Hash:壓縮列表、哈希表 Sorted Set:壓縮列表、跳錶 Set:哈希表、整數數組 數據類型和 ...


概述

  Redis底層有六種數據類型包括:簡單動態字元串、雙向鏈表、壓縮列表、哈希表、跳錶和整數數組。這六種數據結構五大數據類型關係如下:

  • String:簡單動態字元串
  • List:雙向鏈表、壓縮列表
  • Hash:壓縮列表、哈希表
  • Sorted Set:壓縮列表、跳錶
  • Set:哈希表、整數數組

          數據類型和底層數據結構對應關係

 

  每種數據結構特性不一樣,操作時間也不一樣。

        數據結構的時間複雜度

 

二、數據結構

  從上述圖中可以知道,Redis的底層數據結構由簡單動態字元串、雙向鏈表、壓縮列表、哈希表、跳錶、整數數組組成,其中哈希表和整數數組基本上大家都很熟悉了,下麵重點介紹一下其餘的幾種數據結構。

1、簡單動態字元串(SDS)

  結構:alloc,len,buf

        簡單動態字元串結構

 

  buf:位元組數組,保存實際數據。為了表示位元組數組的結束,Redis 會自動在數組最後加一個“\0”,這就會額外占用 1 個位元組的開銷。

  len:占 4 個位元組,表示 buf 的已用長度。

  alloc:也占個 4 位元組,表示 buf 的實際分配長度,一般大於 len。

  那麼SDS與C字元串有什麼區別呢?區別主要有如下兩點:

  (1)獲取字元串長度時間複雜度為O(1)

  (2)在修改字元串時,會先檢查長度是否夠長,不夠會進行擴展,避免緩衝區溢出

 

2、鏈表

  Redis使用的是雙向無環鏈表,並且具有以下幾個特點:

  (1)雙端:鏈表具有前置節點和後置節點的引用,獲取這兩個節點時間複雜度都為O(1)。

  (2)無環:表頭節點的 prev 指針和表尾節點的 next 指針都指向 NULL,對鏈表的訪問都是以 NULL 結束。

  (3)帶鏈表長度計數器:通過 len 屬性獲取鏈表長度的時間複雜度為 O(1)。

  (4)多態:鏈表節點使用 void* 指針來保存節點值,可以保存各種不同類型的值。

 

3、壓縮列表

  壓縮列表(ziplist)是Redis為了節省記憶體而開發的,是由一系列特殊編碼的連續記憶體塊組成的順序型數據結構,一個壓縮列表可以包含任意多個節點(entry),每個節點可以保存一個位元組數組或者一個整數值。壓縮列表並不是對數據利用某種演算法進行壓縮,而是將數據按照一定規則編碼在一塊連續的記憶體區域,目的是節省記憶體。

壓縮列表實際上類似於一個數組,數組中的每一個元素都對應保存一個數據。和數組不同的是,壓縮列表在表頭有三個欄位 zlbytes、zltail 和 zllen,分別表示列表長度、列表尾的偏移量和列表中的 entry 個數;壓縮列表在表尾還有一個 zlend,表示列表結束;

我們要查找定位第一個元素和最後一個元素,可以通過表頭三個欄位的長度直接定位,複雜度是 O(1)。而查找其他元素時,就沒有這麼高效了,只能逐個查找,此時的複雜度就是 O(N) 了。

          壓縮表的查找過程

 

 

4、跳錶

  跳錶在鏈表的基礎上,增加了多級索引,通過索引位置的幾個跳轉,實現數據的快速定位,時間複雜度為O(logN),比起鏈表,跳錶的查詢效率大大提高到了 O(logn)。

        跳錶查找過程

 

三、Redis數據類型的基本數據結構

1、String(字元串)

  1.1 String的內部結構

  redis沒有直接使用C語言中的字元串表示,而是自己構建了一個字元串,名為 “簡單動態字元串” (simple dynamic string , SDS)。其中,C語言中的字元串只是作為字元串面量(通常在無須對字元串值進行修改的地方使用)。

 

  String在結構上的實現類似於Java中的ArrayList(預設構造一個大小為10的初始數組),這是冗餘分配記憶體的思想,也稱為預分配;這種思想可以減少擴容帶來的性能消耗。

              String的內部結構

 

1.2 String使用的數據編碼

  存儲數字的話,採用int類型的編碼,如果是非數字的話,採用 raw 編碼;

 

1.3 使用場景

  (1) 簡單字元緩存

  (2) 分散式鎖

  (3)計數功能——》計數服務

 

2、List(列表)

2.1 List的內部結構

  Redis的列表相當於Java語言中的LinkedList,它是一個雙向鏈表數據結構(但是這個結構設計比較巧妙,後面會介紹),支持前後順序遍歷。鏈表結構插入和刪除操作快,時間複雜度O(1),查詢慢,時間複雜度O(n)。

                List的內部結構

 

2.2 List使用的數據編碼

  字元串長度及元素個數小於一定範圍使用 ziplist 編碼,任意條件不滿足,則轉化為 linkedlist 編碼。

 

2.3 使用場景

  (1)利用List實現棧、隊列

  (2)redis做消息隊列(不推薦使用redis做消息隊列)

  (3)列表緩存

 

3、Hash(字典)

3.1 Hash的內部結構

  Redis的hash(字典)相當於Java語言中的HashMap,它是根據散列值分佈的無序字典,內部的元素是通過鍵值對的方式存儲。

  hash(字典)的實現與Java中的HashMap(JDK1.7)的結構也是一致的,它的數據結構也是數組+鏈表組成的二維結構,節點元素散列在數組上,如果發生hash碰撞則使用鏈表串聯在數組節點上。

        Hash的內部結構

 

3.2 Hash使用的數據編碼

  hash 對象保存的鍵值對內的鍵和值字元串長度小於一定值及鍵值對。

 

3.3 使用場景

  (1) 存儲對象

 

4、Set(集合)

4.1 Set的內部結構

  Redis的set(集合)相當於Java語言里的HashSet,它內部的鍵值對是無序的、唯一的。它的內部實現了一個所有value為null的特殊字典。
集合中的最後一個元素被移除之後,數據結構被自動刪除,記憶體被回收。

        Set的內部結構

 

4.2 Set使用的數據編碼

  保存元素為整數及元素個數小於一定範圍使用 intset 編碼,任意條件不滿足,則使用 hashtable 編碼。

 

4.3 使用場景

  (1)標簽,社交,查詢有共同興趣愛好的人,智能推薦

  (2)抽獎

  (3)朋友圈點贊

 

5、Zset(有序集合)

5.1 Zset的內部結構

  zset(有序集合)是Redis中最常問的數據結構。它類似於Java語言中的SortedSet和HashMap的結合體,它一方面通過set來保證內部value值的唯一性,另一方面通過value的score(權重)來進行排序。這個排序的功能是通過Skip List(跳躍列表)來實現的。zset(有序集合)的最後一個元素value被移除後,數據結構被自動刪除,記憶體被回收。

        Zset的內部結構

 

5.2 Zset使用的數據編碼

  zset 對象中保存的元素個數小於及成員長度小於一定值使用 ziplist 編碼,任意條件不滿足,則使用 skiplist 編碼。

 

5.3 使用場景

  (1)排名場景


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

-Advertisement-
Play Games
更多相關文章
  • 通過這個示例,你將更深入地瞭解如何在實際業務中應用Flutter,以及如何運用不同的解決方案和技術來構建高效、穩定的應用。 ...
  • # el-autocomplete核心參數 可以實現非同步的數據拉取,從非同步返回的數據中,選擇需要的結果,並回顯到文本框中。 ## fetch-suggestions 回調列表,非同步的方式獲取數據列表,顯示在列表框中 ## @select 當選中某一項時,會觸發這個方法,將數據獲取到,這時,我們可以將 ...
  • # 核心原理 長鏈接轉為短鏈接的核心原理是: 將短鏈接與原始長鏈接做一個映射,訪問短鏈接的時候,通過重定向的方式轉到長鏈接。 # 應用場景 比如分享功能,查看分享信息的原始鏈接通常是很長的,直接發給用戶,體驗不是很好,這時候就可以將其映射為一個短鏈接再發給用戶。 又比如我們熟知的百度網盤分享文件,雖 ...
  • ##一、定義 **講一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建造者模式是一種創建型模式。** ##二、描述 **包含以下四個角色:** ![](https://img2023.cnblogs.com/blog/1780813/202305/1780813-202305 ...
  • 你想成為一名架構師,對嗎?別對我撒謊,我知道你想成為架構師。即使你不想,你還是想成為一名更好的開發者。否則,你就不會花時間閱讀這篇文章。 這種態度值得贊賞。畢竟,我們都希望在自己所從事的領域變得更好,即使不能稱為最好。我在這裡就是為了幫助你實現這一目標。 那麼,你如何成為一名架構師呢?當然是通過學習 ...
  • #### 本文為[李你幹嘛](https://www.cnblogs.com/liniganma)原創,轉載請註明出處:[Pybind11綁定C++抽象類(DLL介面)](https://www.cnblogs.com/liniganma/p/17666063.html) # 摘要 假設我們將DLL ...
  • 數據類型是編程中的重要概念。數據類型指定了變數值的大小和類型。 Go是靜態類型的,這意味著一旦變數類型被定義,它只能存儲該類型的數據。 Go有三種基本數據類型: - bool:表示布爾值,要麼是true,要麼是false。 - 數值型:表示整數類型、浮點數值和複數類型。 - string:表示字元串 ...
  • ### Java 8 的改進 - 速度更快 - 代碼更少(**Lambda表達式**) - 引入強大的**Stream API** - 便於並行 - 最大化減少空指針異常(**Optional**) - **Nashorn**引擎,允許在JVM上運行**js**應用 - **並行流**就是把一個內容 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...