検索
ホームページデータベースRedisRedis 研究ノート - リストの原則

#基本関数のリスト

##説明#BLPOP key1、key2、... タイムアウト##移動して入手##LPUSHX キーの値##LRANGE キー srart stop##

グラフの出典: https://www.cnblogs.com/amyzhu/p/13466311.html

単一リンク リスト

Redis のリストの実装を学ぶ前に、まず単一リンク リストの実装方法を見てみましょう:

それぞれのノードには、次のノードを指す後方ポインタ (参照) があり、最後のノードは終了を示す NULL を指し、開始を示す最初のノードを指す Head (ヘッド) ポインタがあります。

Redis 研究ノート - リストの原則

これと同様ですが、新規作成と削除には O(1) のみが必要です。 ですが、検索には O(n) 時間がかかります。逆検索はできないため、検索を開始する必要があります。見逃したら最初から。

ノードを追加します:

Redis 研究ノート - リストの原則

#ノードの削除:

Redis 研究ノート - リストの原則

##二重リンク リスト


二重リンク リスト (二重リンク リストとも呼ばれる) はリンク リストの一種であり、その各データ ノードには 2 つのポインタがあり、それぞれ直接後続ノードと直接先行ノードを指します。したがって、二重リンク リスト内の任意のノードから開始して、その先行ノードおよび後続ノードに簡単にアクセスできます。

Redis 研究ノート - リストの原則

機能:


  1. 挿入または削除するたびに特定のノードが選択された場合、2 つではなく 4 つのノード参照を処理する必要があるため、一方向リンク リストと比較すると実装が難しくなります。 , 必然的にメモリを占有します スペースが大きくなります。

  2. #最初から最後までトラバースでき、最後から最初までトラバースできます

  3. ##これにより、redis が前後の両方を横断できるという問題が解決されるようです。
  4. 次に、

redis のリンク リスト

がどのように処理されるかを見てみましょう:

構造定義のソース コードを見てみましょう

ListNode:

typedef struct listNode
{
    // 前驱节点
    struct listNode *prev;
    // 后继节点
    struct listNode *next;
    // 节点的值
    void *value;
} listNode;

List:

typedef struct listNode
{
    // 表头节点
    listNode *head;
    // 表尾节点
    listNode *tail;
    // 链表所包含的节点数量
    unsigned long len;
    // 节点值复制函数
    void *(*dup)(void *ptr);
    // 节点值释放函数
    void *(*free)(void *ptr);
    // 节点值对比函数
    int (*match)(void *ptr,void *key)
} list;

redis リンク リストの特徴:

  • 双方向非巡回: リンク リスト ノードには、ノードのノードを取得するための先行ポインタと後続ポインタがあります。先行ノードと後続ノードの時間計算量はO(1)であり、先頭ノードの先行ポインタと末尾ノードの後続ポインタはともにNULLを指し、連結リストへのアクセスはNULLで終了する。

  • Length カウンタ: List 構造体の len 属性を通じてノード数を取得する時間計算量は O(1) です。

list には依然として不連続なメモリ割り当てとメモリの断片化の問題があるため、メモリを最適化する方法はあるでしょうか?

redis 圧縮リスト

ZipList は基本的なデータ構造ではなく、Redis 自体によって設計されたデータ ストレージ構造です。これは配列に似ており、連続したメモリ空間を通じてデータを保存します。

配列とは異なり、格納されたリスト要素が異なるメモリ空間を占有することができます。圧縮という言葉に関しては、誰もが最初にメモリの節約を思い浮かべるかもしれません。このストレージ構造がメモリを節約する理由は、それが配列と比較されるためです。

配列では各要素の記憶領域が同じサイズである必要があることは誰もが知っていますが、異なる長さの文字列を格納したい場合は、その文字列が占有している記憶領域を使用する必要があります。文字列配列の各要素の記憶領域のサイズ (50 バイトの場合)。

したがって、文字値が 50 バイト未満の文字列を保存すると、記憶領域の一部が無駄になります。

配列の利点は、連続した領域を占有し、CPU キャッシュを有効に活用してデータに迅速にアクセスできることです。

アレイのこの利点を維持し、ストレージ領域を節約したい場合は、アレイを圧縮できます:

Redis 研究ノート - リストの原則

しかし、問題があり、圧縮されたリストを走査するとき、各要素が占有するメモリ サイズがわからないため、次の要素の特定の開始位置を計算できません。

しかし、考えてみたら、各要素にアクセスする前にその長さを知ることができれば、この問題は解決するのではないか?

Redis 研究ノート - リストの原則

次に、Redis が ZipList を実装することで配列の利点を維持し、メモリを節約する方法を見てみましょう。

