《闲扯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 编码呢?下节再说...

原文地址:https://www.cnblogs.com/jstarseven/p/12620929.html

时间: 2024-10-10 20:04:55

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

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

http://www.cnblogs.com/lori/archive/2012/05/15/2501862.html Redis学习笔记~Redis提供的五种数据结构 回到目录 分布式缓存,消息队列,替代Session呵呵(Session太不稳定了,呵呵)=Redis Redis的崛起绝非偶然,它确实有自己的新东西在里面,它不像Memcached,只能将数据存储在内存中,它提供了持久化机制,避免了場机后的雪崩的问题,即服务器出现问题后,内存中保留的原始数据全部丢失,需要重新组织数据到内存,这时

Redis——五种数据类型

Redis共有strings.hashs.lists.sets.sorted sets五种数据类型,可以说已经比较丰富了.下面只对这几种数据类型的数据结构与用途做简要介绍.至于每种数据类型的操作API,这里只简单一提,不再一一详细介绍,有需要的用户可以Google即可. 一.    strings string是最简单的类型,一个Key对应一个Value.string类型是类型安全的,Redis的string可以包含任何数据,比如jpg图片或者序列化的对象.存储结构如下: 常用的API函数有:

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

string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一段内容 设置及获取字符串的某一位(bit) 批量设置一系列字符串的内容 应用场景: String是最常用的一种数据类型,普通的key/value存储都可以归为此类,value其实不仅是String, 也可以是数字:比如想知道什么时候封锁一个IP地址(访问超过几次).INCRBY命令让这些变得很容易,

Java 操作 Redis 五种数据类型

项目添加依赖 <!-- Redis 依赖 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> Java 怎么连接 Redis //连接 Redis @Test public void initConn01(){ S

轻松搞定高并发:详解Redis的五种数据类型及应用场景分析!

一.Redis基本概念介绍和特性 1.1 Redis基本概念介绍 1.Redis是远程的,有客户端和服务端,我们一般说的是服务端: 2.Redis是基于内存的,所以比基于硬盘的MySQL要快很多,但非常吃内存 3.Redis是非关系型数据库.本质上也是数据库,但MySQL关系型数据库存储时必须定义数据词典,而Redis则不需要. 1.2 Redis 和 Memcached比较 Redis数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的

redis的五种数据类型

redis的五种数据类型 redis客户端建立 ./redis-cli -h 192.168.1.22 -p 6380 --raw 1.String 应用场景: 统计网站访问数量.当前在线人数.微博数.粉丝数等,全局递增ID等 . 常用命令: SET key value GET key MSET key1 value1 [key2 value2] MGET key1 key2 INCR key DECR key SETNX key value  #只有key 不存在时,才设置key的值 2.Ha

Redis有哪几种数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value. string 类型是二进制安全的.意思是 redis 的 string 可以包含任何数据.比如jpg图片或者序列化的对象. string 类型是 Redis 最基本的数据类型,string 类

Redis中的五种数据结构

Strings: Lists: Sets: Hashes: Zsets: Redis中的五种数据结构

redis 五种数据类型

前言 前面学会了单机, 学会了集群, 但是redis咋用啊? 或者说, redis支持哪些数据类型呢? 常用的有五种: String , Hash, List, Set, zset(SortedSet) 一.String String 类型, 在前面也是使用过的. 直接来看一下 可以使用del name来删除缓存 二.List push指令: push分两个, 一个从左边push, 一个从右边push. 但是这个左右, 是对准备push的值而言的. 而不是针对将要push的数组来说的. pop指