Redis 数据结构学习--String,List

361 阅读8分钟

redis 是一个 键值存储(key-value stores) 的内存结构存储,可用作数据库,缓存,消息代理。redis value 支持数据结构,有 String,List,Set,Hash,Sorted_set

1. String

String类型值只要可存储字符串、数值、bit型数据

1.1 字符串

SET key value [EX seconds|PX milliseconds][NX|XX] [KEEPTTL]

设置一个key 的字符串值
时间复杂度: O(1) 
NX:key不存在的时候才设置——分布式锁
EX:只有key存在的时候才操作

127.0.0.1:6379> set k1 hello
OK 

SETEX key seconds value

设置key值及其过期时间
时间复杂度: O(1)

OK
127.0.0.1:6379> get k1
"hello world" 

SETNX key value

设置key值,只有key 不存在时才设置成功
时间复杂度: O(1)

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 'hello'
OK
127.0.0.1:6379> SETNX k1 'world'
(integer) 0
127.0.0.1:6379> SETNX k2 'world'
(integer) 1
127.0.0.1:6379> mget k1 k2
1) "hello"
2) "world" 

PSETEX key milliseconds value

设置key值及其过期时间
时间复杂度: O(1)

127.0.0.1:6379> PSETEX k3 4000 v
OK
127.0.0.1:6379> get k3 

GET key

获取一个 key 的 value
时间复杂度: O(1)

127.0.0.1:6379> get k1
"hello" 

GETRANGE key start end

根据范围索引获取key的值
时间复杂度: O(N)

>127.0.0.1:6379> set k1 'hello world'
OK
127.0.0.1:6379> GETRANGE k1 0 4
"hello"

SETRANGE key offset value

根据范围设置 key 的 值
时间复杂度: O(1) --不计算将新字符串复制到位所需的时间
否则,复杂度为:O(M),其中M为值参数的长度.

127.0.0.1:6379> get k1
"hello world"
127.0.0.1:6379> SETRANGE k1 6 javahhh
(integer) 13
127.0.0.1:6379> get k1
"hello javahhh"

STRLEN key

获取key的值的长度
时间复杂度: O(1)

127.0.0.1:6379> get k1
hello javahh 中
127.0.0.1:6379> STRLEN k1
16 

GETSET key value

获取key 值,同时设置value 为key的新值
时间复杂度: O(1)

127.0.0.1:6379> get k1
hello javahh 中
127.0.0.1:6379> GETSET k1 'ddddddd'
hello javahh 中
127.0.0.1:6379> get k1
ddddddd

MSET key value [key value ...]

批量设置key-value
时间复杂度: O(N),其中N是要设置的键数

127.0.0.1:6379> mset k1 a k2 b k3 c k4 d
OK
127.0.0.1:6379> mget k1 k2 k3 k4
a
b
c
d 

MSETNX key value [key value ...]

批量设置key-value,有且只有key值都不存在时设置成功
时间复杂度: O(N),其中N是要设置的键数

127.0.0.1:6379> keys *
k2
k1
k3
k4
127.0.0.1:6379> MSETNX k4 e k5 f
0
127.0.0.1:6379> keys *
k2
k1
k3
k4
127.0.0.1:6379> MSETNX k5 e k6 f
1
127.0.0.1:6379> keys *
k6
k2
k4
k1
k3
k5
127.0.0.1:6379> mget k5 k6
e
f 

MGET key [key ...]

获取多个key的值
时间复杂度: O(N),其中N是要检索的的键数.

127.0.0.1:6379> mset k1 a k2 b k3 c k4 d
OK
127.0.0.1:6379> mget k1 k2 k3 k4
a
b
c
d 

1.2 数值

应用场景:抢购、秒杀、详情页、点赞、评论

INCR key

key 值自增1
时间复杂度: O(1) 

127.0.0.1:6379> INCR k1
1
127.0.0.1:6379> get k1
1 

INCRBY key increment

key 值自增 increment 
时间复杂度: O(1)

127.0.0.1:6379> INCRBY k2 3
3
127.0.0.1:6379> get k2
3

INCRBYFLOAT key increment

key 值自增 increment , 可为浮点数
时间复杂度: O(1)

127.0.0.1:6379> INCRBYFLOAT k4 0.5
0.5
127.0.0.1:6379> get k4
0.5

DECR key

key 值自减1 
时间复杂度: O(1)

127.0.0.1:6379> DECR k5
-1
127.0.0.1:6379> get k5
-1 

DECRBY key decrement

key 值自减 increment  时间复杂度: O(1)

127.0.0.1:6379> DECRBY k6 10
-10
127.0.0.1:6379> get k6
-10 

1.3 bitmap

SETBIT key offset value

设置或清除key处存储的字符串值中offset处的位.
时间复杂度: O(1) 
@ 的ascII 码:0100 0000

127.0.0.1:6379> SETBIT k1 1 1
0
127.0.0.1:6379> GETBIT k1 0
0
127.0.0.1:6379> GETBIT k1 1
1
127.0.0.1:6379> get k1
@
127.0.0.1:6379> STRLEN k1
1 

GETBIT key offset

