Redis列表操作及链表和链表节点的实现

本专栏新增整合黄健宏老师的《Redis设计与实现》,以便更加有效地了解Redis 的内部构造及运作机制,帮助学者更高效得使用Redis。博文中会以虚线分区,上半区为Redis的简单使用,下半区为Redis内部实现,如果是简单地使用Redis快速完成工作或者只是想简单的了解Redis,只看上半区即可,有兴趣或等空闲的时候学习下下半区,结合源码会对Redis的理解更上一层楼。

List列表

  1. 基于Linked List 实现(索引 从左至右,从0开始   从右至左,从-1开始)
  2. 元素是字符串类型
  3. 列表头尾增删快,中间增删慢,增删元素是常态
  4. 元素可以重复出现
  5. 最多包涵2^32 - 1 个元素

命令说明(help @list 罗列所有关于list的命令)

B     block     块,阻塞

L     left     左

R    right    右

X    exist    存在

左右或者头尾压入元素

LPUSH key value [value......]

LPUSHX key value

RPUSH key value [value......]

RPUSHX key value

左右或者头尾弹出元素

LPOP key

RPOP key

从一个列表尾部弹出元素压入到另一个列表的头部

RPOPLUPSH source destination

返回列表中指定范围的元素

LRANGE key start stop

LRANGE key 0  -1:表示返回所有元素

获取指定位置的元素

LINDEX key index

设置指定位置元素的值

LSET key index value

列表长度,元素个数

LLEN key

从列表头部开始删除值等于value的元素count次

  1. LREM key count value 
  2. count > 0 :从表头开始向表尾搜索,移除与value相等的元素,数量为count
  3. count < 0 :从表尾开始向表头搜索,移除与value相等的元素,数量为count的绝对值
  4. count = 0 :移除表中所有与value相等的值

去除指定范围外的元素

LTRIM key start stop

在列表某个存在的值前后插入元素

LINSERT key BEFORE|AFTER pivot value (在 pivot 之前或之后 插入元素值value)

如果key和pivot不存在,不进行任何操作,返回 -1

阻塞

1、左右或头尾阻塞弹出元素

BLPOP key [key....] timeout

BRPOP key [key...] timeout

2、从一个列表尾部阻塞弹出元素压入到另一个列表头部

BRPOPLPUSH list1 list2 timeout




链表 - 列表键的底层实现之一

1、链表被广泛用于实现Redis的各种功能,比如列表键、发布与订阅、慢查询、监视器等。2、每个链表节点由一个listNode结构来表示,每个节点都有一个指向前置节点和后置节点的指针,所以Redis的链表实现是双端链表。3、每个链表使用一个list结构来表示,这个结构带有表头节点指针、表尾节点指针,以及链表长度等信息。4、因为链表表头节点的前置节点和表尾节点的后置节点都指向NULL,所以Redis的链表实现是无环链表。5、通过为链表设置不同的类型特定函数,Redis的链表可以用于保存各种不同类型的值

每个链表节点使用一个adlist.h/listNode结构来表示,多个listNode可以通过prev和next指针组成双端链表。

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

Redis链表实现:

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

dup、free和match 是用于实现多态链表所需的类型特定函数:dup函数用于复制链表节点所保存的值;free函数用于释放链表节点所保存的值;match函数则用于对比链表节点所保存的值和另一个输入值是否相等;

Redis的链表实现的特性可以总结如下:

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

链表和链表节点的API:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值