Redis - list

Redis中,为了更好地管理链表,定义了一个list的数据结构,做为链表的封装java

typedef struct listNode {

    // 前置节点
    struct listNode *prev;

       // 后置节点
    struct listNode *next;

    // 节点的值
    void *value;
} listNode;
typedef struct list {

    // 头节点
    listNode *head;

    // 尾节点
    listNode *tail;

    // 链表中的节点数
    unsigned int len;

    // 节点值复制函数
    void *(*dup) (void *ptr);

    // 节点值释放函数
    void (*free) (void *ptr);

    // 节点值对比函数
    int (*match) (void *ptr, void *key);
} list;

Redis的链表的实现的主要特性:算法

  1. 双端:链表节点都有prev和next指针,获取节点的前置节点和后置节点的算法复杂度都为O(1)。
  2. 无环:list的第一个节点(头节点)的prev和最后一个节点(尾节点)的next都指向NULL。
  3. 带表头指针和表尾指针:经过list的head和tail两个指针,能够随意的从链表的头和尾进行操做。
  4. 带链表长度计数器:能够经过len成员来获取链表的节点的个数,复杂度O(1)。
  5. 多态:链表使用void *指针来保存value,而且能够经过dup,free,match来操控节点的value值,所以,该链表能够保存任意类型的值。

操做

  1. RPUSH key value [value ...] 
    从队列的右边入队一个元素或多个元素,复杂度O(1) ; 将全部指定的值插入存于key的列表的尾部(从右侧插入)。
    若是key不存在,那么PUSH以前,会先自动建立一个空的列表。若是key对应的值不是一个list的话,则会返回一个错误。若是同时push多个值的话,值会依次从左到右PUSH从尾部进入list。

    a,评论系统数组

    相似微博, 在看完一条微博以后,经常会评论一番,或者看看其余人的吐槽。每条评论的记录都是按照时间顺序排序的。读的时候也是这个顺序。这时,队列就是一个很好的存储结构。每提交一次评论,都向list的末尾添加一个新的节点。安全

    b,并行转串行数据结构

    用户每时每刻均可能发出请求,并且请求的频率常常变化。这时,后台的程序不可能马上响应每个用户的请求,尤为是请求特别占资源的服务的时候(双11的时候,404页面?)。有什么好的办法来解决这个问题呢?须要一个排队系统。根据用户的请求时间,将用户的请求放入队列中,后台程序依次从队列中获取任务,处理并将结果返回到结果队列。函数

  2. LPUSH key value [value ...] 从队列的左边入队一个或多个元素,复杂度O(1)spa

  3. RPUSHX key value 从队列的右边入队一个元素,仅队列存在时有效。当队列不存在时,不进行任何操做。scala

  4. LPUSHX key value 从队列的左边入队一个元素,仅队列存在时有效。当队列不存在时,不进行任何操做。指针

  5. LPOP key 从队列的左边出队一个元素,复杂度O(1)。若是list为空,则返回null。code

  6. RPOP key 从队列的右边出队一个元素,复杂度O(1)。若是list为空,则返回null。

  7. BLPOP key [key ...] timeout 删除并得到该列表中的第一元素,或阻塞,直到有一个可用。
    timeout表示等待的时间,单位是秒。当设为0时,表示永远阻塞,非0时,表示等待的最长时间

  8. BRPOP key [key ...] timeout 删除并得到该列表中的最后一个元素,或阻塞,直到有一个可用

  9. RPOPLPUSH source destination 

    删除列表中的最后一个元素,将其追加到另外一个列表。

    这个命令能够原子性地返回并删除source对应的列表的最后一个元素(尾部元素),并将钙元素放入destination对应的列表的第一个元素位置(列表头部)。

    使用这个模式的客户端是易于扩展(scalable)且安全的(reliable),由于即便客户端把接收到的消息丢失了, 这个消息依然存在于队列中,等下次迭代到它的时候,由其余客户端进行处理。

  10. BRPOPLPUSH source destination timeout 

    弹出一个列表的值,将它推到另外一个列表,并返回它;或阻塞,直到有一个可用

    RPOPLPUSH的阻塞版本。timeout的单位是秒,当timeout为0的时候,表示无限期阻塞。

  11. LLEN key 得到队列(List)的长度

  12. LRANGE key start stop 从列表中获取指定返回的元素.

    负数表示从右向左数。超出范围的下标不会产生错误:若是start>end,会获得空列表,若是end超过队尾,则Redis会将其当作列表的最后一个元素
  13. LINDEX key index  获取一个元素,经过其索引列表

    以前介绍的操做都是对list的两端进行的,因此算法复杂度都只有O(1)。而这个操做是指定位置来进行的,每次操做,list都得找到对应的位置,所以算法复杂度为O(N)。list的下表是从0开始的,index为负的时候是从右向左数。-1表示最后一个元素。当下标超出的时候,会返回nul。因此不用像操做数组同样担忧范围越界的状况。
  14. LSET key index value 设置队列里面一个元素的值 当index越界的时候会报异常

  15. LREM key count value  从列表中删除元素

    该命令用于从key对应的list中,移除前count次出现 的值为value的元素。count参数有三种状况:

    count > 0: 表示从头向尾(左到右)移除值为value的元素。

    count < 0: 表示从尾向头(右向左)移除值为value的元素。

    count = 0: 表示移除全部值为value的元素。

  16. LTRIM key start stop  修剪到指定范围内的清单

    这个命令和LRANGE十分类似,LRANGE会将指定范围的元素返回给客户端,而LTRIM会对list进行修剪,使其只包含指定范围的元素。start和stop表示范围。

    超出范围的下标不会产生错误:若是start>end,会获得空列表,若是end超过队尾,则Redis会将其当作列表的最后一个元素。

  17. LINSERT key BEFORE|AFTER pivot value 在列表中的另外一个元素以前或以后插入一个元素

    该命令将value插入值key对应的列表的基准值pivot的前面或是后面。

    当key不存在时,这个list被视为空列表,任何操做都不会发生。

    当key存在,但保存的不是list,则会报error。

    该命令会返回修改以后的list的长度,若是找不到pivot,则会返回-1。

相关文章
相关标签/搜索