Redis深度历险笔记(1):基础数据结构篇
Redis
- 全称:远程字典服务(Remote Dictionary Service),从名字可以看出来Redis是一个key-value形的非关系型数据库(NoSQL),貌似除了windows系统都支持
- 应用:缓存,分布式锁,等
- 默认端口:6379
- 安装(centos):
yum intall redis
- 运行:
redis-cli
万丈高楼平地起:支持的五种数据结构
类型 | 作用 |
---|---|
string | 字符串 |
list | 列表 |
hash | 字典 |
set | 普通集合 |
zset | 有序集合 |
-
redis是
KV
数据库,所有数据结构都是针对value
定义的,因为key
只能是string类型 -
string:Redis中最基础的数据结构,所有key都是string类型的
- 使用场景1:序列化将用户信息(可能是不同数据结构)统一映射成字符串缓存起来,用户使用的时候再通过反序列化来获取
- 动态扩容:会动态分配空间,一旦字符串的长度大于已分配容量,那么将会扩容,扩容的方式是,小于
1M
的时候,加倍扩容,大于1M
的时候,每次只会增加1M
,最大支持512M
的字符串。 - 字符串通过
bitmap
实现,不过这是后话
-
list:双向链表,起源类似java中的
LinkedList
,但是其实不完全一样,在redis中用到的其实是优化过的链表,称为quicklist
。-
quicklist
: 在列表元素少的情况下,使用一块连续的内存存储,类似数组,这一块连续的内存称为zplist
,因为是连续内存,因此块内支持随机寻址,只需要直到头节点的地址即可。当元素较多的时候,quicklist
会将所有元素分割成一跨快的zplist
-
zplist
的使用降低了内存开销,因为只需要让zplist的头部和尾部添加两个方向的指针就可以,在大量数据的情况下,节约了很多没必要的指针空间。
-
-
list:单纯插入和删除操作都是
o(1)
,但是索引则是o(n)
,因为内存不连续,无法通过头部+偏移
来直接定位 -
使用场景:进程间通信的消息队列,将需要延后处理的任务结构体序列化成字符串,插入链表中,其他进程根据字符串查找要处理的任务
-
list利用
lpop
,rpop
和lpush
,rpush
可以适配成栈或者队列 -
遍历操作会随着key的增加而变慢
-
-
hash:无序字典,结构是数组槽+链表(开链法哈希),数组的每个槽都代表一个
key
,槽后连接的链表就是value- 扩容:扩容由于内存是重新开辟的,因此原先的key所处的地址无效了,因此需要进行一个rehash过程。redis为了追求性能,使用了渐进式rehash的操作。
- 渐进式rehash:在rehash的同时,保留旧的hash结构,查询key的时候会在现在旧的hash表找,然后再往新的hash表找,在后续的任务中再一点点将旧的hash表移动到新的hash表中,当最后一个元素都移动完成,就删除旧的哈希表。
- 使用场景:不需要序列化整个对象,可以单独存储用户每个字段,实现数据的部分获取。
- 缺点:哈希表存储高于字符串。
-
set:与
hashset
类似,用于实现去重功能 -
zset:有序的set,为每个value设置一个权重,从而实现排序功能,内部数据结构是跳表。
- 使用场景:存储学生成绩,value是ID,socre是成绩
-
跳表
:多层链表,第一层存储所有数据,第二层在第一层的基础上,以每个节点50%
的概率抽取出来形成新的链表,第第三层在第二层的基础上抽取,以此类推,形成多级索引结构。
基本操作
操作 | 参数 | 作用 |
---|---|---|
set |
key value |
定义一个k-v对 |
get |
key |
查询key对应的value |
exists |
key |
查询key是否存在 |
del |
key |
删除key,返回是否成功 |
mset |
key1 value1 … keyn valuen
|
设置多个k-v对 |
mget |
key1 ... keyn |
返回多个key对应的value |
expire |
key time(s)
|
设置key过期时间,过期自动删除 |
setex |
key time value
|
set +expire
|
setnx |
key value
|
判断key 是否存在,不存在才创建 |
incr |
key |
value是整形就自增,范围是signed long ,越界报错 |
incrby |
key num
|
增加num ,可以是负数 |
参考资料
- 《Redis》深度历险
- 漫画算法:什么是跳跃表?