Redis的数据类型
String、List、Hash、Set 和
Sorted Set它们可以满足大多数的数据存储需求,但是在面对海量数据统计时,它们的
内存开销很大,而且对于一些特殊的场景,它们是无法支持的。
所以,Redis 还提供了 3
种扩展数据类型,分别是 Bitmap、HyperLogLog 和 GEO
Redis是一种 key : value 形式的非关系型数据库
其中,value 不仅可以是简单的变量类型,也可以是集合,map,object等类型
Redis的一个重点是快,能达到微妙级别,什么导致它快?
原因:它是一个内存级别的数据库!
使用Redis实现一个消息队列
实现消息队列的要素:
- 消息有序性(消费者需要按照生产者发送的顺序消费)List/Streams
- 重复消息处理(全局唯一ID)
- 消息可靠性保证(宕机是否有备份?)
Streams 是 Redis 专门为消息队列设计的数据类型,它提供了丰富的消息队列操作命令
Streams 类型存取消息的操作 XADD
XADD 命令可以往消息队列中插入新消息,消息的格式是键 - 值对形式。对于插入的每一
条消息,Streams 可以自动为其生成一个全局唯一的 ID。
当消费者需要读取消息时,可以直接使用 XREAD 命令从消息队列中读取
XREAD 在读取消息时,可以指定一个消息 ID,并从这个消息 ID 的下一条消息开始进行读
取。
另外,消费者也可以在调用 XRAED 时设定 block 配置项,实现类似于 BRPOP 的阻塞读
取操作。当消息队列中没有消息时,一旦设置了 block 配置项,XREAD 就会阻塞,阻塞的
时长可以在 block 配置项进行设置
举个例子,我们来看一下下面的命令,其中,命令最后的“$”符号表示读取最新的消息,
同时,我们设置了 block 10000 的配置项,10000 的单位是毫秒,表明 XREAD 在读取最
新消息时,如果没有消息到来,XREAD 将阻塞 10000 毫秒(即 10 秒),然后再返回。
下面命令中的 XREAD 执行后,消息队列 mqstream 中一直没有消息,所以,XREAD 在
10 秒后返回空值(nil)。
刚刚讲到的这些操作是 List 也支持的,接下来,我们再来学习下 Streams 特有的功能。
Streams是Redis 5.0 专门针对消息队列场景设计的数据类型,如果你的 Redis 是 5.0 及 5.0 以后的版本,就可以考虑把 Streams 用作消息队列了
1个小目标(亿)keys要统计,应该用什么集合
集合类型常见的四种统计模式,包括聚合统计、排序统计、二值状态统计和基数统计
- 聚合统计:常用于记录每天的新增数,或者累计数量
- 排序统计:所有评论中的最新留言
- 在 Redis 常用的 4 个集合类型中(List、Hash、Set、Sorted Set),List 和 Sorted Set
就属于有序集合。 - List 是按照元素进入 List 的顺序进行排序的,而 Sorted Set 可以根据元素的权重来排
序
- 在 Redis 常用的 4 个集合类型中(List、Hash、Set、Sorted Set),List 和 Sorted Set
- 二值状态统计
- 基数统计
如何保证时间序列
RedisTimeSeries
因为 RedisTimeSeries 不属于 Redis 的内建功能模块,在使用时,我们需要先把它的源码
单独编译成动态链接库 redistimeseries.so,再使用 loadmodule 命令进行加载,如下所
示:
当用于时间序列数据存取时,RedisTimeSeries 的操作主要有 5 个
用 TS.CREATE 命令创建时间序列数据集合;
用 TS.ADD 命令插入数据;
用 TS.GET 命令读取最新数据;
用 TS.MGET 命令按标签过滤查询数据集合;
用 TS.RANGE 支持聚合计算的范围查询。
与使用 Hash 和 Sorted Set 来保存时间序列数据相比,RedisTimeSeries 是专门为时间序
列数据访问设计的扩展模块,能支持在 Redis 实例上直接进行聚合计算,以及按标签属性
过滤查询数据集合,当我们需要频繁进行聚合计算,以及从大量集合中筛选出特定设备或
用户的数据集合时,RedisTimeSeries 就可以发挥优势了。
点查询,根据一个时间戳,查询相应时间的数据;
范围查询,查询起始和截止时间戳范围内的数据;
聚合计算,针对起始和截止时间戳范围内的所有数据进行计算,例如求最大 / 最小值,
求均值等。
RedisTimeSeries的劣势
RedisTimeSeries 模块。这是专门为存取时间序列数据
而设计的扩展模块。和第一种方案相比,RedisTimeSeries 能支持直接在 Redis 实例上进
行多种数据聚合计算,避免了大量数据在实例和客户端间传输。不过,RedisTimeSeries
的底层数据结构使用了链表,它的范围查询的复杂度是 O(N) 级别的,同时,它的 TS.GET
查询只能返回最新的数据,没有办法像第一种方案的 Hash 类型一样,可以返回任一时间
点的数据
在日常生活中,我们越来越依赖搜索“附近的餐馆”、在打车软件上叫车,这些都离不开
基于位置信息服务(Location-Based Service,LBS)的应用
GEO
以SortedSet 为数据基础
主要的作用是用来处理有关方位,地理位置上的计算问题。
比如打车的时候可以使用该数据结构,用来判断附近的车辆;
微信附近的人也可以使用该数据结构来是实现!!
开发一个新的数据类型
Redis 的基本对象结构
RedisObject 的内部组成包括了 type,、encoding,、lru 和 refcount 4 个元数据,以及 1
个*ptr指针。
type:表示值的类型,涵盖了我们前面学习的五大基本类型;
encoding:是值的编码方式,用来表示 Redis 中实现各个基本类型的底层数据结构,
例如 SDS、压缩列表、哈希表、跳表等;
lru:记录了这个对象最后一次被访问的时间,用于淘汰过期的键值对;
refcount:记录了对象的引用计数;
*ptr:是指向数据的指针。
了解了 RedisObject 结构后,定义一个新的数据类型也就不难了。首先,我们需要为新数
据类型定义好它的底层结构、type 和 encoding 属性值,然后再实现新数据类型的创建、
释放函数和基本命令
构,
例如 SDS、压缩列表、哈希表、跳表等;
lru:记录了这个对象最后一次被访问的时间,用于淘汰过期的键值对;
refcount:记录了对象的引用计数;
*ptr:是指向数据的指针。
了解了 RedisObject 结构后,定义一个新的数据类型也就不难了。首先,我们需要为新数
据类型定义好它的底层结构、type 和 encoding 属性值,然后再实现新数据类型的创建、
释放函数和基本命令