redis 系列4 數據結構之鏈表

来源:https://www.cnblogs.com/MrHSR/archive/2018/11/01/9887373.html
-Advertisement-
Play Games

一. 概述 鏈表提供了高效的節點重排能力,以及順序性的節點訪問方式,並且可能通過增刪節點來靈活地調整鏈表的長度。作為一種數據結構,在C語言中並沒有內置的這種數據結構。所以Redis構建了自己的鏈表實現。鏈表在Redis中應用非常多,比如列表鍵的底層實現之一就是鏈表,當一個列表鍵包含了數量比較多的元素 ...


一. 概述

  鏈表提供了高效的節點重排能力,以及順序性的節點訪問方式,並且可能通過增刪節點來靈活地調整鏈表的長度。作為一種數據結構,在C語言中並沒有內置的這種數據結構。所以Redis構建了自己的鏈表實現。鏈表在Redis中應用非常多,比如列表鍵的底層實現之一就是鏈表,當一個列表鍵包含了數量比較多的元素,又或者列表中包含的元素都是比較長的字元串時,Redis就會使用鏈表作為列表鍵的底層實現。

-- 例1:使用integers 列表鍵包含了從1到10,共有10個整數
127.0.0.1:6379> rpush integers "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
(integer) 10
127.0.0.1:6379> llen integers
(integer) 10
127.0.0.1:6379> lrange integers 0 5
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"

  integers列表鍵的底層實現就是一個鏈表。鏈表中的每個節點都保存了一個整數值,除了鏈表鍵之外,發佈與訂閱,慢查詢,監視器等功能也用到了鏈表。Redis伺服器本身還使用鏈表來保存多個客戶端的狀態信息,以及使用鏈表來構建客戶端輸出緩衝區(output buffer)。

 

二 鏈表和鏈表節點定義

// 每個鏈表節點使用一個adlist.h/listNode結構來表示:
      typedef struct listNode
        {
            //前置節點
            struct listNode *prev;
            //後置節點
            struct listNode *next;
            //節點的值
            void *value;
        }listNode; //別名

  多個listNode可能通過prev和next指針組成雙端鏈表。雖然使用多個listNode結構就可以組成鏈表,但使用adlist.h/list 來持有鏈表的話,操作起來會更方便。

 typedef struct list
        {
            //表頭節點
            listNode    *head;
            //表尾節點
             listNode *tail;
            //鏈表所包含的節點數量 
            unsigned long len;
            //節點值複製函數
            void *(*dup) (void *ptr);
            //節點值釋放函數
            void (*free)(void *ptr)
            //節點值對比函數
            int (*match) (void *ptr,void *key)
        }list; //別名

  在list結構中鏈表提供了表頭指針head, 表尾指針tail,以及鏈表長度計數器len, 而dup, free和match成員則是用於實現多態鏈表所需的類型特定函數:dup 函數用於複製鏈表節點所保存的值; free 函數用於釋放鏈表節點所保存的值; match 函數則用於對比鏈表節點所保存的值和另一個輸入值是否相等。

 

三.Redis的鏈表實現的特性總結

  (1)雙端: 鏈表節點帶有prev 和next 指針,獲取某個節點的前置節點和後置節點的複雜度都是0(1) 。

  (2)無環: 表頭節點的prev指針和表尾節點的next 指針都指向null ,對鏈表的訪問以null 為終點 。

  (3)帶表頭指針和表尾指針:通過list結構的head指針和tail 指針,程式獲取鏈接的表頭節點和表尾節點的複雜度為0(1)

  (4)帶鏈表長度計數器:程式使用list結構的len屬性來對list持有的鏈表節點進行計數,程式獲取鏈表中節點數量的複雜度為0(1)

  (5)多態:鏈表節點使用void* 指針來保存節點值,並且可能通過list結構的dup,free,match 三個屬性為節點值設置類型特定函數,所以鏈表可以用於保存各種不同類型的值。

 

四. 鏈表和鏈表節點的API

函數

作用

listSetDupMethod

將給定的函數設置為鏈表的節點值複製函數

listGetDupMethod

返回鏈表當前正在使用的節點值複製函數

listSetFreeMethod

將給定的函數設置為鏈表的節點值釋放函數

listGetFree

返回鏈表當前正在使用的節點值釋放函數

listSetMatchMethod

將給定的函數設置為鏈表的節點值對比函數

listGetMatchMethod

