5.6 KiB
- String
- hash
- list
- set
- zset
一、数据结构
1. string
字符串由多个字节组成,每个字节由8个bit组成,可以将一个字符串看成很多bit的组合,这就是bitmap数据结构。
redis提供的字符串是动态字符串,是可以修改的字符串,内部使用数组结构实现,采用预分配冗余空间的方式来减少内存的频繁分配,如图所示预分配的空间capacity要高于实际字符串长度len。
!
当字符串长度小于1MB时,扩容都是加倍现有空间。如果字符串长度超过1MB,扩容时一次只会多扩1MB空间,并且字符串最大长度为512MB。
1.1常用命令
1.1.1 键值对
1.1.2 批量键值对
1.1.3 过期和set命令扩展
对key设置过期时间,到期自动删除
!
等价命令 setex name 3 zr 等价于set + expire
!
setnx name zr 如果name不存在则创建
!
1.1.4 计数
如果value值是一个整数,可以对它进行自增操作,自增范围在long的最大值和最小值之间
!
2.list
Redis的list相当于Java的LinkedList,是链表不是数组。插入和删除很快,时间复杂度为O(1)。索引定位慢,时间复杂度为O(n)。list的每个元素都使用了双向指针,可以支持前向后向遍历,因此可以作为队列或栈使用。
!
2.1 常用命令
2.1.1 队列
队列是先进先出的数据结构,用于消息排队和异步逻辑处理。支持左进右出、右进左出,会确保元素的访问顺序性。
!
注:使用pop命令后元素会删除
2.1.2栈
2.1.3慢操作
lindex类似于java的get(int index)方法,需要对list进行遍历,性能随着参数index增加而变差。
ltrim类似于截取操作,由两个参数start_index和end_index定义一个区间,保留在区间内的值,区间外的删除,可以用来实现一个定长的链表。
index可以为负数,index=-1表示倒数第一个元素,同理index=-2表示倒数第二个元素。
!
2.2底层数据结构(quicklist)
实际上Redis的list并不是一个简单的linkedlist,而是quicklist(快速链表)。
在元素较少情况下,会使用一块连续的内存存储,这个结构是ziplist(压缩列表)。将所有的元素彼此紧挨着存储,也可以看作是数组结构。当数据量比较多的时间才会变成quicklist,因为普通的链表需要的附加指针空间(前后指针),所以Redis将链表和ziplist结合组成quicklist,将多个ziplist使用双向指针连接使用。
quicklist内部默认单个ziplist长度为8kb,超过这个字节数,就会另启一个ziplist
!
3.hash
Redis字典相当于Java的HashMap,属于无序字典,在数据结构上使用的是数组+链表也就是散列表结构。
!
3.1 常用操作
获取字典中的所有值
3.2 底层数据结构
采用于HashMap相同的散列表结构,redis字段的值只能是字符串
!
3.2.1 rehash
Redis为了追求高性能采用了渐进式rehash策略,可以不堵塞服务,但是需要牺牲空间,可以理解为空间换时间。渐进式rehash会在执行同时保留新旧两个hash结构,查询时会同时查询两个hash,然后再后续的定时任务以及hash操作指令中,循序渐进地将旧hash的内容迁移到新hash结构,当迁移完成就使用新hash代替。(空间换时间)
!
3.3优缺点
hash结构可以结构化存储用户信息,相比于json存储,可以单独获取或修改某几个字段。如果以整个字符串形式保存的话只能一次性读取,比较浪费流量。缺点是存储消耗要高于单个字符。
4.set
相当于Java的HashSet,其内部键值对是无序且唯一的,内部实现相当于一个特殊的字典,字典中所有的value都是NULL
4.1 常用操作
查询某个值是否存在
获取长度
弹出一个
5.zset
类似于Java的SortedSet和HashMap结合体,set保证内部value的唯一性,另外可以给每个value赋予一个score代表排序权重,内部是使用‘跳跃列表’实现。
!
5.1 常用操作
逆序输出
统计
获取指定value的score
排名
删除value
根据score区间遍历
5.2 底层数据结构(跳跃列表)
查看数据结构相关文档
5.3 假如元素score值相同
zset的排序元素不只看score值,如果score相同还会比较value值(字符串比较)