Redis五种基础数据结构

Redis可以做什么?

  • 记录帖子的点赞数、评论数、点击数(hash)
  • 记录用户的的帖子ID列表(排序),便于快速显示用户的帖子列表(zset)
  • 记录帖子的标题、摘要、作者和封面信息,用于列表页展示(hash)
  • 记录帖子的点赞用户ID列表,评论ID列表,用于显示和去重计数(zset)
  • 缓存近期热帖内容(帖子内容的空间占用比较大),减少数据库压力(hash)
  • 记录帖子相关文章ID,根据内容推荐相关帖子(list)
  • 如果帖子ID是整数自增的,可以使用redis来分配帖子ID(计数器)
  • 收藏集和帖子之间的关系(zset)
  • 记录热榜帖子ID列表、总热榜、分类热榜(zset)
  • 缓存用户行为历史,过滤恶意行为(zset、hash)

Redis 5种基础数据结构

  • string(字符串)
  • list(列表)
  • hash(字典)
  • set(集合)
  • zset(有序集合)
string(字符串)

字符串结构使用非常广泛,一个常见的用途就是缓存用户信息。我们将用户信息结构体使用json序列化成一个字符串,然后将它放进redis来缓存。

redis的字符串是`动态字符串`,是可以修改的字符串,采用预分配冗余空间的方式来减少内存的频繁分配, 当字符串长度小于1MB时,扩容是按加倍现有的空间,如果字符串长度超过1MB,扩容一次只会多扩1MB的空间。需要注意的是字符串最大长度为512MB

字符串由多个字节组成,每个字节又由8个bit组成,如此便可以将一个字符串看成很多bit组合,这便是bitmap(位图)数据结构。

list(列表)

redis的列表是类似于双向链表,双链表(双向链表)知道要删除某一节点p时,获取其前驱节点q的方式为 q = p->prior,不必再进行遍历。故时间复杂度为O(1)。而若只知道待删除节点的序号,则依然要按序查找,时间复杂度仍为O(n)。

但是,redis的列表准确是快速链表(quicklist)的结构。首先在列表元素较少的情况下,会使用一块连续的内存存储,这个结构是ziplist也就是压缩列表。它将所有的元素彼此紧挨一起存储,分配的是一块连续的内存,当数据比较多的时候才会改成quicklist。

hash(字典)

hash是一个无序字典,内存存储了很多键值对,实现结构是"数组+链表"二维结构,因为第一维的hash的数组位置会存在碰撞,如果多个key的hash值一样,就会使用链表串接起来(解决hash冲突的办法一般有线性探测法、二次探测法、链地址法、建立公共溢出区、多重散列法)

不同的是,redis的字典的值只能是字符串,redis的rehash采用的是渐进式rehash策略,渐进式rehash会在rehash的同时,保留新旧两个hash结构,查询时会同时查询两个hash结构,然后在后续的定时任我游以及hash操作指令种,循序渐进的将旧的hash内容一点点迁移到新的hash结构,当迁移完成时,就会使用新的hash结构取而代之,当hash移除最后一个元素后,该数据结构将被自动删除,内存被回收

set(集合)

redis的集合内部的键值对是无序的,唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value都是一个值NULL。

当集合中的最后一个元素被移除后,数据结构被自动删除,内存被回收。

set结构可以用来存储在某个活动中中奖的用户ID,因为有去重功能,可以保证同一个用户不会中奖两次

zset(有序集合)

有序集合的内部实现用的是一种或叫做 "跳跃列表"的数据结构

zset中最后一个value被移除后,数据结构被自动删除,内存被回收

zset可以用来存储粉丝列表,value值是粉丝的用户ID,score是关注时间,这样就可以根据关注时间来排序,用作学生成绩也是同理

容器型数据结构的通用规则

list、set、hash、zset这四种数据结构都是容器型数据结构,它们共享下面两个通用规则。

  • create if not exists: 如果容器不存在,就创建一个,在进行操作
  • drop if no elements:如果容器里没有元素,那么就立即删除容器,释放内存
标签:
作者:华传财
舞台上有你,就演好角色; 舞台上没你,就静静地做观众;

已有 0 位网友参与,快来吐槽:

发表评论