Redis 研究ノート - リストの原則

  • zlbytes:压缩列表的字节长度,是uint32_t类型,占4字节,因此压缩列表最多有232-1字节,可以通过该值计算zlend的位置,也可以在内存重新分配的时候使用。

  • zltail:压缩列表尾元素相对于压缩列表起始地址的偏移量,是uint32_t类型,占4字节,可以通过该值快速定位到列表尾元素的位置。

  • zllen:压缩列表元素的个数,是uint16_t类型,占2字节,表示最多存储的元素个数为216-1=65 535,如果需要计算总数量,则需要遍历整个压缩列表。

  • entryx:压缩列表存储的元素,既可以是字节数组,也可以是整数,长度不限。

  • zlend:压缩列表的结尾,是uint8_t类型,占1字节,恒为0xFF。

  • previous_entry_length:表示前一个元素的字节长度,占1字节或者5字节,当前元素的长度小于254时用1字节,大于等于254时用5字节,previous_entry_length 字段的第一个字节固定是0xFE,后面的4字节才是真正的前一个元素的长度。

  • encoding:表示元素当前的编码,有整数或者字节数。为了节省内存,encoding字段长度可变。

  • content:表示当前元素的内容。

ZipList变量的读取和赋值都是通过宏来实现的,代码片段如下:

//返回整个压缩列表的总字节
#define ZIPLIST_BYTES(zl)       (*((uint32_t*)(zl)))

//返回压缩列表的tail_offset变量,方便获取最后一个节点的位置
#define ZIPLIST_TAIL_OFFSET(zl) (*((uint32_t*)((zl)+sizeof(uint32_t))))

//返回压缩列表的节点数量
#define ZIPLIST_LENGTH(zl)      (*((uint16_t*)((zl)+sizeof(uint32_t)*2)))

//返回压缩列表的表头的字节数
//(内存字节数zlbytes,最后一个节点地址ztail_offset,节点总数量zllength)
#define ZIPLIST_HEADER_SIZE     (sizeof(uint32_t)*2+sizeof(uint16_t))

//返回压缩列表最后结尾的字节数
#define ZIPLIST_END_SIZE        (sizeof(uint8_t))

//返回压缩列表首节点地址
#define ZIPLIST_ENTRY_HEAD(zl)  ((zl)+ZIPLIST_HEADER_SIZE)

//返回压缩列表尾节点地址
#define ZIPLIST_ENTRY_TAIL(zl)  ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))

//返回压缩列表最后结尾的地址
#define ZIPLIST_ENTRY_END(zl)   ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)


对此,可以通过定义的结构体和对应的操作定义知道大概 redis 设计 压缩list 的思路;

这种方式虽然节约了空间,但是会存在每次插入和创建存在内存重新分配的问题。

quicklist

quicklist是Redis 3.2中新引入的数据结构,能够在时间效率和空间效率间实现较好的折中。Redis中对quciklist的注释为A doubly linked list of ziplists。顾名思义,quicklist是一个双向链表,链表中的每个节点是一个ziplist结构。quicklist可以看成是用双向链表将若干小型的ziplist连接到一起组成的一种数据结构。

当ziplist节点个数过多,quicklist退化为双向链表,一个极端的情况就是每个ziplist节点只包含一个entry,即只有一个元素。当ziplist元素个数过少时,quicklist可退化为ziplist,一种极端的情况就是quicklist中只有一个ziplist节点。

Redis 研究ノート - リストの原則

Redis 研究ノート - リストの原則


quicklist 结构定义:

typedef struct quicklist {
    // 指向quicklist的首节点
    quicklistNode *head;
    // 指向quicklist的尾节点
    quicklistNode *tail;
    // quicklist中元素总数
    unsigned long count;        /* total count of all entries in all ziplists */
    // quicklistNode节点个数
    unsigned long len;          /* number of quicklistNodes */
    // ziplist大小设置,存放list-max-ziplist-size参数的值
    int fill : 16;              /* fill factor for individual nodes */
    // 节点压缩深度设置,存放list-compress-depth参数的值
    unsigned int compress : 16; /* depth of end nodes not to compress;0=off */
    unsigned int bookmark_count: 4;
    quicklistBookmark bookmarks[];
} quicklist;

typedef struct quicklistBookmark {
    quicklistNode *node;
    char *name;
} quicklistBookmark;

quicklistNode定义如下:

typedef struct quicklistNode {
    struct quicklistNode *prev;
    struct quicklistNode *next;
    unsigned char *zl;
    unsigned int sz;             /* ziplist size in bytes */
    unsigned int count : 16;     /* count of items in ziplist */
    unsigned int encoding : 2;   /* RAW==1 or LZF==2 */
    unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */
    unsigned int recompress : 1; /* was this node previous compressed? */
    unsigned int attempted_compress : 1; /* node can't compress; too small */
    unsigned int extra : 10; /* more bits to steal for future usage */
} quicklistNode;

