redis 系列8 數據結構之整數集合

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

一.概述 整數集合(intset)是集合鍵的底層實現之一, 當一個集合只包含整數值元素,並且這個集合元素數量不多時, Redis就會使用整數集合作為集合鍵的底層實現。下麵創建一個只包含5個元素的集合鍵,並且集合中所有元素都是整數值,那麼這個集合鍵的底層實現就會是整數集合。 接著添加非整數值,集合鍵的 ...


一.概述

  整數集合(intset)是集合鍵的底層實現之一, 當一個集合只包含整數值元素,並且這個集合元素數量不多時, Redis就會使用整數集合作為集合鍵的底層實現。下麵創建一個只包含5個元素的集合鍵,並且集合中所有元素都是整數值,那麼這個集合鍵的底層實現就會是整數集合。 接著添加非整數值,集合鍵的底層實現就會是hashtable。

127.0.0.1:6379> sadd numbers 1 3 5 7 9 
(integer) 5
127.0.0.1:6379> object encoding numbers
"intset"
127.0.0.1:6379> sadd numbers 'one'
(integer) 1
127.0.0.1:6379> object encoding numbers
"hashtable"

 

二. 整數集合實現

  整數集合是Redis用於保存整數值的集合抽象數據結構,它可以保存類型為int16_t, int32_t, int64_t的整數值,並且保證集合中不會出現重覆元素。數據集合定義如下:

// 每個intset.h/intset結構表示一個整數集合
           typedef struct intset
        {
            //編碼方式
            uint32_t encoding;
            //集合包含的元素數量
             uint32_t  length;
            //保存元素的數組
             int8_t contents[];
        }intset;

  (1) contents數組是整數集合的底層實現,整數集合的每個元素都是contents數組的一個數組項(item),各個項在數組中按值從小到大有序排列,並且數組中不包含重覆項。如下麵腳本:

127.0.0.1:6379> sadd record 5 3 4 5 6 0
(integer) 5
127.0.0.1:6379> smembers record
1) "0"
2) "3"
3) "4"
4) "5"
5) "6"

  (2) length屬性記錄了整數集合包含的元素數量,也即是contents數組的長度。雖然contents屬性聲明為int8_t類型的數組,但實現上contents數組並不保存任何int8_t類型的值,contents數組的真正類型取決於encoding屬性的值。

  a. 如果encoding 屬性的值為intset_enc_int16,那麼contents就是一個int16_t類型的數組,數組裡的每個項都是一個int16_t類型的整數值(範圍在 -32768 ~ 32767)。如下圖encoding屬性的值有5個整數型,根據這些整數值得出encoding為int16_t類型。

  b. 如果encoding屬性的值為intset_enc_int32, 那麼數組裡每個項就是一個int32_t類型的整數值(範圍在 -2147483648 ~ 2147483647)。還有encoding屬性的值為intset_enc_int64類型的,數組裡每個項取取值範圍更大。

  需要註意的是:假設contents數組保存的值為2147483647, 1,2,3 四個整數值。 但只有第一個整數值需要用int32_t類型來保存,而其它三個值可以用int16_t類型來保存。不過根據整數集合的升級規則,當一個底層的int16_t數組的整數集合添加一個int64_t類型的整數值時,整數集合中所有元素都會被轉換成int64_t類型。 所以contents數組保存的整數值都是int64_t類型的。

 

三. 升級

   當我們要將一個新元素添加到整數集合裡面,並且新元素的類型比整數集合現有所有元素的類型都要長時,整數集合需要先進行升級,然後才能將新元素添加到整數集合中。假設:集合中包含三個int16_t類型的元素,值分別是1,2,3 。因為每個元素都占用16位空間,所以整數集合底層數組的大小 為3 * 16 =48位。現將int32_t的數值65535添加進去,這裡程式需要對整數集合進行升級。

  升級整數集合併添加新元素共分三步進行:

    (1) 根據新元素的類型,擴展整數集合底層數組的空間大小 ,併為新元素分配空間。分配空間後,現在整數集合4個元素的底層數組大小為4 *32 =128位, 此時前三位還是48位空間,如下圖所示:

    (2) 將底層數組現有的所有元素都轉換成與新元素相同的類型(需要從int16_t 轉成int32_t所需的空間) ,轉換後元素位置有序不變,如下圖所示:

    (3) 將新元素添加到底層數組裡面,如下圖所示:

