列表(list)类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储232-1个元素。在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。

列表类型有两个特点:

  1. 列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表。
  2. 列表中的元素可以是重复的.

一、内部实现

在Redis3.2版本以前列表类型的内部编码有两种。

  • ziplist(压缩列表):当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。
  • linkedlist(链表):当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。

而在Redis3.2版本开始对列表数据结构进行了改造,使用 quicklist 代替了 ziplist 和 linkedlist.

关于这三种底层数据结构可以查看我的另外三篇文章

Redis数据结构——链表

Redis数据结构——压缩列表

Redis数据结构——quicklist

二、常用命令

Redis列表对象常用命令如下表(点击命令可查看命令详细说明)。

命令 说明 时间复杂度
BLPOP key [key ...] timeout 删除,并获得该列表中的第一元素,或阻塞,直到有一个可用 O(1)
BRPOP key [key ...] timeout 删除,并获得该列表中的最后一个元素,或阻塞,直到有一个可用 O(1)
BRPOPLPUSH source destination timeout 弹出一个列表的值,将它推到另一个列表,并返回它;或阻塞,直到有一个可用 O(1)
LINDEX key index 获取一个元素,通过其索引列表 O(N)
LINSERT key BEFORE AFTER pivot value在列表中的另一个元素之前或之后插入一个元素 O(N)
LLEN key 获得队列(List)的长度 O(1)
LPOP key 从队列的左边出队一个元素 O(1)
LPUSH key value [value ...] 从队列的左边入队一个或多个元素 O(1)
LPUSHX key value 当队列存在时,从队到左边入队一个元素 O(1)
LRANGE key start stop 从列表中获取指定返回的元素 O(S+N)
LREM key count value 从列表中删除元素 O(N)
LSET key index value 设置队列里面一个元素的值 O(N)
LTRIM key start stop 修剪到指定范围内的清单 O(N)
RPOP key 从队列的右边出队一个元 O(1)
RPOPLPUSH source destination 删除列表中的最后一个元素,将其追加到另一个列表 O(1)
RPUSH key value [value ...] 从队列的右边入队一个元素 O(1)
RPUSHX key value 从队列的右边入队一个元素,仅队列存在时有效 O(1)

三、使用场景

3.1 消息队列

列表类型可以使用 rpush 实现先进先出的功能,同时又可以使用 lpop 轻松的弹出(查询并删除)第一个元素,所以列表类型可以用来实现消息队列

3.2 文章(商品等)列表

我们以博客站点为例,当用户和文章都越来越多时,为了加快程序的响应速度,我们可以把用户自己的文章存入到 List 中,因为 List 是有序的结构,所以这样又可以完美的实现分页功能,从而加速了程序的响应速度。

  1. 每篇文章我们使用哈希结构存储,例如每篇文章有3个属性title、timestamp、content

    hmset acticle:1 title xx timestamp 1476536196 content xxxx
    ...
    hmset acticle:k title yy timestamp 1476512536 content yyyy
    ...
  2. 向用户文章列表添加文章,user:{id}:articles作为用户文章列表的键:

    lpush user:1:acticles article:1 article3
    ...
    lpush
    ...
  3. 分页获取用户文章列表,例如下面伪代码获取用户id=1的前10篇文章

    articles = lrange user:1:articles 0 9
    for article in {articles}
    {
    hgetall {article}
    }

注意:使用列表类型保存和获取文章列表会存在两个问题。

  • 如果每次分页获取的文章个数较多,需要执行多次hgetall操作,此时可以考虑使用Pipeline批量获取,或者考虑将文章数据序列化为字符串类型,使用mget批量获取。
  • 分页获取文章列表时,lrange命令在列表两端性能较好,但是如果列表较大,获取列表中间范围的元素性能会变差,此时可以考虑将列表做二级拆分,或者使用Redis3.2的quicklist内部编码实现,它结合ziplist和linkedlist的特点,获取列表中间范围的元素时也可以高效完成。

关于列表的使用场景可参考以下几个命令组合:

  • lpush+lpop=Stack(栈)
  • lpush+rpop=Queue(队列)
  • lpush+ltrim=Capped Collection(有限集合)
  • lpush+brpop=Message Queue(消息队列)

小结

本篇文章我们总结了Redis 列表对象的内部实现、常用命令以及常用的一些场景,那么大家在项目中对Redis列表对象的使用都有哪些场景呢,欢迎在评论区给我留言和分享,我会第一时间反馈!我们共同学习与进步!

参考

《Redis设计与实现》

《Redis开发与运维》

《Redis官方文档》

-----END-----