返回鏈表當前正在使用的節點值對比函數

listLenth

返回鏈表的長度(包含多少節點)

listFirst

返回鏈表的表頭節點

listLast

返回鏈表的表尾節點

listPrevNode

返回給定節點的前置節點

listNextNode

返回給定節點的後置節點

listNodeValue

返回給定節點目前正在保存的值

listCreate

創建一個不包含任何節點的新鏈表

listAddNodeHead

將一個包含給定值的新節點添加到給定鏈表的表頭

listAddNodeTail

將一個包含給定值的新節點添加到給定鏈表的表尾

listInsertNode

將一個包含給定值的新節點添加到給定節點的之前或者之後

listSearchKey

查找並返回鏈表中包含給定值的節點

listIndex

返回鏈表在給定索引上的節點

listDelNode

從鏈表中刪除給定節點

listRotate

將鏈表的表尾節點彈出,然後將被彈出的節點插入到鏈表的表頭,成為新的表頭節點

listDup

複製一個給定鏈表的副本

listRelease

釋放給定鏈表,以及鏈表中的所有節點

  總結:

    (1) 鏈表被廣泛用於實現Redis的各種功能,比如列表鍵,發佈與訂閱,慢查詢,監視器等。

    (2) 每個鏈表節點由一個listNode結構來表示,每個節點都有一個指定前置節點和後置節點的指針,所以Redis的鏈表實現是雙端鏈表。

    (3) 每個鏈表使用一個list結構來表示,這個結構帶有表頭節點指針 ,表尾節點指針,以及鏈表長度等信息。

    (4) 因為鏈表表頭節點的前置節點和表尾節點的後置節點都指向null, 所以Redis的鏈表實現是無環鏈表。

    (5) 通過為鏈表設置不同的類型特定函數,Redis的鏈表可以用於保存各種不同類型的值。


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

-Advertisement-
Play Games
更多相關文章
  • 伺服器 swap 交換分區製作 作用:‘提升‘ 記憶體的容量,防止OOM(Out Of Memory) 查看當前的交換分區 增加交換分區 可是是分區,LVM,File file創建: 1、新建一個專門的文件用於swap分區 註:此文件的大小是count的大小乘以bs大小,上面命令的大小是4GB 2、通 ...
  • linux的touch命令一般用來修改文件時間戳,或者新建一個不存在的文件。 一.命令格式: touch [參數]... 文件... 二.命令參數: |參數|描述| | | | | a | 或 time=atime或 time=access或 time=use 只更改存取時間。| | c | 或 n ...
  • 設計目的: 減少各種狀態值欄位; 減少資料庫冗餘和存儲空間; 增加狀態值時可靈活調整,無需增加額外欄位 ...
  • 前言 前面介紹了redis持久化和容災備份,這篇會介紹redis主從複製和redis持久化在主從複製中的一些應用。因為本人沒有那麼多伺服器或機器,所以這裡主要介紹下如何在docker容器中搭建主從複製以及搭建過程中遇到的一些問題。關於redis的深入講解,這邊博客《深入學習Redis(3):主從複製 ...
  • 似乎只要coding,這些代碼就要跟我過不去似的 今天在linux上安裝了mysql-server,想不到竟然被一個及其簡單的問題給難住了。 是的,我竟然無法登陸!!! 在論壇,百度,google上苦苦搜尋了半天,終於找到了問題所在。本質上還是自己資料庫學習的不夠扎實導致的問題。 廢話不多說,直接上 ...
  • mysql的出錯代碼表,根據mysql的頭文件mysql/include/mysqld_error.h整理而成 1005:創建表失敗 1006:創建資料庫失敗 1007:資料庫已存在,創建資料庫失敗 1008:資料庫不存在,刪除資料庫失敗 1009:不能刪除資料庫文件導致刪除資料庫失敗 1010:不 ...
  • 1、下載 https://dev.mysql.com/downloads/mysql/ 2、解壓到固定位置,如D:\MySQL\mysql 5.7.24 3、添加my.ini文件 跟bin同級 ··· [mysql] 設置mysql客戶端預設字元集 default character set=utf ...
  • map 結構 1. 語法:map(k1,v1,k2,v2,…) 1. 語法:map(k1,v1,k2,v2,…) 操作類型:map ,map類型的數據可以通過'列名['key']的方式訪問 案例: select deductions['Federal Taxes'],deductions['Stat ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...