返回key处存储的字符串值中offset处的位值
时间复杂度: O(1)

127.0.0.1:6379> SETBIT k1 1 1
0
127.0.0.1:6379> GETBIT k1 0
0
127.0.0.1:6379> GETBIT k1 1
1

BITOP operation destkey key [key ...]

在多个键(包含字符串值)之间执行按位运算,并将结果存储在目标键中
BITOP命令支持四个按位运算: AND , OR , XOR和NOT 
时间复杂度: O(N) 
A 的ascII 码:0100 0001
B 的ascII 码:0100 0010 
C 的ascII 码:0100 0011 
@ 的ascII 码:0100 0000

127.0.0.1:6379> mset k1 A k2 B
OK
127.0.0.1:6379> BITOP and andkey k1 k2
1
127.0.0.1:6379> BITOP or orkey k1 k2
1
127.0.0.1:6379> mget andkey orkey
@
C 

BITPOS key bit [start][end]

bit 在key 中 start end 区间内出现 1 的第一个位置
返回的是bit流数组的index
start end 区间 是字符数组范围
时间复杂度: O(N)

127.0.0.1:6379> get k1
A
127.0.0.1:6379> BITPOS k1 1 0 -1
1 

BITCOUNT key [start end]

返回start end 区间内出现 1 的个数
时间复杂度: O(N)

127.0.0.1:6379> get k1
A
127.0.0.1:6379> BITCOUNT k1 0 -1
2 

BITFIELD key [GET type offset][SET type offset value] [INCRBY type offset increment][OVERFLOW WRAP|SAT|FAIL]

将Redis字符串视为位数组,并且能够处理具有不同位宽和任意非(必要)对齐偏移量的特定整数字段. 
时间复杂度:每个指定的子命令为O(1)

1.4 其他

STRALGO LCS algo-specific-argument [algo-specific-argument ...]

对字符串进行运算的复杂算法
redis6.0 新增,目前值支持LCS(最长公共子字符串) 算法
KEYS:后接 key 
STRINGS:后接 字符串

127.0.0.1:6379> mset k1 'hello world' k2 'world is beautiful'
OK
127.0.0.1:6379> mget k1 k2
hello world
world is beautiful
127.0.0.1:6379> STRALGO lcs keys k1 k2
world
127.0.0.1:6379> STRALGO lcs strings '112***' '**223232'
**

2. List

list 类型是一个双向链表,数据可重复,数据依照添加顺序排序。

使用List 结构数据可以实现如下结构

  • 栈:同向命令
  • 队列:异向命令
  • 数值:LSET+LINDEX
  • 阻塞队列:LPUSH+BRPOP/ RPUSH BLPOP

数据结构如下图:

2.1 非阻塞操作—从队列头部操作

LPUSH key element [element ...]

添加一个或者多个值到 key
时间复杂度:每个添加的元素为O(1),O(N)要添加N个元素

127.0.0.1:6379> LPUSH k1 a b c d e f 
6

LPUSHX key element [element ...]

添加一个或者多个值到 key,key存在才操作
时间复杂度:每个添加的元素为O(1),O(N)要添加N个元素

127.0.0.1:6379> LPUSHX k1 pushx
7
127.0.0.1:6379> LPUSHX k2 pushx
0
127.0.0.1:6379> keys *
k1

LRANGE key start stop

返回 key中 start stop 索引区间内的数据
时间复杂度: O(S + N)
S是小列表到HEAD的起始偏移量,大列表到最近的头(HEAD或TAIL)的起始偏移量
N是指定范围内的元素数

127.0.0.1:6379> LRANGE k1 0 -1
f
e
d
c
b
a 

LPOP key

删除并返回列表第一个元素
时间复杂度: O(1)

127.0.0.1:6379> LPOP k1
f
127.0.0.1:6379> LRANGE k1 0 -1
e
d
c
b
a

LINDEX key index

返回key 中 index索引的值
时间复杂度: O(N)其中N是要遍历才能到达索引处元素的元素数

127.0.0.1:6379> LRANGE k1 0 -1
d
f
e
c
b
a
e
d
c
b
a
127.0.0.1:6379> LINDEX k1 0
d

LPOS key element [RANK rank] [COUNT num-matches] [MAXLEN len]

返回key中匹配到 element 的索引
RANK 指定起始索引位置,rank>= 0 正向匹配,rank<0 逆向匹配
COUNT 指定匹配成功返回值的个数
MAXLEN 指定匹配成功返回值索引的最大索引值
时间复杂度: O(N),其中N是平均情况下列表中元素的数量

127.0.0.1:6379> LPUSH k1 a b c e f d 
11
127.0.0.1:6379> LRANGE k1 0 -1
d
f
e
c
b
a
e
d
c
b
a
127.0.0.1:6379> LPOS k1 a 
5
127.0.0.1:6379> LPOS k1 a rank 2
10
127.0.0.1:6379> LPOS k1 a rank -2
5
127.0.0.1:6379> LPOS k1 b count 1
4
127.0.0.1:6379> LPOS k1 b count 0
4
9
127.0.0.1:6379> LPOS k1 b count 0 maxlen 4

