中间件专题之文档学习Stream

新的数据结构Stream

Redis5.0引入了新的数据结构stream,依据文档说明它是一个类日志文件的数据结构,而日志文件结构是一个单纯的追加文件模式,存在许多限制(单纯的追加模式是无法满足我们多变的功能需求的);Redis的stream中加入了一系列的阻塞操作和Consumers Group(消费者组)的概念,这一概念和kafka的消费者组是基本相同的,允许一组消费者协同消费。

1.Stream操作

官方文档中介绍了以下几个操作命令:

Because streams are an append only data structure, the fundamental write command, called XADD, appends a new entry into the specified stream. A stream entry is not just a string, but is instead composed of one or multiple field-value pairs. This way, each entry of a stream is already structured, like an append only file written in CSV format where multiple separated fields are present in each line.
因为streams是一个仅追加模式数据结构,基本的写操作是:XADD,追加一个新的entry到指定的stream。一个stream entry不单单是一个字符串,儿是有一对或者多对field-value(键值)组成。stream中的每一个entry都是已经结构化的,类似向CSV格式文件中追加,逐行多分割字段。
XADD mystream * sensor-id 1234 temperature 19.8
command_name stream_name entryID field1 value1 field2 value2
1518951480106-0

下面重点来看一下XADD操作的返回值,自生成实体ID(auto-generated entry ID):

构成
<millisecondsTime>-<sequenceNumber>

millisecondsTime: 本地Redis节点本地时间,如果当前的毫秒数比前一个entryid中的毫秒数小,则会使用前一个entryid中的毫秒数。
sequenceNumber:同1毫秒内追加的entry个数,64位,理论上是不会超出的
以上是Redis服务器自增entryid的构成,处于某些原因用户可能想要在不基于毫秒的情况下指定entryid(如:0-1)来替换通配id(*),原则是不能大于前一个entryid。

获取数据

stream获取数据可以分为三种模式:

  1. 常规(可阻塞)获取 XREAD
  2. 按照事件范围获取 XRANGE XREVRANGE
  3. 通过消费者组消费stream数据
//以下分别是阻塞读取stream数据和根据时间范围获取数据的命令示例
> XREAD COUNT 2 STREAMS mystream 0 //阻塞读取需要增加BLOCK参数
> XREAD BLOCK 0 STREAMS mystream $
1) 1) "mystream"
   2) 1) 1) 1519073278252-0
         2) 1) "foo"
            2) "value_1"
      2) 1) 1519073279157-0
         2) 1) "foo"
            2) "value_2"

> XRANGE mystream - +
1) 1) 1518951480106-0
   2) 1) "sensor-id"
      2) "1234"
      3) "temperature"
      4) "19.8"
2) 1) 1518951482479-0
   2) 1) "sensor-id"
      2) "9999"
      3) "temperature"
      4) "18.2"
XREAD
  1. Stream可以有多个客户端(消费者)等待获取数据。每一个新的实体会默认发送给等待数据的每一个消费者。这个行为不同于list的阻塞,每个消费者会获取到不同地实体。这类似发布订阅模式。
  2. list中的发布订阅使用的pop命令,元素最终会被删除。在stream中不同地是元素会被无限期的追加在stream中,除非用户明确声明要删除。不同地消费者会通过记录上一个实体的id来知道什么是新消息。
  3. $ 符号代表将stream中最大entryid作为上一次获取的id,也就意味着只读取最新消息。
XRANGE

-和+符号代表最小和最大的entryid

Consumer Groups 消费者组

消费者组是为了解决同一stream中不同地消息子集不同客户端消费的场景。下面看一下官方提供的场景:
想象一下,我们有三个消费者C1,C2,C3,还有一个包含7个元素的stream:1,2,3,4,5,6,7;之后我们想让当前stream中的消息按照下图方式消费:

1 -> C1
2 -> C2
3 -> C3
4 -> C1
5 -> C2
6 -> C3
7 -> C1

为了达到这种目的,Redis使用了消费者组这个概念,它同kafka的消费者组没有任何关系,仅仅是概念上的相似。一个消费者组类似一个从stream获取数据的假的消费者,它实际上服务于多个消费者,提供一定保障:

  1. 一条信息只属于一个消费者,不会被多个消费者消费。
  2. 消费者组内的消费者具有唯一,大小写敏感的名称。
  3. 消费一条消息需要通过特定的命令告知已被正确消费,可以从服务端移除
  4. 消费者组跟踪所有信息的状态,被消费但是没有确认正确消费的信息;由于这个特性,当查看历史信息的时候每个消费者只能看到自己的信息。
    官方提供了一种消费者组的表达:
+----------------------------------------+
| consumer_group_name: mygroup           |
| consumer_group_stream: somekey         |
| last_delivered_id: 1292309234234-92    |
|                                        |
| consumers:                             |
|    "consumer-1" with pending messages  |
|       1292309234234-4                  |
|       1292309234232-8                  |
|    "consumer-42" with pending messages |
|       ... (and so forth)               |
+----------------------------------------+
//以下为对照
+----------------------------------------+
| 消费者组名称: mygroup           |
| 消费者组流: somekey         |
| 最后消费的信息id: 1292309234234-92    |
|                                        |
| 所有消费者:                             |
|    "consumer-1" with pending messages  |
|       1292309234234-4                  |
|       1292309234232-8                  |
|    "consumer-42" with pending messages |
|       ... (and so forth)               |
+----------------------------------------+

**XGROUP** 创建销毁及管理消费者组
**XREADGROUP** 通过消费者组读取信息
**XACK** 消费者标记信息状态的命令
永久故障修复

现实情况中消费者可能存在永久宕机且无法恢复的情况。Redis对于这种情况提供了一种特性,能够在消费者宕机时将消息重新指定到其他消费者。
实现这个特性需要通过特定命令XPENDING,这个命令为只读安全的,只需提供两个参数,stream名称和消费者组名称。
以下是命令构成:

第一步查看pending的消息:
XPENDING <key> <groupname> [<start-id> <end-id> <count> 
[<consumer-name>]]
第二步恢复消息使得其他消费者可以消费pending消息:
XCLAIM <key> <group> <consumer> <min-idle-time> <ID-1> <ID-2> ... <ID-N>
查看流信息
> XINFO HELP
1) XINFO <subcommand> arg arg ... arg. Subcommands are:
2) CONSUMERS <key> <groupname>  -- Show consumer groups of group <groupname>. --显示消费者组中的消费者
3) GROUPS <key>                 -- Show the stream consumer groups. --显示消费者组
4) STREAM <key>                 -- Show information about the stream. --显示流信息
5) HELP                         -- Print this help.
零长度流

当stream中没有元素时不会被删除

特殊的id

在此总结一下各命令中用到的特殊id:

- 最小id
+ 最大id
$ 最后消费实体的id,之后再消费都是最新的
> XREADGROUP命令使用时,代表消费未消费的信息
* 仅与XADD同时使用,让redis为我们自动生成id

以上仅仅时官方文档中对stream这个数据结构所作的介绍,不包含具体开发过程中的使用方法;其实java开发中,目前仅lettuce和Redisson支持stream特性,以上文档部分是在学习官方文档的过程中边看边记录的,限于我的学习程度和理解水平,没什么深度可言,且可能会有错误的地方,如有意见望不吝赐教,必及时改正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值