Redis对象——列表(List)的更多相关文章

  1. 【redis源码阅读】redis对象

    结构定义 在redis中,对象的数据结构定义如下: ​typedef struct redisObject { ​unsigned type:4; ​unsgined encoding:4; ​uns ...

  2. Redis对象类型

    Redis对象类型 Redis基于基础的数据结构创建的对象: 字符串对象. 列表对象. 哈希对象. 集合对象 有序集合对象. 对象回收:Redis对象系统实现了基于引用计数技术的内存回收机制,当程序不 ...

  3. Redis底层探秘(五):Redis对象

    前面几篇文章,我们一起学习了redis用到的所有主要数据结构,比如简单动态字符串(sds).双端链表.字典.压缩列表.整数集合等等. redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这 ...

  4. 【redis对象,集合序列化Demo】

    package org.seckill.dao.cache; import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStr ...

  5. Redis对象的设计与实现

    一.Redis对象结构Redis中的每个对象都由一个redisObject结构表示: typedef struct redisObject { unsigned type;//类型 unsigned ...

  6. 面试官:你了解过Redis对象底层实现吗

    上一章我们讲了Redis的底层数据结构,不了解的人可能会有疑问:这个和平时用的五大对象有啥关系呢?这一章我们就主要解释他们所建立的联系. 看这个文件之前,如果对ziplist.skiplist.int ...

  7. Redis之对象篇——Redis对象系统简介

    Redis之对象篇--Redis对象系统简介 前言     之前几篇文章,简单介绍 Redis用到的所有主要数据结构,简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合.跳跃表. 图解Red ...

  8. Redis对象

    概述 Redis并没有使用基础数据结构去实现键值数据库,而是基于数据结构封装了一个个对象. 类型和编码 由于Redis是键值数据库,所以每次存储数据时,至少包含两个对象,即K.V对应的对象.其数据结构 ...

  9. spring jdbc 查询结果返回对象、对象列表

    首先,需要了解spring jdbc查询时,有三种回调方式来处理查询的结果集.可以参考 使用spring的JdbcTemplate进行查询的三种回调方式的比较,写得还不错. 1.返回对象(queryF ...

随机推荐

  1. 微信小程序结构目录、配置介绍、视图层(数据绑定,运算,列表渲染,条件渲染)

    目录 一.小程序结构目录 1.1 小程序文件结构和传统web对比 1.2 基本的项目目录 二.配置介绍 2.1 配置介绍 2.2 全局配置app.json 2.3 page.json 三.视图层 3. ...

  2. 量子计算机编程(二)——QPU基础函数

    第二部分主要是QPU的基础功能,第一部分就像是我们有了哪些基本的语句,第二部分就是我们能写一些简单基础的函数,一些小模块,第三部分就是他的应用了. 先来看一下一个简单量子应用的结构: 第一步,将量子态 ...

  3. 基于Canal和Kafka实现MySQL的Binlog近实时同步

    前提 近段时间,业务系统架构基本完备,数据层面的建设比较薄弱,因为笔者目前工作重心在于搭建一个小型的数据平台.优先级比较高的一个任务就是需要近实时同步业务系统的数据(包括保存.更新或者软删除)到一个另 ...

  4. chrome 和 chromeDriver

    在写selenium的时候,发现很简单的case也报错 package com.lv.test; import org.junit.Test; import org.openqa.selenium.W ...

  5. R自带数据集

    向量 euro    #欧元汇率,长度为11,每个元素都有命名landmasses    #48个陆地的面积,每个都有命名precip   #长度为70的命名向量rivers   #北美141条河流长 ...

  6. Python多线程的事件监控

    设想这样一个场景: 你创建了10个子线程,每个子线程分别爬一个网站,一开始所有子线程都是阻塞等待.一旦某个事件发生:例如有人在网页上点了一个按钮,或者某人在命令行输入了一个命令,10个爬虫同时开始工作 ...

  7. (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)

    协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...

  8. 微信小程序开发(二)认识开发工具

    腾讯微信团队提供非常优秀的微信小程序开发工具,大大降低了开发者的入门门槛,为他们点赞!上一篇文章已经说明了,如何注册及下载开发工具,现在我们就来一起认识见识一下开发工具的庐山真面目. 首次打开这个开发 ...

  9. C/C++、C#、JAVA(二):基本类型和转换操作

    基本类型和转换操作 数据类型 C语言中的基本类型如下. 类型 存储大小 值范围 char 1 字节 -128 到 127 或 0 到 255 unsigned char 1 字节 0 到 255 si ...

  10. kerberos系列之kerberos安装

    最近搞了一下kerberos,准备写一个系列,介绍kerberos的安装,和常用组件kerberos配置,今天进入第一篇:kerberOS安装 具体kerberos是什么东西,大家可以百度查一下,这里 ...