一、前言

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. CSS——NO.1(初识CSS)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  2. Docker深入浅出系列 | 单机Nginx+Springboot实战

    目录 Nginx+Springboot实战 前期准备 实战目标 实战步骤 创建Docker网络 搭建Mysql容器 搭建额度服务集群 搭建Nginx服务 验证额度服务 附录 Nginx+Springb ...

  3. 想要成为一名优秀的Java程序员,你需要这8个锦囊

    私底下,隔三差五就有读者问我:"二哥,怎么样才能像你一样,成为一名优秀的 Java 开发者呢?"假如把"怎么才能像你一样"去掉的话,这个问题就是一个好问题,否则 ...

  4. css实战#用css画一个中国结

    大家好!今天跟大家分享一个用 css 画中国结的教程.最终效果如下: 大家如果感兴趣可以参考我的源码:gitHub地址 首先,我们定义好画中国结需要的结构: <div class="k ...

  5. js判断PC端还是移动端的代码小坑

    我在写官网的时候做了pc和移动端两个,在通过网上查找了这样的代码,看着完全没问题,等放进去页面中后,PC端页面一直刷新,根本停不下来,找了类似js还是同样的问题.通过不断尝试后才发现,问题就是多了一行 ...

  6. React拖拽组件Dragact V0.1.7:教你优化React组件性能与手感

    仓库地址:Dragact手感丝滑的拖拽布局组件 预览地址:支持手机端噢- 上回我们说到,Dragact组件已经进行了一系列的性能优化,然而面对大量数据的时候,依旧比较吃力,让我们来看看,优化之前的Dr ...

  7. DUBBO 面试灵魂18问

    一.Dubbo 是什么 dubbo 是一个分布式框架,是一个远程服务调用的分布式框架,其核心部分包含: 1)集群容错: 提供基于接口方法的透明远程过程调用,包含多协议支持,以及软负债均衡.失败容错.地 ...

  8. centOS 6.5 yum升级 gcc4.8 然后又退回来4.4

    CentOS 6.5 用了很多年了,一直舍不得省7 . 由于要用到 c++ 11 ,所以决定升级一下. 为了省事我选择用 yum 方式升级,结果最后还是不能用,差点搞坏,这是真机,重装麻烦了. get ...

  9. pytest、tox、Jenkins实现python接口自动化持续集成

    pytest介绍 pytest是一款强大的python测试工具,可以胜任各种级别的软件测试工作,可以自动查找测试用并执行,并且有丰富的基础库,可以大幅度提高用户编写测试用例的效率,具备可扩展性,用户自 ...

  10. PBM error occurred during PreCloneCheckCallback: 由于目标计算机积极拒绝,无法连接

    问题如下: 迁移存储和主机的时候发生错误,错误如下: 出现了常规系统错误: PBM error occurred during PreCloneCheckCallback: 由于目标计算机积极拒绝,无 ...