Redis 学习笔记之链表

Redis 学习之链表

简介

  • Redis lists 能保存 2^32 – 1 个元素,40 亿个元素
  • Redis lists 是双向链表的数据结构

一、Redis 链表底层数据结构

1.1 节点定义

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

Redis 学习笔记之链表

从图中可以看出,Redis list 结构采用双向链表的数据结构

1.2 Redis list 内部定义

typedef struct list {
    // 表头节点
    listNode *head;
    // 表尾节点
    listNode *tail;
    // 链表所包含的节点数量
    unsigned long len;
    // 节点值复制函数(dup 函数用于复制链表节点所保存的值;)
    void *(*dup)(void *ptr);
    // 节点值释放函数(free 函数用于释放链表节点所保存的值;)
    void (*free)(void *ptr);
    // 节点值对比函数(match 函数则用于对比链表节点所保存的值和另一个输入值是否相等。)
    int (*match)(void *ptr, void *key);
} list;

Redis 学习笔记之链表

1.3 Redis list 的特性

  • 双端: 链表节点带有 prev 和 next 指针, 获取某个节点的前置节点和后置节点的复杂度都是 O(1) 。
  • 无环: 表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL , 对链表的访问以 NULL 为终点。
  • 带表头指针和表尾指针: 通过 list 结构的 head 指针和 tail 指针, 程序获取链表的表头节点和表尾节点的复杂度为 O(1) 。
  • 带链表长度计数器: 程序使用 list 结构的 len 属性来对 list 持有的链表节点进行计数, 程序获取链表中节点数量的复杂度为 O(1) 。
  • 多态: 链表节点使用 void* 指针来保存节点值, 并且可以通过 list 结构的 dup 、 free 、 match 三个属性为节点值设置类型特定函数, 所以链表可以用于保存各种不同类型的值。

二、Redis list 常用命令学习

2.1 RPUSH 命令

#语法 RPUSH key value1 value2 ...

向存于 key 的列表的尾部插入所有指定的值
如果 key 不存在,那么会创建一个空的列表然后再进行 push 操作。
返回值为 list的长度
127.0.0.1:0>RPUSH mylist "Hello"
"1"
127.0.0.1:0>RPUSH mylist "World" "!"
"3"

2.2 RPUSHX 命令

将值 value 插入到列表 key 的表尾, 当且仅当 key 存在并且是一个列表。
当key不存在时,不做操作
返回值为 list的长度
127.0.0.1:0>RPUSHX mylist "Java"
"4"
因为myNewList 不存在,所以不会创建空的list,并进行push操作
127.0.0.1:0>RPUSHX myNewList "new"
"0"
查看keys
127.0.0.1:0>keys *
 1)  "num"
 2)  "mylist"
 3)  "age"
 4)  "num2"
 5)  "a"
 6)  "num4"
 7)  "num3"
 8)  "name"
 9)  "b"
 10)  "test"
 11)  "num1"
 12)  "mykey"

2.3 LLEN 命令

返回存储在 key 里的list的长度。
127.0.0.1:0>llen mylist
"4"
如果key 不存在,则返回0
127.0.0.1:0>llen myNewList
"0"

当存储在 key 里的值不是一个list的话,会返回error。
127.0.0.1:0>llen num
"WRONGTYPE Operation against a key holding the wrong kind of value"

2.4 LPUSH

与RPUSH 命令 类似
将所有指定的值插入到存于 key 的列表的头部。
在 push 操作后的 list 长度
127.0.0.1:0>LPush list1  Java python
"2"
127.0.0.1:0>lrange list1 0 -1
 1)  "python"
 2)  "Java"

2.5 LPUSHX

RPUSHX 命令类似
将值 value 插入到列表 key 的表头, 当且仅当 key 存在并且是一个列表。

返回值为 list的长度
127.0.0.1:0>LPUSHX list1 c++
"3"
127.0.0.1:0>lrange list1 0 -1
 1)  "c++"
 2)  "python"
 3)  "Java"
 # 当key不存在时,不做操作
 127.0.0.1:0>LPUSHX list2 c++
