Linvis Blog

Redis的数据类型

2020-04-11

Redis的数据类型

string

基本操作

1
set key value
1
get key

过期时间

1
2
3
4
5
6
7
8
9
10
11
# 单位是秒
set a b ex 10

# 毫秒
set a b px 1000

# s
expire a 10

# 查看过期时间
ttl a

查询长度

1
strlen key

字符串操作

如果value是数字,还可以执行基本的数学运算

1
2
3
4
set a 1

incrby a 5
# a = 6

获取子串

1
2
# a[2:5]
getrange a 2 5

这是一个前闭后闭的操作,比如 a = 1234567

上述操作会获得 3456

覆盖子串

1
setrange a 2 abcdef

相当于a[0:2] + newval,这里的a[0:2]是前开后闭

追加子串

1
append a abcdef

基本实现

就是往db(哈希表)里插数据

list

redis使用双向链表存储list的元素,所以不是数组,因为是链表,查找能力弱,如果数据量很大,时间复杂度就会升高

支持负下标,和python一样

list不能用set/get操作

list增删操作

1
2
3
4
5
6
7
8
9
# 从尾部增加
rpush key val1 val2

# 从头部增加
lpush key val1 val

lpop key

rpop key

这四种操作,不同组合,可以构成队列,栈等数据结构

获取list长度

1
llen key

随机读

1
2
3
4
5
6
7
8
# 读a[1]
lindex a 1

# a[0:]
lrange a 0 -1

# a [1:3] a[1] a[2] a[3]
larnge a 1 3

修改元素

1
2
3
4
5
6
# a[1] = newval
lset a 1 newval

# 在java前/后插入python
# rpust a go java c
linsert a before/after java python

linsert为什么不用index?

分布式环境中,列表的元素会频繁的变动,index也会随之变动,但是val不会

删除特定元素

1
2
# 1表示最大删除一个元素
lrem a 1 java

也是靠值删除

定长列表

比如top10等等

1
2
3
4
5
6
7
8
> rpush ireader go java python javascript ruby erlang rust cpp
(integer) 8
> ltrim ireader -3 -1
OK
> lrange ireader 0 -1
1) "erlang"
2) "rust"
3) "cpp"

list的基本实现

redis采用了quicklist的数据结构,这是一个双向链表,而和不同的双向链表不同的是,链表节点上存储的并不是数据,而是ziplist,ziplist是为了解决链表造成的存储碎片化,一个quicklistNode上,存储一个ziplist,最大可以存16个item,这些ziplist的item在内存存储上,是紧挨着的。

简单类比,ziplist相当于一个内存池,并且具有压缩编码功能。

典型的是,如果value是整数,ziplist会把字符转成整型,并且根据整数的大小,选择不同的整型存储(省内存)

ziplist原理

hash

等价与python中的dict

增加元素

1
2
hset key field1 val1 field2 val2
hmset key field1 val1 field2 val2

获取元素

1
2
3
4
5
hget key field1
hmget key field1 field2
hgetall key
hkeys key
hvals key

删除元素

1
2
hdel key field
hdel key field1 field2

判断元素是否存在

1
2
hexists key field
# 1 - yes, 0 - not

计数器

1
2
hincrby key field num
# hincrby language go 2

这个value需要是整数

hash的基本实现

hash,首先会用ziplist存,会存两个信息,第一个是field,紧挨着下一块内存会存value

当ziplist的大小超过一个阈值后,默认512,就会把ziplist转成dict,读取更高效

1
2
3
#define OBJ_HASH_MAX_ZIPLIST_ENTRIES 512

hash_max_ziplist_entries

dict的实现

redis采用了哈希表的方式,即一个大表,hash值%size的方式维护索引,为了避免碰撞,采用链表定址法,hash值相同的挂链表索引。

装载过小就会扩容,过大会缩容。扩容不是一次性copy old to new。而是摊还copy(扩容后先查新,没有就查旧,然后copy旧到新)

set

介于list和hash之间,set不允许有重复的value出现

增加元素

1
2
3
4
5
6
7
8
9
10
sadd key val1 val2 val3

# 列出所有
smembers key

# 读取长度
scard key

# 随机读取一个元素
srandmember key

删除元素

1
2
3
4
srem key val1 val2

# 随机删除一个元素
spop key

判断元素是否存在

1
2
sismember key val
# 1 - yes, 0 - no

set的基本实现

dict的key

如果val都是int,则用了intset的实现方式,string转int,用数组存整数(类似ziplist),并且通过二分,保证插入是有序的,查找是二分查找

zset(sortset)

set的基础上,每个val都有一个权重score,内部按照score排序

可以理解成sort set

增删元素

1
2
3
4
5
6
7
zadd a 2.0 val1 3.0 val2

# 长度
zcard a

# 删除元素
zrem a val1 val2

score排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 获取val的score
zscore a val1

# 获取排序后的index,score小的在前
zrank a val1

# 倒序index
zrevrank a val1

# 获取所有元素
zrange a 0 -1
zrange a 0 -1 withscores
zrevrange a 0 -1 withscores

# 范围获取
# 获取前6
zrangebyscore a 0 5
# 所有
zrangebyscore ireader -inf +inf withscores
# 倒序
zrevrangebyscore ireader +inf -inf withscores

# 范围删除
# score在0 - 1的都删掉
zremrangebyrank a 0 1
zremrangebyscore ireader -inf 4

zset的基本实现

链表存数据,跳表实现排序

Tags: Backend

扫描二维码,分享此文章