redis数据类型strings详解
redis数据类型keys详解
lists
单键多值
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
l就是left、左边,r就是right、右边
- 从表头插入一个或多个值。(头插)
lpush value1 value2......
有左边插入自然有右边插入,从右边插入就是把l改成r
- 从表尾插入一个或多个值。(尾插)
rpush value1 value2......
- 将值 value 插入到列表 key 的表头
lpushx key value
- 将值 value 插入到列表 key 的表尾
rpushx key value
lpushx与rpushx和lpush与rpush有什么区别吗?不都是push?不就是加了个x?功能都一样啊
当且仅当 key 存在并且是一个列表。lpushx和rpushx才会将值插入到列表,否则什么也不做。 而 lpush、rpush命令相反, 当 key 不存在时,会创建一个类型是list的key并插入值。
注意当值pop完之后键就会销毁
- 从表头吐出一个值。(头删)
lpop key
- 从表尾吐出一个值。(尾删)
rpop key
- 从 key1 列表右边吐出一个值,插到 key2 列表左边。
rpoplpush key1 key2
看到前面成双成对是不是认为还有个【lpoprpush】命令?
然而,并没有这个命令
- 按照索引下标获得元素(从左到右,从0开始)
lrange key start(起始下标) stop(结束下标)
lrange key 0 -1 表示获取全部值
- 按照索引下标获得元素(从左到右)
lindex key index
- 获得列表长度
llen key
- 在 列表key中 value 的前面插入 newvalue ,如果有多个value就在第一个value前插入
linsert key before value newvalue
- 在 列表key中 value 的后面插入 newvalue ,如果有多个value就在第一个value后插入
linsert key after value newvalue
在值前面插入就是before,值后面插入就是after
- 从列表key中左边删除n个value(从左到右),不足n个就删完,返回删除的个数
lrem key n value
- 将列表key下标为index的值替换成newValue
lset key index newValue
- 修剪一个已存在的 list,这样 list 就会只包含指定范围的指定元素。start 和 stop 都是由0开始计数的
ltrim key start stop
演示
#从列表key表头插入v1、v2、v3、v4
127.0.0.1:6379> lpush key v1 v2 v3 v4
#返回当前列表值的个数
(integer) 4
#从列表key表尾插入
127.0.0.1:6379> rpush key a b c
(integer) 7
#获取key列表全部的值(从左到右)
127.0.0.1:6379> lrange key 0 -1
1) "v4"
2) "v3"
3) "v2"
4) "v1"
5) "a"
6) "b"
7) "c"
# 从表头获取一个值
127.0.0.1:6379> lpop key
"v4"
127.0.0.1:6379> lpop key
"v3"
#从表尾获取一个值
127.0.0.1:6379> rpop key
"c"
127.0.0.1:6379> rpop key
"b"
127.0.0.1:6379> lrange key 0 -1
1) "v2"
2) "v1"
3) "a"
127.0.0.1:6379> lpop key
"v2"
127.0.0.1:6379> lpop key
"v1"
127.0.0.1:6379> lpop key
"a"
# 前面把列表key的值全部pop了
# 再判断当前库中键为key的列表是否存在
127.0.0.1:6379> exists lisi key
#返回0表示不存在,因为值pop完键就会销毁
(integer) 0
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> lpush key1 1 2 3
(integer) 3
127.0.0.1:6379> lpush key2 a b c
(integer) 3
127.0.0.1:6379> lrange key1 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> lrange key2 0 -1
1) "c"
2) "b"
3) "a"
# 从key1表尾pop出一个值,然后push到key2的表头
127.0.0.1:6379> rpoplpush key1 key2
# 从key1 pop出来要push到key2的值
"1"
127.0.0.1:6379> lrange key1 0 -1
1) "3"
2) "2"
127.0.0.1:6379> lrange key2 0 -1
1) "1"
2) "c"
3) "b"
4) "a"
# 从列表key1中获取下标为0的值
127.0.0.1:6379> lindex key1 0
"3"
# 获取列表key1的长度(元素个数)
127.0.0.1:6379> llen key1
(integer) 2
127.0.0.1:6379> llen key2
(integer) 4
127.0.0.1:6379> lrange key1 0 -1
1) "3"
2) "2"
# 在列表key1中第一个值为2的元素前插入a
127.0.0.1:6379> linsert key1 before 2 a
(integer) 3
127.0.0.1:6379> lrange key1 0 -1
1) "3"
2) "a"
3) "2"
127.0.0.1:6379> linsert key1 after 2 b
(integer) 4
127.0.0.1:6379> lrange key1 0 -1
1) "3"
2) "a"
3) "2"
4) "b"
127.0.0.1:6379> lpush key1 a
(integer) 5
127.0.0.1:6379> rpush key1 a
(integer) 6
127.0.0.1:6379> lrange key1 0 -1
1) "a"
2) "3"
3) "a"
4) "2"
5) "b"
6) "a"
# 在列表key1中从左到右删除2个值为a的元素,
127.0.0.1:6379> lrem key1 2 a
(integer) 2
127.0.0.1:6379> lrange key1 0 -1
1) "3"
2) "2"
3) "b"
4) "a"
127.0.0.1:6379> lindex 0
(error) ERR wrong number of arguments for 'lindex' command
127.0.0.1:6379> lindex key1 0
"3"
127.0.0.1:6379> lset key1 0 new
OK
127.0.0.1:6379> lrange key1 0 -1
1) "new"
2) "2"
3) "b"
4) "a"
127.0.0.1:6379> flushdb
OK
# key不存在就lpushx,不起任何作用
127.0.0.1:6379> lpushx key 1 2
(integer) 0
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> lpush k1 1
(integer) 1
# 查看k1是上面类型
127.0.0.1:6379> type k1
list
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush k1 1 2 3
(integer) 3
# del删除key可带值的类型也可以不带
127.0.0.1:6379> del list k1
(integer) 1
127.0.0.1:6379> lpush k a b c
(integer) 3
127.0.0.1:6379> del k
(integer) 1
数据结构
List的数据结构为快速链表quickList。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。
它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。
因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。
Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。