"0"

2.6 LPOP 命令

移除并且返回 key 对应的 list 的第一个元素
当key 不存在时,返回null
127.0.0.1:0>lpop list1
"c++"
127.0.0.1:0>lpop  list3
null

2.7 RPOP 命令

移除并返回存于 key 的 list 的最后一个元素。
127.0.0.1:0>rpop list1
"Java"
127.0.0.1:0>rpop list3
null

2.8 LINDEX 命令

#返回列表里的元素的索引 index 存储在 key 里面。 下标是从0开始索引的
#list1 列表的长度为1
127.0.0.1:0>llen  list1
"1"
#取出第一位
127.0.0.1:0>lindex list1 0
"python"

2.9 LINSERT 命令

#把 value 插入存于 key 的列表中在基准值 pivot 的前面或后面。
#当 key 不存在时,这个list会被看作是空list,任何操作都不会发生。
#当 key 存在,但保存的不是一个list的时候,会返回error。

在列表list1 的元素python 前插入Java元素
127.0.0.1:0>LINSERT list1 BEFORE python Java
"2"
127.0.0.1:0>lrange list1 0 -1
1)  "Java"
2)  "python"

元素python 后插入Java元素
127.0.0.1:0>LINSERT list1 AFTER  python Java
"3"
127.0.0.1:0>lrange list1 0 -1
1)  "Java"
2)  "python"
3)  "Java"

2.10 LSET 命令

#设置 index 位置的list元素的值为 value
#设置地三个元素为c++
127.0.0.1:0>lset list1 2 c++
"OK"
127.0.0.1:0>lrange list1 0 -1
 1)  "Java"
 2)  "python"
 3)  "c++"

2.11 LREM 命令

#从存于 key 的列表里移除前 count 次出现的值为 value 的元素。
count > 0: 从头往尾移除值为 value 的元素。
count < 0: 从尾往头移除值为 value 的元素。
count = 0: 移除所有值为 value 的元素。
#语法 LREM key count value
127.0.0.1:0>lpush list1 java
"4"
127.0.0.1:0>lpush list1 java
"5"
127.0.0.1:0>lpush list1 java
"6"
#删除前两次出现的java
127.0.0.1:0>lrem list1 2 java
"2"
127.0.0.1:0>lrange list1 0 -1
 1)  "java"
 2)  "Java"
 3)  "python"
 4)  "c++"

2.12 阻塞的命令

BLPOP、BRPOP是阻塞式列表的弹出命令,当给定列表没有数据时,则会阻塞客户端,直到列表有元素
127.0.0.1:0>rpush list java
"1"

0 代表不设置超时,但不能为负数
127.0.0.1:0>brpop list 0
 1)  "list"
 2)  "java"
list中没有元素阻塞
127.0.0.1:0>brpop list 0

三、了解 Redis list 的应用场景

  • 事务模块使用双端链表依序保存输入的命令;
  • 服务器模块使用双端链表来保存多个客户端;
  • 订阅/发送模块使用双端链表来保存订阅模式的多个客户端;
  • 事件模块使用双端链表来保存时间事件(time event)

参考