四. 升級的好處

  4.1 提升靈活性

    為了避免類型錯誤,通常不會將兩種不同類型的值放在同一個數據結構裡面,通過升級處理可以隨意地將int16_t, int32_t, , int64_t 類型的整數添加到集合中,而不必擔心出現類型錯誤。

       4.2 節約記憶體

    要讓一個數組可以同時保存int16_t,int32_t, , int64_t三種類型的值,最簡單的做法就是直接使用int64_t類型的數組作為整數集合的底層實現,不過這樣浪費記憶體空間。

 

五.   降級

  整數集合不支持降級操作,一旦對數組進行了升級,編碼就會一直保持升級後的狀態。即使集合里只有一個需要使用int64_t類型的元素被刪除了,整數集合的編碼仍然會維持intset_enc_int64, 底層數組也仍然會是int64_t類型,如下圖所示:

 

六. 整數集合API

函數

作用

intsetNew

創建一個新的壓縮列表

intsetAdd

將給定元素添加到整數集合裡面

intsetRemove

從整數集合中移除給定元素

intsetFind

檢查給定值是否存在於集合

intsetRandom

從整數集合中隨機返回一個元素

intsetGet

取出底層數組在給定索引上的元素

intsetLen

返回整數集合包含的元素個數

intsetBloblen

返回整數集合占用的記憶體位元組數

  


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

-Advertisement-
Play Games
更多相關文章
  • 這個寫的比較簡單,先做以下記錄 centos虛擬機安裝到別的電腦上,因為linux中的程式需要向外有網路互通,所以需要重新設置ip 通過 ifconfig eth4 192.168.0.20 broadcast 192.168.0.1 :broadcast 參數可以不填,這樣就設置好了ip 但是一個 ...
  • 1. CFS進程入隊和出隊 完全公平調度器CFS中有兩個函數可用來增刪隊列的成員: 和`dequeue_task_fair`分別用來向CFS就緒隊列中添加或者刪除進程 2 enqueue_task_fair入隊操作 2.1 enque_task_fair函數 向就緒隊列中放置新進程的工作由函數 函數 ...
  • 1 虛擬運行時間(今日內容提醒) 1.1 虛擬運行時間的引入 CFS為了實現公平,必須懲罰當前正在運行的進程,以使那些正在等待的進程下次被調度。 具體實現時,CFS通過每個進程的虛擬運行時間(vruntime)來衡量哪個進程最值得被調度。 CFS中的就緒隊列是一棵以vruntime為鍵值的紅黑樹,虛 ...
  • 有一段時間沒有寫學習心得了;現在開始加油,再接再勵。 從最基礎的開始 1.安裝centOS7.3之後設置IP地址。一般linux的系統都是作為伺服器的系統來使用,伺服器的屬性註定了他的IP不能隨意的更變,所以需要設置一個固定的IP地址。 一般centos系統安裝完成後,IP都是通過dhcp來獲得的。 ...
  • LVM邏輯捲管理器 為什麼要使用邏輯捲? 邏輯捲管理器是Linux系統用於對硬碟分區進行管理的一種機制,為瞭解決硬碟設備在創建分區後不易修改分區大小的缺陷。儘管對傳統的硬碟分區進行強制擴容或縮容從理論上講是可行的。但是卻可能造成數據的丟失。LVM技術是在硬碟分區和文件系統之間添加了一個邏輯層,它提供 ...
  • whereis命令用於查找文件。 該指令會在特定目錄中查找符合條件的文件。這些文件應屬於原始代碼、二進位文件,或是幫助文件。 該指令只能用於查找二進位文件、源代碼文件和man手冊頁,一般文件的定位需使用locate命令。 一.命令格式: whereis [ bfmsu][ B ...][ M ... ...
  • 一、命令介紹 mkdir 命令用於創建空白目錄格式為“mkdir [選項] 目錄”, 除了能夠創建單個空白目錄,還能結合 -p 參數來遞歸創建具有嵌套層疊關係的文件目錄。 二、實例 使用mkdir命令在當前目錄創建一個名為new的文件目錄 執行 mkdir new 可以看到文件目錄 new 已經創建 ...
  • 任務二 表數據的插入、修改及刪除 @[toc] | 班級 | 姓名 | | | | |軟體工程16 9班 | 洪燕妮| 【實訓目的與要求】 1、利用MySQL命令行視窗進行增、刪、改數據操作; 2、利用界面工具進行增、刪、改數據操作。 【實訓原理】 MySQL的增、刪、改數據操作命令。 【實訓步驟】 ...
一周排行
    -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# ...