一、前言

Redis 提供了5种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要。

原文解析

Redis 中的 list 是我们经常使用到的一种数据类型,根据使用方式的不同,可以应用到很多场景中。

二、操作命令

List数据类型在 Redis 中的相关命令:

命令 描述 用法
LPUSH 1.将一个或多个值value插入到列表key的表头
2.如果有多个value值,那么各个value值按从左到右的顺序依次插入表头
3.key不存在,一个空列表会被创建并执行LPUSH操作
4.key存在但不是列表类型,返回错误
LPUSH key value [value ...]
LPUSHX 1.将值value插入到列表key的表头,当且仅当key存在且为一个列表
2.key不存在时,LPUSHX命令什么都不做
LPUSHX key value
LPOP 1.移除并返回列表key的头元素 LPOP key
LRANGE 1.返回列表key中指定区间内的元素,区间以偏移量start和stop指定
2.start和stop都以0位底
3.可使用负数下标,-1表示列表最后一个元素,-2表示列表倒数第二个元素,以此类推
4.start大于列表最大下标,返回空列表
5.stop大于列表最大下标,stop=列表最大下标
LRANGE key start stop
LREM 1.根据count的值,移除列表中与value相等的元素
2.count>0表示从头到尾搜索,移除与value相等的元素,数量为count
3.count<0表示从从尾到头搜索,移除与value相等的元素,数量为count
4.count=0表示移除表中所有与value相等的元素
LREM key count value
LSET 1.将列表key下标为index的元素值设为value
2.index参数超出范围,或对一个空列表进行LSET时,返回错误
LSET key index value
LINDEX 1.返回列表key中,下标为index的元素 LINDEX key index
LINSERT 1.将值value插入列表key中,位于pivot前面或者后面
2.pivot不存在于列表key时,不执行任何操作
3.key不存在,不执行任何操作
LINSERT key BEFORE
LLEN 1.返回列表key的长度
2.key不存在,返回0
LLEN key
LTRIM 1.对一个列表进行修剪,让列表只返回指定区间内的元素,不存在指定区间内的都将被移除 LTRIM key start stop
RPOP 1.移除并返回列表key的尾元素 RPOP key
RPOPLPUSH 在一个原子时间内,执行两个动作:
1.将列表source中最后一个元素弹出并返回给客户端
2.将source弹出的元素插入到列表desination,作为destination列表的头元素
RPOPLPUSH source destination
RPUSH 1.将一个或多个值value插入到列表key的表尾 RPUSH key value [value ...]
RPUSHX 1.将value插入到列表key的表尾,当且仅当key存在并且是一个列表
2.key不存在,RPUSHX什么都不做
RPUSHX key value

实践:别偷懒,动手一下,try it out

三、应用场景

1、lpush+lpop=Stack(栈)

2、lpush+rpop=Queue(队列)

3、lpush+ltrim=Capped Collection(有限集合)

4、lpush+brpop=Message Queue(消息队列)

5、排行榜,数据最新列表等等

四、底层解析

结构图上显示,List类型有两种实现方式:

举例说明,创建列表对象 numbers

1、使用压缩列表(ziplist)实现的列表对象

结构如下

2、使用双端链表(linkedlist)实现的列表对象

结构如下

五、疑问思考

压缩列表与双端链表是什么样的结构?

1、压缩列表(ziplist)

压缩列表(ziplist)是Redis为了节省内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。

结构如下

压缩列表的每个节点构成如下

1)previous_entry_ength:以字节为单位,记录了压缩列表中前一个字节的长度。previous_entry_ength 的长度可以是1字节或者5字节:

  如果前一节点的长度小于254字节,那么 previous_entry_ength 属性的长度为1字节,前一节点的长度就保存在这一个字节里面。

  如果前一个节点的长度大于等于254,那么 previous_entry_ength 属性的长度为5字节,其中属性的第一字节会被设置为0xFE(十进制254),而之后的四个字节则用于保存前一节点的长度。

  利用此原理即当前节点位置减去上一个节点的长度即得到上一个节点的起始位置,压缩列表可以从尾部向头部遍历,这么做很有效地减少了内存的浪费。

2)encoding:记录了节点的 content 属性所保存数据的类型以及长度。

3)content:保存节点的值,节点的值可以是一个字节数组或者整数,值的类型和长度由节点的 encoding 属性决定。

2、双端链表(linkedlist)

