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