温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Redis中的Redis Streams有什么作用

发布时间:2021-11-17 14:45:26 来源:亿速云 阅读:175 作者:iii 栏目:大数据

这篇文章主要讲解了“Redis中的Redis Streams有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis中的Redis Streams有什么作用”吧!

Streams是steroids上的CSV文件

如果你想记录一系列的结构化数据,并且确定数据库是足够大的,你可能会说:我们以追加写入的方式打开一个文件,每一行记录是一个CSV数据项:

time=1553096724033,cpu_temp=23.4,load=2.3
time=1553096725029,cpu_temp=23.2,load=2.1

这看起来很简单,然后人们一直这样做了好多年,并且一直持续着:如果你知道你在做什么,那么这将成为一种固定的模式。如果同样的事情发生在内存中会怎样呢?内存的顺序写入能力更强,并且会自动移除掉CSV文件的一些限制:

  1. 很难批量查询

  2. 太多的冗余信息:每个条目的时间几乎相同,字段也相同。但是移除字段会降低灵活性,就不能再增加别的字段了

  3. 每个条目的偏移量都是它在文件中的字节偏移量,而如果我们修改了文件结构,那么这些偏移量就会失效。所以这里缺少一个唯一标识的ID。

  4. 不能删除条目,只能标记无效。如果不重写日志的话,又没有垃圾回收,重写日志经常会因为各种原因出错,所以最好不要重写。

不过使用这样的CSV条目也有一些好处:没有固定格式,字段可以改变,生成比较容易,而且存储格式比较紧凑。我们保留了其优点,去掉了限制,于是设计出了像Redis Sorted Set这样的混合数据结构——Redis Streams。他们看起来像基本数据结构一样,但是为了得到这样的效果,内部是有多种表现形式的。 

Streams 101(就是Streams基础部分)

Redis Streams是一种通过基数树连接的增量压缩的宏节点。(好难理解的概念,把原话贴出来:Redis Streams are represented as delta-compressed macro nodes that are linked together by a radix tree)。它的作用是,快速查找一个随机项,获取范围值,删除旧值来创建一个有大小上限的流。对程序员来说,我们的接口和CSV文件很相似:

1> XADD mystream * cpu-temp 23.4 load 2.3
2"1553097561402-0"
3> XADD mystream * cpu-temp 23.2 load 2.1
4"1553097568315-0"
 

通过这个例子可以看到,XADD命令自动生成并返回了一个entry ID。它是单调递增的,并且有两部分组成,<时间>-<数量>,时间是毫秒级,而数量则是同一毫秒生成的entry数量递增。

所以第一个从上面所说的"追加写入CSV"文件抽象出来概念就是,如果用星号作为XADD命令的ID参数,就从服务器获取了一个entry ID。这个ID不仅仅是entry的唯一标识,也和entry加入流的时间有关。XRANGE命令可以批量获取或获取单个数据项。

1> XRANGE mystream 1553097561402-0 1553097561402-0
21) 1) "1553097561402-0"
3   2) 1) "cpu-temp"
4      2) "23.4"
5      3) "load"
6      4) "2.3"
 

在这个例子中,为了得到单个数据项,我用了相同的ID作为起始和结束值。然而我可以获取任意范围的数据项,并且用COUNT参数限制结果的数量。我也可以将起止参数都设置为时间戳,获取一段时间内的数据项。

 1> XRANGE mystream 1553097560000 1553097570000
21) 1) "1553097561402-0"
3   2) 1) "cpu-temp"
4      2) "23.4"
5      3) "load"
6      4) "2.3"
72) 1) "1553097568315-0"
8   2) 1) "cpu-temp"
9      2) "23.2"
10      3) "load"
11      4) "2.1"
 

篇幅原因,我们不再展示更多的Streams API了。我们有相关的文档,感兴趣的同学可以去阅读。目前为止,我们只需要关注基本使用方法:XADD用来增加数据,XRANGE(或XREAD)用来读取数据。我们来看一下我为什么说Streams是一个强大的数据结构。

网球运动员

前几天我和一个最近在学习Redis的朋友一起建模一个应用程序:这是一个用来追踪当地网球场、球员和比赛的app。很明显,球员是一个小的模型,在Redis中只需要用一个hash就足够了,key的形式可以是player:<id\>。当你进一步使用Redis建模时,就会意识到你需要去追踪指定网球俱乐部的一场比赛。如果球员1和球员2打了一场比赛,球员1获胜。那么我们可以这样来记录:

1> XADD club:1234.matches * player-a 1 player-b 2 winner 1
2"1553254144387-0"
 

通过这样简单的操作,我们就可以获得如下的信息:

  1. 一场比赛的唯一标识:流里的ID

  2. 不需要创建一个表示比赛的对象

  3. 分页查询比赛情况,或者查看某场比赛是否在指定时间就进行

在Streams出现之前,我们需要创建一个Sorted Set,分数是时间。Sorted Set的元素是比赛的ID(存在一个Hash里)。这不仅是增加了工作量,而且还造成了更多的内存浪费,比你想象的要多得多。

现在看起来Streams像是一个追加模式的,以时间为分数,元素是小型Hash的Sorted Set。简而言之,这是Rediscover建模环境中的一次革命。

内存使用情况

上面的例子不仅仅是固化模式的问题,相比旧有的Sorted Set+ Hash的模式,Streams对内存的节省做了很好的优化,然而这一点是不容易被发现的。

假设我们要记录100万场比赛,

Sorted Set + Hash的内存使用量是220MB(242RSS)

Stream的内存使用量是16.8MB(18.11RSS)

这不仅仅是一个数量级的差异(实际上是13倍的差异),这意味着我们旧有的模式实在是太浪费了,而新的模式是完美可行的。Redis Streams还有其他神奇的地方:宏节点可以包括多个元素,它们使用叫做listpack的数据进行编码。listpacks会对二进制形式的整数进行编码,即时它是语义字符串。最重要的是,我们使用了增量压缩和相同字段压缩。我们可以通过ID或时间进行查询,因为宏节点是用基数树连接的。基数树叶被设计为使用很少的内存。所有的事情都使用极少的内存,但有趣的是,用户并不能从语义上看到使Streams更加高效的实现细节。

现在我们来做一个简单的计算,如果我保存了100万个entry,使用了18MB内存,那么1000万个就是180MB,1亿个使用1.8GB,保存10亿数据也只使用18GB内存。

时间序列

有一个比较重要的事情需要注意,在我看来,上面我们用来记录网球比赛的例子与把Redis Streams作为一个时间序列来使用非常不同。没错,逻辑上我们仍然是记录一类事件,但本质上的区别是记录日志和创建一个entry并存入对象的不同。在使用时间序列时,我们只是记录一个外部事件,而不需要真的展示一个对象。你可能认为这个区别不重要,但事实不是这样。对Redis用户来说很重要的是,如果需要保存一系列有序的对象,并且给每个对象赋一个ID,那么就需要使用Redis Streams。

然而即时是一个简单的时间序列,也是一个很大的用例,因为在Streams出现之前,Redis在面对这种用例时令人有些绝望。一个节省内存,并且灵活的流,对开发者来说是一个重要的工具。

感谢各位的阅读,以上就是“Redis中的Redis Streams有什么作用”的内容了,经过本文的学习后,相信大家对Redis中的Redis Streams有什么作用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI