微信号:yogoup

介绍:网站性能提升与架构设计

Redis 新数据结构 - Streams

2017-10-13 20:02 杜亦舒

1. 为什么添加 Streams 数据流?

Stream 数据流的使用越来越多,Redis 的作者 antirez 也在积极思考,如何让 redis 能够很好的支持数据流的使用场景

antirez 认为 Redis 现有的数据结构都不能很好的处理数据流,例如:

(1)Sorted sets

有序集合中的元素根据他们的分值进行变化,不能自然的模拟不断被传递的消息,也不支持 client 阻塞等待新消息

(2)Lists

列表中的阻塞形式是一个元素对一个 client,并且 list 中的元素没有一个固定标识

(3)Pub/Sub

发布订阅适合一对多的场景,但元素是很快消失的,这样不符合某些场景的需求,例如需要保存历史数据的情况、连接断掉重连后需要重新获取消息的情况,再比如时间序列,范围查询很重要,如查询过去10秒钟我体温的监测数据

antirez 试图解决这些问题,例如是否可以给 Pub/Sub 添加历史记录、是否可以给 List 添加灵活的访问模式,但都不太理想,antirez 最后决定使用新的数据结构

2. 实现过程

antirez 受到一个 log 类型的 Redis module 启发,决定使用 log 来实现

log 是一个极其普通的东西,我们每个人都在用,就是打开文件以某种格式把数据追加进去

普通日志的 offset 是没有逻辑意义的,而且不好做垃圾回收,追加形式的日志很难移除旧数据,理想的形式是,指定一个数字,之前的老日志就被删除了

antirez 在开发 Redis Cluster 时使用的 radix 树正好为 Redis Stream 打下了很好的基础,可以达到空间和访问时间都很高效

antirez 也研究了 kafka 的思路(kafka 就是基于 log 的),借鉴了一些好的概念,例如 consumer groups

antirez 希望 Redis streams 能在事件、消息型应用中发挥重要作用,尤其是在 time series 场景中

3. 命令实例

Streams 的几个主要特点

  1. Streams 中的元素不是简单的字符串,而是由多组 field、value 构成的对象

  2. 范围查询方便而且高效

  3. 不同的 client 可以阻塞等待新的元素,而且可以指定从哪个 ID 开始

实例

> XADD mystream * sensor-id 1234 temperature 10.5
1506871964177.0

XADD 命令会把新元素添加到指定的 stream 中

这个例子中,mystream 是目标 stream,新的元素有2个 field,sensor-id temperature

同一个 stream 中的不同元素中的 field 是可以不同的,但使用相同的 field name 可以更有效的利用内存

XADD 的返回值是新插入的元素ID,例子中的 * 表示让 XADD 自动生成一个 ID,当然也可以自己指定一个 ID

ID 由2部分构成:毫秒值时间戳 + 序号,用 . 分隔,序号用来区分相同时间新加的元素

时间戳来自2方面,一是 Redis Server 本机的系统时间,二是 stream 中元素的最大时间值,生成 ID 时,会选取二者中的最大值,例如本机的时间被调小了,那么还可以保证ID是在继续增长的

> MULTI
OK
> XADD mystream * foo 10
QUEUED
> XADD mystream * bar 20
QUEUED
> EXEC
1) 1506872463535.0
2) 1506872463535.1

这个例子展示了批量快速插入,也可以看到不同元素中的 field 可以不同

> XRANGE mystream 1506871964177.0 1506871964177.0
1) 1) 1506871964177.0
   2) 1) "sensor-id"
      2) "1234"
      3) "temperature"
      4) "10.5"

XRANGE 命令用于从指定 stream 中获取某个范围的元素,参数分别是 stream 名称、开始位置、结束位置,开始和结束位置的元素是包括在内的 

4. 小结

Redis streams 将使 Redis 覆盖更多的使用场景,其中一个重要场景就是 time series,会在 4.0 系列版本中发布,大概是在年底,目前核心功能已经开发完成,有兴趣的话可以获取 Github 上的 streams 分支感受一下


点击 “阅读原文” 查看 文章列表

 
性能与架构 更多文章 Kafka 是否可以用做长期数据存储? 为什么我们需要区块链 Kafka 流数据 SQL 引擎 -- KSQL Redis Cluster 迁移案例 分布式 NoSql 数据库 Couchbase 的3个应用案例
猜您喜欢 《漫画:这两个愿望我实现了》,长大后我成了程序猿 如何像专业设计师一样,处理插画中的4大难题 想要这样一段不煽情,不鸡汤,不说教的家书来往 云计算“走出去”:机遇与挑战并存 PHP中Notice错误常见解决方法