127.0.0.1:6379> LPOS k1 b count 0 maxlen 9
4
127.0.0.1:6379> LPOS k1 b count 0 maxlen 10
4
9
127.0.0.1:6379> LPOS k1 b count 0 maxlen 0
4
9 

LINSERT key BEFORE|AFTER pivot element

在参考值pivot 前/后 加入element
时间复杂度: O(N)
N是在看到值轴之前要遍历的元素数
在列表(头)左端的某处插入可以视为O(1),而在右端(尾部)的某处插入则认为O(N)

127.0.0.1:6379> lpush k1 world hello world hello
4
127.0.0.1:6379> LRANGE k1 0 -1
hello
world
hello
world
127.0.0.1:6379> LINSERT k1 before world before
5
127.0.0.1:6379> LRANGE k1 0 -1
hello
before
world
hello
world
127.0.0.1:6379> LINSERT k1 after world after
6
127.0.0.1:6379> LRANGE k1 0 -1
hello
before
world
after
hello
world

LLEN key

返回key 长度
时间复杂度: O(1)

127.0.0.1:6379> LRANGE k1 0 -1
hello
before
world
after
hello
world
127.0.0.1:6379> LLEN k1
6 

LREM key count element

删除key中 element,共删除count个
count > 0 :删除等于element移动的元素的element.
count < 0 :删除等于从尾到头移动的element .
count = 0 :删除所有等于element .
时间复杂度: O(N + M),N是列表的长度,M是删除的元素数.

127.0.0.1:6379> LRANGE k1 0 -1
hello
before
world
after
hello
world
127.0.0.1:6379> LREM k1 2 world
2
127.0.0.1:6379> LRANGE k1 0 -1
hello
before
after
hello
127.0.0.1:6379> LREM k1 1 hello
1
127.0.0.1:6379> LRANGE k1 0 -1
before
after
hello

LSET key index element

将index处的list元素设置为element
时间复杂度: O(N),N是列表的长度将列表的第一个或最后一个元素设置为O(1).

127.0.0.1:6379> LLEN k1
3
127.0.0.1:6379> LSET k1 8 888
ERR index out of range
127.0.0.1:6379> LSET k1 0  888
OK
127.0.0.1:6379> LRANGE k1 0 -1
888
after
hello

LTRIM key start stop

根据索引范围[start stop]截取key,start和stop都是从零开始的索引
时间复杂度: O(N),其中N是要由操作删除的元素数.

127.0.0.1:6379> LPUSH k1 the world is so beautiful
5
127.0.0.1:6379> LTRIM k1 1 3
OK
127.0.0.1:6379> LRANGE k1 0 -1
so
is
world

2.2 非阻塞操作——从队列尾部操作

RPUSH key element [element ...]

添加一个或者多个值到 key
时间复杂度:每个添加的元素为O(1),O(N)要添加N个元素

127.0.0.1:6379> RPUSH k1 a b c d e f 
6
127.0.0.1:6379> LRANGE k1 0 -1
a
b
c
d
e
f

RPUSHX key element [element ...]

添加一个或者多个值到 key,key存在才操作
时间复杂度:每个添加的元素为O(1),O(N)要添加N个元素

127.0.0.1:6379> RPUSHX k1 h i g 
9
127.0.0.1:6379> RPUSHX k2 h i g 
0
127.0.0.1:6379> keys *
k1

RPOP key

删除并返回列表最后一个元素
时间复杂度: O(1)

127.0.0.1:6379> LRANGE k1 0 -1
a
b
c
d
e
f
h
i
g
127.0.0.1:6379> RPOP k1
g

RPOPLPUSH source destination

删除key为source中最后一个元素,并将改元素插入到 destination中
时间复杂度: O(1)

127.0.0.1:6379> LRANGE k1 0 -1
a
b
c
d
e
f
h
i
127.0.0.1:6379> RPOPLPUSH k1 k2
i
127.0.0.1:6379> LRANGE k1 0 -1
a
b
c
d
e
f
h
127.0.0.1:6379> LRANGE k2 0 -1
i
127.0.0.1:6379> RPOPLPUSH k1 k2
h
127.0.0.1:6379> LRANGE k2 0 -1
h
i

2.3 阻塞操作

BLPOP key [key ...] timeout

阻塞弹出List中第一个元素,如果list为空,阻塞连接,直到timeout之后
时间复杂度:O(1)

127.0.0.1:6379> BLPOP k1 1
k1
a
127.0.0.1:6379> BLPOP k3 1

BRPOP key [key ...] timeout

阻塞弹出List中最后个元素,如果list为空,阻塞连接,直到timeout之后
时间复杂度: O(1)

127.0.0.1:6379> BRPOP k1 1
k1
f
127.0.0.1:6379> BRPOP k3 1000
k3
3

BRPOPLPUSH source destination timeout

阻塞删除key为source中最后一个元素,并将改元素插入到 destination中
时间复杂度: O(1)

127.0.0.1:6379> BRPOPLPUSH k3 k4 10000
3333
127.0.0.1:6379> LRANGE k4 0 -1
3333
127.0.0.1:6379> LRANGE k3 0 -1