前言

    Redis不仅仅是简单的键值对存储服务,它是一个支持 多种不同类型数据结构 数据的服务器。

它目前支持的数据类型:

  • Binary-safe String: 二进制安全字符串
  • List: 列表
  • Set: 集合
  • Sorted Set: 有序集合
  • Hash: 哈希
  • Bit Array:位数组,String的扩展
  • HyperLogLogs:概率数据结构
  • Stream:流

数据类型

Binary-safe String(二进制安全字符串)

String是Redis最基本、最简单的数据类型,它允许的最大密钥大小为512MB,同时,值也不能大于512MB,不过建议不要设置太长的key或value,否则它会给你带来巨大的内存开销。

同时,它是二进制安全的,所以它可以存储包括字符串在内的任何数据。

什么是二进制安全?

1
2
二进制安全功能(函数)是指在一个二进制文件上所执行的不更改文件内容的功能或者操作,
其本质上将操作输入作为原始的、无任何特殊格式意义的数据流,它保证了二进制数据的信息安全。

注:SETGET命令是我们设置和检索字符串值的方式

奇异的incr

1
2
3
看到这里,大家可能会疑惑了,我们在使用 incr/get 命令的时候,明明就是整型的数字啊!

因为Redis并没有整数类型,所以,INCR命令在执行的时候,会将字符串解析为一个整数,达到整型的效果。

List(列表)

List是字符串元素的有序集合,通过链表实现,按照插入的顺序排序,元素可重复

链表(Linked list)是一种线性表,是很常见的基础数据结构,在每一个节点里存到下一个节点的指针,由于不必按顺序存储。

所以链表在插入的时候可以达到O(1)的复杂度,无论你在 1万 还是 1千万 的列表中,在其 左侧 或 右侧 添加元素的速度都是 非常快的、相同的。

但是访问速度不是那么快了,查找一个节点或者访问特定编号的节点则需要O(n)的时间,特别是LRANGE命令,查询时间复杂度:O(S+N), S 为偏移量 start , N 为指定区间内元素的数量,时间复杂度与所访问元素的索引量成正比。

常用的相关命令:

命令 解释
LPUSH/RPUSH 将一个新元素到列表的左侧(头部)/右侧(尾部)
LRANGE 从列表中提取指定范围的元素
LPOP/RPOP 返回并移除列表左侧(头部)/右侧(尾部)的元素
LTRIM 修剪指定范围的列表,让列表只保留指定范围的元素
LLEN 获取列表的元素数量

适合的使用的场景:

  • 作为消息队列
  • 浏览足迹

Set(集合)

Set是字符串元素的无序集合,通过哈希表实现,元素不可重复

它的 添加、删除、查找 的复杂度都是 O(1)。

何为哈希表?

哈希表(Hash table)也被叫做散列表,它通过计算一个键值的映射函数(散列函数),将键(Key)映射到表中的一个位置,从而直接访问数据储存位置的数据结构,能带来极高的查询速度。

哈希算法是一种摘要算法,不同的数据产生定长的摘要,所以会产生碰撞冲突,为了解决数据冲突,会采用单独链表法将散列到同一个存储位置的所有元素保存在一个链表中。

Sorted Set(有序集合)

有序集合和集合Set的特性基本相同,唯一的区别在于它是有序的。

每个字符串元素都与score这个浮点数字值相关联。这个值就是它排序的分值(分值可以相同),根据这个分值实现元素的升序或降序排列。

适合的使用的场景:

  • 排行榜
  • 商品推荐

Hash(哈希)

Hash是一个由 字段 组成的映射表,也就是一个个键值对,字段和值都是字符串类型,你可以把它想象成Java里的HashMap<String,String>,一个Key对应一个HashMap。

相对单独使用 键值对 保存数据而言,使用Hash类型来存储,更加节省空间。

适合的使用的场景:

  • 购物车
  • 对象属性信息

Bit Array(位数组)

Bit Array不是实际的数据类型,而是在String类型上定义的一组面向位的操作,所以可以说它是String类型的一种扩展。

由于字符串是二进制安全,并且最大长度为512 MB,因此它们适合设置多达 2的32次方 个不同的字节。

Bit Array就是一个长度可变的bit数组,每个位只能存储0或1。

位操作分为两类:

  • 1,对单个位操作,把字段的某个位设置为 0或1
  • 2,对给定的位范围内,统计其设置的位(0或1)的数量

所以,它的最大优点是:在存储信息时可以节省大量空间,例如,在以增量用户ID表示不同用户的系统中,仅使用512MB内存就可以记住40亿用户的位信息

适合的使用的场景:

  • 数据去重

HyperLogLogs(概率数据结构)

HyperLogLogs是一种概率数据结构,用于对唯一元素进行计数(这里指集合的基数),它存在一定误差,但误差小于1%。

通常,对唯一元素进行计数需要保存元素本身,并使用与要计数的元素数量成比例的内存量。

而HyperLogLogs只需根据输入元素来计算基数,而不会储存输入元素本身,所以,无论元素的数量和体积有多大,计算基数所需的内存空间都是固定不变的,并且是很小,每个Key的占用内存不会超过12KB。

这个特性造就了它的价值,当然也丧失了获取元素的能力,不过获取元素的能力也不需要,所以根本不care。

相关命令:

命令 解释 示例
pfadd 添加一个或多个元素 pfadd k a b c
pfcount 获取Key的基数估算值 pfcount k
pfmerge 合并多个Key到一个新Key,如:将k1k2合并到newk pfmerge newk k1 k2

示例:

1
2
3
4
5
6
redis0> pfadd k a b c
1
redis0> pfadd k c d
1
redis0> pfcount k
4

适合使用的场景:

  • 记录网站访问量、PV、UV之类的数据

Stream(流)

Stream是Redis 5.0引入的新数据类型,它就像日志文件一样,仅以追加模式添加数据。

流与列表没有太大不同,只是附加的API更复杂,功能更强大。

它非常适合作为消息系统来使用,虽然 Redis 本身提供了发布订阅 (pub/sub) 来实现消息队列的功能,但是以前的发布订阅功能是有缺陷的,消息无法持久化,如果出现网络断开、Redis宕机等,消息就会被丢弃。

Stream流的工作方式截然不同,所有消息都将无限期保留在流中,除非用户明确要求删除,并且,丰富的API足以支撑整个消息系统的功能。