Redis Value的数据结构,以及决定了哪些使用场景

157 阅读4分钟

一、Redis的数据结构概述

Redis本质上是一款内存存储系统,与其他任何存储系统一样,Value值在数据结构上其实都划分为对外(使用者视角)的数据结构,以及对内(服务器)的内部编码两类。

1.1 使用者视角的数据结构

包括以下五种:

  • string——字符串
  • hash——哈希
  • list——列表
  • set——集合
  • zset——有序集合

这些都是Redis对外的数据结构。

1669795503993.png

1.2 服务器存储角度的内部编码

上面的每种数据结构都有自己底层的内部编码实现,而且不止一种实现。

Redis底层存在多种内部编码实现,以应对不同场景选择合适的内部编码。

1669796455849.png

这样设计,与MySQL可插拔存储引擎有异曲同工之妙。

其一,将对外的数据结构与内部编码分开,可以在不影响用户使用的同时,可以迭代改进内部编码,只要一旦有更优秀的内部编码被开发出来,可直接进行替换,而用户几乎不用感知。

其二,在不同的使用场景下,可以针对性的使用更合适的内部编码,可以借助配置参数让redis自动去适配。

二、使用场景

2.1 字符串使用场景

字符串类型的值,可以是字符串,包括简单的字符串和诸如JSON、XML等的复杂字符串,数字(整数、浮点数),甚至二进制(图片、音频、视频),但是值最大不能超过512M。

字符串类型的内部编码有以下3种:

  1. int:8个字节的长整型
  2. embstr: 小于等于39个字节的字符串
  3. raw:大于39个字节的字符串

Redis会根据当前值的类型和长度决定使用哪种内部编码实现。

使用场景:

  1. 缓存功能

这应该是Redis被使用最多的场景,也是比较典型的场景。一般用作应用和数据库两者之间的加速层,减少数据库的压力。

  1. 计数

常见于朋友圈点赞数、微博点赞数、视频播放网站上的视频播放数等。

  1. 共享session

用于集中管理web服务器的session。

  1. 限速

常用于用户每分钟获取手机验证码的频率,比如一分钟不能超过5次的场景。

2.2 哈希使用场景

哈希类型的内部编码有两种:

  1. ziplist,压缩列表

当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储。

  1. hashtable,哈希表

当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

使用场景:

用于缓存整个对象类型数据。如果一个对象的某些字段经常需要一起使用,很少分开单独使用的话,就可以将这些字段作为一个整体对象,使用哈希结构缓存。

2.3 列表使用场景

列表的内部编码实现有两种:

  1. ziplist,压缩列表

当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于 list-max-ziplist-value配置(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。

  1. linkedlist,链表

当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。

使用场景:

  1. 消息队列

Redis的lpush+brpop命令组合即可实现阻塞队列,生成者客户端使用lrpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用。

  1. 文章列表

博客系统每个用户都有属于自己的文章列表,可借助Redis的集合类型实现分页展示文章列表的需求。因为列表是有序的,而且支持按照索引范围获取元素。

2.4 集合使用场景

集合的使用场景是标签(tag)。

2.5 有序集合使用场景

有序集合使用场景是排行榜系统。