《闲扯Redis三》Redis五种数据类型之List型
一、前言
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型的更多相关文章
- 《闲扯Redis一》五种数据类型之String型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- Redis支持的五种数据类型
redis支持的五种数据类型: 1.string(字符串) 2.hash(哈希) Redis hash 是一个键值(key=>value)对集合. Redis hash是一个string类型的f ...
- 【Redis】一、Redis简介及五种数据类型
(一)Redis简介 Redis(Remote Dictionary Server)是一个使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value的开源 ...
- 《闲扯Redis六》Redis五种数据类型之Hash型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- 《闲扯Redis九》Redis五种数据类型之Set型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- Redis安装及五种数据类型
redis是非关系型数据库,也叫内存数据库.数据是键值对的形式,通过key查找value 安装Radis:6379 sudo apt-get update sudo apt-get install r ...
- Redis学习笔记--五种数据类型的使用场景
String 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...
- <Redis> 入门二 五种数据类型的操作、通用key的操作、发布订阅
文档参考:http://www.redis.net.cn/ string - > key value 简单的keyvalue,常规计数:例如微博数,粉丝数 set -> key v ...
- redis五种数据类型的使用场景
string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...
随机推荐
- C++走向远洋——65(十五周、项目一)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++学习之旅
到现在为止学习C++也已经有一个半月了.一个半个月里我怀着好奇与敬畏一步步的走来,一步步的走向C++的内心深处,也发现了C++"内心的复杂".虽有坎坷,但从未放弃. 我承认,我不是 ...
- ZOJ 4109 Welcome Party
题目链接:(https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370504)(https://vjudge.net/proble ...
- 7-35 jmu-python-求三角形面积及周长 (10 分)
输入的三角形的三条边a.b.c,计算并输出面积和周长.假设输入三角形三边是合法整形数据. 三角形面积计算公式: ,其中s=(a+b+c)/2. import math #导入math库 math.s ...
- boostrap3 bootstrap-datetimepicker.min.js设置中文语言
问题 bootstrap3中使用bootstrap-datetimepicker遇到设置中文语言的问题 解决办法 bootstrap-datetimepicker在使用的时候要先引入momentjs中 ...
- 使用 Redis 如何实现查询附近的人?「视频版」——面试突击 003 期
面试问题 Redis 如何实现查询附近的人? 涉及知识点 Redis 中如何操作位置信息? GEO 底层是如何实现的? 如何在程序实现查询附近的人? 在实际使用中需要注意哪些问题? 视频答案 视频地址 ...
- 峰哥说技术: 05-Spring Boot条件注解注解
Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 05 峰哥说技术 Spring Boot条件注解 @EnableAutoConfiguration开启自 ...
- 微信SEO怎么做-最新微信SEO干货
星辉信息科技进行微信SEO已经很多年了,结合多年的微信SEO经验通过浅谈微信SEO.微信SEO的3大优势.微信SEO的6个排名技巧.企业和个人微信SEO的4大优化战略来讲,可以完美解决B端C端微信获客 ...
- idea新建springboot项目
不多说废话,直接进入正题,按照下面的步骤创建一个springboot项目一般不会出错,当然不排除可能会有一些脸黑的,不过应该问题不大. 第一步,如果你是在已有的项目里面,新建一个springboot项 ...
- 一文详解Hexo+Github小白建站
作者:玩世不恭的Coder时间:2020-03-08说明:本文为原创文章,未经允许不可转载,转载前请联系作者 一文详解Hexo+Github小白建站 前言 GitHub是一个面向开源及私有软件项目的托 ...