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
  • 移動開發(一):使用.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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...