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的链表的实现的主要特性:算法
a,评论系统数组
相似微博, 在看完一条微博以后,经常会评论一番,或者看看其余人的吐槽。每条评论的记录都是按照时间顺序排序的。读的时候也是这个顺序。这时,队列就是一个很好的存储结构。每提交一次评论,都向list的末尾添加一个新的节点。安全
b,并行转串行数据结构
用户每时每刻均可能发出请求,并且请求的频率常常变化。这时,后台的程序不可能马上响应每个用户的请求,尤为是请求特别占资源的服务的时候(双11的时候,404页面?)。有什么好的办法来解决这个问题呢?须要一个排队系统。根据用户的请求时间,将用户的请求放入队列中,后台程序依次从队列中获取任务,处理并将结果返回到结果队列。函数
LPUSH key value [value ...] 从队列的左边入队一个或多个元素,复杂度O(1)spa
RPUSHX key value 从队列的右边入队一个元素,仅队列存在时有效。当队列不存在时,不进行任何操做。scala
LPUSHX key value 从队列的左边入队一个元素,仅队列存在时有效。当队列不存在时,不进行任何操做。指针
LPOP key 从队列的左边出队一个元素,复杂度O(1)。若是list为空,则返回null。code
RPOP key 从队列的右边出队一个元素,复杂度O(1)。若是list为空,则返回null。
BLPOP key [key ...] timeout 删除并得到该列表中的第一元素,或阻塞,直到有一个可用。
timeout表示等待的时间,单位是秒。当设为0时,表示永远阻塞,非0时,表示等待的最长时间
BRPOP key [key ...] timeout 删除并得到该列表中的最后一个元素,或阻塞,直到有一个可用
RPOPLPUSH source destination
删除列表中的最后一个元素,将其追加到另外一个列表。
这个命令能够原子性地返回并删除source对应的列表的最后一个元素(尾部元素),并将钙元素放入destination对应的列表的第一个元素位置(列表头部)。
使用这个模式的客户端是易于扩展(scalable)且安全的(reliable),由于即便客户端把接收到的消息丢失了, 这个消息依然存在于队列中,等下次迭代到它的时候,由其余客户端进行处理。
BRPOPLPUSH source destination timeout
弹出一个列表的值,将它推到另外一个列表,并返回它;或阻塞,直到有一个可用
RPOPLPUSH的阻塞版本。timeout的单位是秒,当timeout为0的时候,表示无限期阻塞。
LLEN key 得到队列(List)的长度
LRANGE key start stop 从列表中获取指定返回的元素.
负数表示从右向左数。超出范围的下标不会产生错误:若是start>end,会获得空列表,若是end超过队尾,则Redis会将其当作列表的最后一个元素LINDEX key index 获取一个元素,经过其索引列表
以前介绍的操做都是对list的两端进行的,因此算法复杂度都只有O(1)。而这个操做是指定位置来进行的,每次操做,list都得找到对应的位置,所以算法复杂度为O(N)。list的下表是从0开始的,index为负的时候是从右向左数。-1表示最后一个元素。当下标超出的时候,会返回nul。因此不用像操做数组同样担忧范围越界的状况。LSET key index value 设置队列里面一个元素的值 当index越界的时候会报异常
LREM key count value 从列表中删除元素
该命令用于从key对应的list中,移除前count次出现 的值为value的元素。count参数有三种状况:
count > 0: 表示从头向尾(左到右)移除值为value的元素。
count < 0: 表示从尾向头(右向左)移除值为value的元素。
count = 0: 表示移除全部值为value的元素。
LTRIM key start stop 修剪到指定范围内的清单
这个命令和LRANGE十分类似,LRANGE会将指定范围的元素返回给客户端,而LTRIM会对list进行修剪,使其只包含指定范围的元素。start和stop表示范围。
超出范围的下标不会产生错误:若是start>end,会获得空列表,若是end超过队尾,则Redis会将其当作列表的最后一个元素。
LINSERT key BEFORE|AFTER pivot value 在列表中的另外一个元素以前或以后插入一个元素
该命令将value插入值key对应的列表的基准值pivot的前面或是后面。
当key不存在时,这个list被视为空列表,任何操做都不会发生。
当key存在,但保存的不是list,则会报error。
该命令会返回修改以后的list的长度,若是找不到pivot,则会返回-1。