目录
引言
Stream 类型
Geospatial 类型
HyperLogLog 类型
Bitmaps 类型
Bitfields 类型
引言
- Redis 最关键(应用广泛、频繁使用)的五个数据类型
- String
- List
- Hash
- Set
- ZSet
- 下文介绍的数据类型一般适合在特定的场景中使用!
Stream 类型
- Stream 类型可理解为一个阻塞队列,可用记录和模拟实时的事件
什么是事件?
- 有些操作,我们无法知道它啥时候会出现,所以只能等到这个事情出现了之后,再采取相应的动作来处理该事件!
实例理解
- JavaScript 中包含有 点击事件、键盘事件、窗口大小改变、位置改变事件 等
- epoll 是 Linux 中特定的 I/O 多路复用机制,用于监视多个文件描述符的事件,每当 网卡 或 socket 上有可读可写的数据时,epoll 便会使用 事件回调机制 来通知应用程序
总结:
- 官方文档的意思为 steam 类型可以用来模拟实现这种事件传播的机制
应用场景
- stream 类型是 Redis 作为消息队列的重要支撑,属于 List 类型中 blpop 和 brpop 命令的升级版
Geospatial 类型
- Geospatial 类型是指一组用于存储地理空间信息(地理位置)的数据结构和相关操作
- 该类型主要用来存储坐标的(经纬度)
应用场景
- 存储了一些坐标点后,便可让用户给定一个坐标,然后从刚才存储的坐标点中进行相应的查找
- 比如 按照半径、矩形区域 等
- 此处我们指定了一个坐标,并想要查找附近的美食,此时地图上便会标识出符合要求的坐标位置
HyperLogLog 类型
- HyperLogLog 类型不是 Redis 专有的类型,属于一种思想方法!
- HyperLogLog 类型可用于 估算 集合中的不重复元素的个数
应用场景
- Set 类型存在一个应用场景,即统计服务器的 UV (用户的访问次数)
明确:
- 使用 Set 类型固然可以统计 UV,但是当 UV 的数据量非常大时,使用 Set 类型便会消耗很多内存空间
实例理解
- 使用 Set 类型存储 userId,且单个 userId 按 8 字节算
- 1亿 UV ——> 8 亿字节 ——> 0.8G ——> 800MB
- 使用 Set 类型存储一亿个 userId 便需要消耗 800MB 的内存空间
- 如果使用 HyperLogLog 类型,则最多消耗 12KB 的内存空间,便可实现上述效果!
重点理解:
- 之所以 Set 类型要消耗这么大的空间,是因为 Set 类型需要存储每个元素
- 而 HyperLogLog 类型却无需存储元素的内容,也能判断当前元素是否为重复元素
- 因为 HyperLogLog 类型会提取新增元素的特征,并利用该特征来判断后续新增的元素是否为重复元素!
通俗理解:
- HyperLogLog 类型适合用来计数,即记录出当前集合有多少个不同元素,但无法告诉你这些元素的内容是什么
注意:
- HyperLogLog 类型并不具有 100% 的精确性,即存在一定的误差!
- 官方文档描述误差大概为 0.81%
Bitmaps 类型
- Bitmaps 类型使用 bit 位来表示整数
- 位图(bitmaps)本质上还是一个集合,属于 Set 类型针对整数的特化版本
- 其目的也还是为了节省空间,且也因为计算机进行位运算一般都是比较高效的
问题:
- 相比于使用 Bitmap 类型,使用 HyperLogLog 类型更节省空间呀?
明确:
- HyperLogLog 类型即可以存储数字,也可以存储字符串,但是 不存储元素内容,仅有计数效果
- 因为 Hyperloglog 类型在存储元素的时候,提取特征的过程 是不可逆的!
- 而 Bitmap 类型是实实在在存储了元素,即 可以通过遍历精确知道哪些元素已经存储
总结:
- 通常我们首选还是使用 Set 类型,因为 Set 类型更加通用!
- 如果存在这种极端的特定场景,再进而考虑使用 Bitmap 类型、Hyperloglog 类型
Bitfields 类型
- Redis 的位域(bitfields)允许您设置、递增和获取任意位长度的整数值
- 位域(bitfields)相较于之前的 String 、Hash 类型来说,其目的也是为了节省空间!
辅助理解:
- C 语言中的位域 是一种结构体成员的特殊用法,允许你在内存中以位为单位对数据进行紧凑的存储
- 位域 本质上是让我们进行精确位操作的一种方法
重点理解:
- Bitfields 类型与 C 语言中的位域非常相似
- Bitfields 类型可以理解成一串二进制序列(字节数组)
- 程序员可以将这个字节数组中的某几个位赋予特定的含义,并且可以针对这某几个位进行 读取、修改、算数运算等相关操作
实例理解
- 此处我们需要针对页游初始化新玩家的 金币数
- 因此我们可以给每个玩家均分配一个位域,以此来表示每个玩家的 金币数
- 此处假设每个新玩家初始状态均有 1000 金币
> BITFIELD player:1:stats SET u32 #0 1000 1) (integer) 0
- 使用 BITFIELD 命令来进行操作
- "player:1:stats" 为 key 值
- "SET" 属于 BITFIELD 命令下的一个子命令
- "u32" ——> unsigned 32 ——> 无符号操作 32 个 bit 位
- "#0" 相当于一个标签,此处表示 金币数
- "1000" 设置的初始值 1000 金币