链表是一种常用的数据结构,C 语言内部是没有内置这种数据结构的实现,所以Redis自己构建了链表的实现。

链表节点定义:

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

多个 listNode 可以通过 prev 和 next 指针组成双端链表,结构如下

另外Redis还提供了操作链表的数据结构:

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

list结构为链表提供了表头指针 head ,表尾指针 tail 以及链表长度计数器 len ,dup、free、match 成员则是用于实现多态链表所需的类型特定函数。

Redis链表实现的特性

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

疑问:Redis列表什么时候会使用 ziplist 编码,什么时候又会使用 linkedlist 编码呢?下节再说...

《闲扯Redis三》Redis五种数据类型之List型的更多相关文章

  1. 《闲扯Redis一》五种数据类型之String型

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  2. Redis支持的五种数据类型

    redis支持的五种数据类型: 1.string(字符串) 2.hash(哈希) Redis hash 是一个键值(key=>value)对集合. Redis hash是一个string类型的f ...

  3. 【Redis】一、Redis简介及五种数据类型

    (一)Redis简介   Redis(Remote Dictionary Server)是一个使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value的开源 ...

  4. 《闲扯Redis六》Redis五种数据类型之Hash型

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  5. 《闲扯Redis九》Redis五种数据类型之Set型

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  6. Redis安装及五种数据类型

    redis是非关系型数据库,也叫内存数据库.数据是键值对的形式,通过key查找value 安装Radis:6379 sudo apt-get update sudo apt-get install r ...

  7. Redis学习笔记--五种数据类型的使用场景

    String 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...

  8. <Redis> 入门二 五种数据类型的操作、通用key的操作、发布订阅

    文档参考:http://www.redis.net.cn/ string - > key value 简单的keyvalue,常规计数:例如微博数,粉丝数 set     -> key v ...

  9. redis五种数据类型的使用场景

    string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...

随机推荐

  1. 达拉草201771010105《面向对象程序设计(java)》第四周学习总结

    实验四类与对象的定义及使用 实验时间 2018-9-20 第一部分:理论知识 1.类与对象概念 (1)类是具有相同属性和方法的一类事物的抽象,是构造对象的模板或蓝图,由类构造对象的过程称为创建类的实例 ...

  2. js笔记-0

    #js笔记-0 数组: indexOf方法: Array也可以通过indexOf()来搜索一个指定的元素的位置: var arr = [10, 20, '30', 'xyz']; arr.indexO ...

  3. echart 之实现温度计

    百度这个图表支持不是很好,有的需要自己写,看大神们实现温度计都是用 水球特效实现的我这里雕虫小计啊但是满足我了我的项目需求特此分享出来,可惜自己不是专业的前端 这是我的实现结果 好了上代码html: ...

  4. HTML5 Canvas(基础知识)

    最近笔者在学习HTML5的新元素<canvas>,会分享一些基础知识以及小例子,最终使用<canvas>实现一个绘制简单图表(条形图.线图或者饼图)的js库,会更新一到两篇文章 ...

  5. notepad++ 字符处理: 字符前后删除 或 删除未包含字符串的行

    字符串前后删除 删除str之后的所有字符用,打开替换(Ctrl+H) :str.*$ 删除str之前的所有字符用:^.*str 如果是其他字符就把str替换为其他字符 ---------------- ...

  6. PYTHON程序设计实验

    Python程序设计实验报告一: 熟悉IDLE和在线编程平台 安徽工程大学 Python程序设计实验报告 班级 物流191 姓名 邹缕学号 3190505117成绩 ▁▁▁ 日期 2020.3.5 指 ...

  7. python对接elasticsearch的基本操作

    基本操作 #!/usr/bin/env python # -*- coding: utf-8 -*- # author tom from elasticsearch import Elasticsea ...

  8. 树链剖分与倍增求LCA

    树链剖分与倍增求\(LCA\) 首先我要吐槽机房的辣基供电情况,我之前写了一上午,马上就要完成的时候突然停电,然后\(GG\)成了送链剖分 其次,我没歧视\(tarjan LCA\) 1.倍增求\(L ...

  9. 机器学习 - LSTM应用之情感分析

    1. 概述 在情感分析的应用领域,例如判断某一句话是positive或者是negative的案例中,咱们可以通过传统的standard neuro network来作为解决方案,但是传统的神经网络在应 ...

  10. What is the difference between shades and shadows?

    Shade is the darkness of an object not in direct light, while shadows are the silhouette of an objec ...