Redis
List
基本的数据类型,列表,可以实现 栈 队列
所有的list都以L开头
### PUSH ###
# LPUSH key element [element ...] 可同时push多个值
127.0.0.1:6379> LPUSH list one #插入列表的头部 栈顶
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LRANGE list 0 -1 # 查看列表的全部元素 LRANGE key start stop
1) "two"
2) "one"
127.0.0.1:6379> LRANGE list 0 1
1) "two"
2) "one"
127.0.0.1:6379> RPUSH list right #插到队列的尾部 栈的底部
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
3) "right"
### POP ###
127.0.0.1:6379> lpop list #移除列首 栈顶
"two"
127.0.0.1:6379> rpop list #移除列尾 栈底
"right"
### lindex key index###
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lindex list 0 #类似数组从左到右 0 -> max 第一个元素是0
"three"
127.0.0.1:6379> lindex list 1
"two"
### Llen key start stop查看长度 ###
127.0.0.1:6379> lpush list one
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> llen list #返回列表的长度
(integer) 3
### Lrem key count element 移除key中count个数指定元素 ###
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "three"
4) "two"
127.0.0.1:6379> lrem list 1 two
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "three"
3) "two"
### ltrim key start stop 截断###
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
### rpoplpush source destination 移除列表的最后一个元素放入新列表中###
127.0.0.1:6379> lpush list hello
(integer) 1
127.0.0.1:6379> lpush list hello1
(integer) 2
127.0.0.1:6379> lpush list hello2
(integer) 3
127.0.0.1:6379> lpush list hello3
(integer) 4
127.0.0.1:6379> rpoplpush list list2
"hello"
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
3) "hello1"
127.0.0.1:6379> lrange list2 0 -1
1) "hello"
### lset key index element ###
# 将列表中指定下标的值更新为另一个值
# 如果不存在列表就会报错 如果存在就会更新当前下标值
### linsert key BEFORE|AFTER pivot element
# 将world插入在item之前
127.0.0.1:6379> linsert list before item world
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "world"
2) "item"
3) "hello2"
4) "hello1"
# 将world插入在item之后
127.0.0.1:6379> linsert list after item world
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "world"
2) "item"
3) "world"
4) "hello2"
5) "hello1"
小结
-
实际上是一个双向链表,before node after left right都可以插入
-
如果key不存在,创建新链表
-
如果key存在,新增内容
-
如果移除了所有值,空链表,也代表不存在
-
在两边插入或者改动值,效率高,中间元素效率低
-
如果用LRANGE来获取数据,起始位置越大,速度越慢
list底层数据结构
127.0.0.1:6379> object encoding list
"quicklist"
Redis自己构件了链表的实现(c语言)
typedef struct listNode{
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}listNode
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;
Redis链表特性:
①、双端:链表具有前置节点和后置节点的引用,获取这两个节点时间复杂度都为O(1)。
②、无环:表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,对链表的访问都是以 NULL 结束。
③、带链表长度计数器:通过 len 属性获取链表长度的时间复杂度为 O(1)。
④、多态:链表节点使用 void* 指针来保存节点值,可以保存各种不同类型的值。