redis为了节省内存空间,会将quicklist的节点用LZF压缩后存储,但这里不是全部压缩,可以配置compress的值,compress为0表示所有节点都不压缩,否则就表示从两端开始有多少个节点不压缩;compress如果是1,表示从两端开始,有1个节点不做LZF压缩。compress默认是0(不压缩),具体可以根据你们业务实际使用场景去配置。

redis 的配置文件可以配置该参数

list-compress-depth 0

コマンド
リストの #最初の要素を削除して取得します。リストに要素がない場合はブロックされます。リストはタイムアウトになるか、要素がポップされるまで待機します。 ##BRPOP key1 [key2 ] タイムアウト
リストの最後の要素 リストに要素がない場合、リストは待機がタイムアウトになるかポップアップ要素が表示されるまでブロックされます。見つかった。
#BRPOPLPUSH ソース宛先タイムアウト リスト A からポップポップされた要素を別のリストに挿入して返す値。リストに要素がない場合、待機がタイムアウトになるかポップ可能な要素が見つかるまで、リストはブロックされます。
LIndex key index 通过索引获取列表中的元素
Linsert key before/after pivot value 在列表的元素前或者后插入元素
LLEN key 获取列表长度
LPOP key 移出并获取列表的第一个元素
LPUSH キーの値 1、値 2、… #1 つまたは複数の値がリストの先頭に挿入されます
##既存のリストの先頭に値を挿入
#リストの指定範囲内の要素を取得 ##LREM キー カウント値
リスト要素の削除 ##LSET キー インデックス値
インデックスによるリスト要素の値の設定 LTRIMキー スタート ストップ リストのプルーニングとは、指定された範囲内の要素のみがリストに保持され、指定された範囲内にない要素が削除されることを意味します。インデックスは 0 から始まり、範囲は 0 を含みます。
RPOP キー リストを削除最後の # 要素、戻り値は削除された要素です
RPOPPUSHソース宛先 リストの #最後の要素 # を削除して置き換えます。要素は次のとおりです。別のリストに追加され、
RPUSH キー value1 value2 …… # を返します。 #リストの最後に 1 つ以上の値を追加します
##RPUSHX キーの値 既存のリストに値を追加する
##意味0
##値
##特別な値は圧縮なしを意味します 1
##クイックリストの両端に 1 つあります。ノードは圧縮されていません。中間ノードは圧縮されます #2
クイックリストの両端の 2 つのノードは圧縮されておらず、中央のノードは圧縮されています #n クイックリストの両端には圧縮されていないノードが n 個あり、中央のノードは圧縮されています


各クイックノード ノードの最大容量を意味する塗りつぶしフィールドもあります。 、異なる値それぞれには異なる意味があり、デフォルトは -2 ですが、もちろん他の値に設定することもできます;

##list-max-ziplist-size -2

    値が正の数の場合、quicklistNode ノードのジップリストの長さを示します。たとえば、この値が 5 の場合、各 QuicklistNode ノードの ziplist には最大 5 つのデータ項目が含まれます。
    値が負の数、quicklistNode ノードの ziplist の長さがバイト数に応じて制限されていることを示します。オプションの値は -1 ~ -5 です。
##-2-3##-4
#値 意味
#-1 ziplist ノードの最大数ジップリスト ノードの最大数は 4kb
## です。 # 8kb
ziplist ノードの最大数は16kb
##ziplist ノードの最大値は 32kb
#-5 ##ジップリスト ノードの最大サイズは 64kb
なぜ構成が提供されるのですか?

  • #zipリストが短いほど、より多くのメモリ断片が発生し、ストレージ効率に影響します。ジップリストに 1 つの要素のみが格納されている場合、クイックリストは二重リンク リストに縮退します。ジップリストのメモリ スペース。値が大きいほど、メモリ スペースの小さなブロックがより多く浪費されます。クイックリストにノードが 1 つしかなく、すべての要素がジップリストに格納されている場合、クイックリストはジップリストに縮退します。

  • #結論
  • ##ソース コードを完全に理解しているわけではありませんが、Redis の設計アイデアについて理解することはできます。この記事。そしてそれがどのように段階的に最適化されるかを理解してください。パフォーマンスの一般的な概念を理解しましょう。

以上がRedis 研究ノート - リストの原則の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事はGolang菜鸟で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
NOSQLの理解:Redisの重要な機能NOSQLの理解:Redisの重要な機能Apr 13, 2025 am 12:17 AM

Redisの主な機能には、速度、柔軟性、豊富なデータ構造のサポートが含まれます。 1)速度:Redisはメモリ内データベースであり、読み取り操作はほとんど瞬間的で、キャッシュとセッション管理に適しています。 2)柔軟性:複雑なデータ処理に適した文字列、リスト、コレクションなど、複数のデータ構造をサポートします。 3)データ構造のサポート:さまざまなビジネスニーズに適した文字列、リスト、コレクション、ハッシュテーブルなどを提供します。