Original: https://www.cnblogs.com/JianJianHuang/p/13676294.html
Author: JiaJianHuang
Title: Redis 学习笔记之链表

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/573094/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • InnoDB学习(五)之MVCC多版本并发控制

    MVCC多版本并发控制,是一种数据库管理系统并发控制的方法。MVCC多版本并发控制下,数据库中的数据会有多个版本,分别对应不同的事务,从而达到事务之间并发数据的隔离。MVCC最大的…

    Java 2023年6月8日
    081
  • java Builder模式

    Builder 模式也叫建造者模式,builder模式的作用将一个复杂对象的构建与他的表示分离,一步一步创建一个复杂对象的创建型模式。在不知道内部建造细节的情况下,可以更精细的控制…

    Java 2023年6月16日
    0106
  • Random在高并发下的缺陷以及JUC对其的优化

    Random可以说是每个开发都知道,而且都用的很6的类,如果你说,你没有用过Random,也不知道Random是什么鬼,那么你也不会来到这个技术类型的社区,也看不到我的博客了。但并…

    Java 2023年6月5日
    097
  • Spring Boot 面试问题

    说一说你对Spring Boot的理解 名词解释: Spring Boot 基于 Spring 开发, Spirng Boot 本身并 不提供 Spring 框架的核心特性以及扩展…

    Java 2023年6月7日
    078
  • Fizz网关入门教程-安装

    概述 Fizz网关是一个基于 Java开发的微服务聚合网关,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的…

    Java 2023年6月9日
    077
  • Java中类变量(静态变量)和类方法(静态方法)

    类变量 类变量也叫静态变量或静态属性,是该类所有对象共享的变量任何一个该类的对象去访问它时,取得都是一样的值 语法: 访问修饰符 static 数据类型 变量名 static 访问…

    Java 2023年6月6日
    098
  • Git (简单基本操作)

    1、设置配置信息 查看配置信息:git config -l 设置用户名:git config –global user.name xxx 设置邮箱:git config…

    Java 2023年6月15日
    066
  • Spring事务源码解读

    一、Spring事务使用 1.通过maven方式引入jar包 com.alibaba druid 1.2.8 mysql mysql-connector-java 8.0.28 o…

    Java 2023年6月13日
    092
  • 2020年度钻石C++C学习笔记(2)–《博学谷》

    1. 以下标示符中命名合法的是 A A、A B、ab.c C、@rp D、2Y_ 2. 设 a 和 b 均为 double 型变量,且a=5.5、b=2.5,则表达式(int)a …

    Java 2023年6月7日
    039
  • 深入MySQL(一):MySQL的组织架构

    今天开始将自己所学过的MySQL的知识都尝试融会贯通,并且用写博客的方式记录分享下来。今天讲的主题是 MySQL的组织架构,对于学习一个中间件或者开源项目而言,我觉得最重要的便是先…

    Java 2023年6月7日
    0104
  • 用户后台管理

    User Management 这是通过SpringBoot完成的用户后台管理系统 一些解释说明也在代码里面, 源码及资源 会放在文末哦!!! – 这是效果图 大概就这…

    Java 2023年6月9日
    077
  • 谷粒商城(无CURD代码)

    写在开头: 这份笔记仅仅记录了一些环境搭建以及基础篇中一些技术的使用,基本的CURD大部分没有记录,参考了很多网友的博客。若有冒犯,请联系我删除。参考文档见下: 本博客为自己随笔记…

    Java 2023年6月13日
    071
  • springboot

    狂神说秦疆老师的笔记 Original: https://www.cnblogs.com/zrk0929/p/15878309.htmlAuthor: 学技术的小凯Title: s…

    Java 2023年6月7日
    081
  • Spring RestTemplate中几种常见的请求方式

    在Spring Cloud中服务的发现与消费一文中,当我们从服务消费端去调用服务提供者的服务的时候,使用了一个很好用的对象,叫做RestTemplate,当时我们只使用了RestT…

    Java 2023年5月30日
    086
  • intellij idea 之 CheckStyle 代码格式校验

    posted @2016-04-06 11:52 聊聊IT那些事 阅读(1967 ) 评论() 编辑 Original: https://www.cnblogs.com/FCWOR…

    Java 2023年6月6日
    091
  • 自定义注解,利用AOP实现日志保存(数据库),代码全贴,复制就能用

    前言 1,在一些特定的场景我们往往需要看一下接口的入参,特别是跨系统的接口调用(下发,推送),这个时候的接口入参就很重要,我们保存入参入库,如果出问题就可以马上定位是上游还是下游的…

    Java 2023年6月14日
    082
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球