Redis:主要な機能を特定しますRedis:主要な機能を特定しますApr 12, 2025 am 12:01 AM

Redisのコア関数は、高性能のメモリ内データストレージおよび処理システムです。 1)高速データアクセス:Redisはデータをメモリに保存し、マイクロ秒レベルの読み取り速度と書き込み速度を提供します。 2)豊富なデータ構造:文字列、リスト、コレクションなどをサポートし、さまざまなアプリケーションシナリオに適応します。 3)永続性:RDBとAOFを介してディスクにデータを持続します。 4)サブスクリプションを公開:メッセージキューまたはリアルタイム通信システムで使用できます。

Redis:一般的なデータ構造のガイドRedis:一般的なデータ構造のガイドApr 11, 2025 am 12:04 AM

Redisは、次のようなさまざまなデータ構造をサポートしています。1。文字列、単一価値データの保存に適しています。 2。キューやスタックに適したリスト。 3.非重複データの保存に使用されるセット。 4。ランキングリストと優先キューに適した注文セット。 5。オブジェクトまたは構造化されたデータの保存に適したハッシュテーブル。

Redisカウンターを実装する方法Redisカウンターを実装する方法Apr 10, 2025 pm 10:21 PM

Redisカウンターは、R​​edisキー価値ペアストレージを使用して、カウンターキーの作成、カウントの増加、カウントの減少、カウントのリセット、およびカウントの取得など、カウント操作を実装するメカニズムです。 Redisカウンターの利点には、高速速度、高い並行性、耐久性、シンプルさと使いやすさが含まれます。ユーザーアクセスカウント、リアルタイムメトリック追跡、ゲームのスコアとランキング、注文処理などのシナリオで使用できます。

Redisコマンドラインの使用方法Redisコマンドラインの使用方法Apr 10, 2025 pm 10:18 PM

Redisコマンドラインツール(Redis-Cli)を使用して、次の手順を使用してRedisを管理および操作します。サーバーに接続し、アドレスとポートを指定します。コマンド名とパラメーターを使用して、コマンドをサーバーに送信します。ヘルプコマンドを使用して、特定のコマンドのヘルプ情報を表示します。 QUITコマンドを使用して、コマンドラインツールを終了します。

Redisクラスターモードの構築方法Redisクラスターモードの構築方法Apr 10, 2025 pm 10:15 PM

Redisクラスターモードは、シャードを介してRedisインスタンスを複数のサーバーに展開し、スケーラビリティと可用性を向上させます。構造の手順は次のとおりです。異なるポートで奇妙なRedisインスタンスを作成します。 3つのセンチネルインスタンスを作成し、Redisインスタンスを監視し、フェールオーバーを監視します。 Sentinel構成ファイルを構成し、Redisインスタンス情報とフェールオーバー設定の監視を追加します。 Redisインスタンス構成ファイルを構成し、クラスターモードを有効にし、クラスター情報ファイルパスを指定します。各Redisインスタンスの情報を含むnodes.confファイルを作成します。クラスターを起動し、CREATEコマンドを実行してクラスターを作成し、レプリカの数を指定します。クラスターにログインしてクラスター情報コマンドを実行して、クラスターステータスを確認します。作る

Redisキューの読み方Redisキューの読み方Apr 10, 2025 pm 10:12 PM

Redisのキューを読むには、キュー名を取得し、LPOPコマンドを使用して要素を読み、空のキューを処理する必要があります。特定の手順は次のとおりです。キュー名を取得します:「キュー:キュー」などの「キュー:」のプレフィックスで名前を付けます。 LPOPコマンドを使用します。キューのヘッドから要素を排出し、LPOP Queue:My-Queueなどの値を返します。空のキューの処理:キューが空の場合、LPOPはnilを返し、要素を読む前にキューが存在するかどうかを確認できます。

Redisクラスターzsetの使用方法Redisクラスターzsetの使用方法Apr 10, 2025 pm 10:09 PM

RedisクラスターでのZsetの使用:Zsetは、要素をスコアに関連付ける順序付けられたコレクションです。シャード戦略:a。ハッシュシャーディング:ZSTキーに従ってハッシュ値を分配します。 b。範囲シャード:要素スコアに従って範囲に分割し、各範囲を異なるノードに割り当てます。操作の読み取りと書き込み:a。読み取り操作:ZSetキーが現在のノードのシャードに属している場合、ローカルで処理されます。それ以外の場合は、対応するシャードにルーティングされます。 b。書き込み操作:Zsetキーを保持しているシャードに常にルーティングされます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。