redis stream类型

1.常用命令

功能命令参数表返回信息
添加消息xaddkey ID field string [field string …]entryId
读取消息xread[COUNT count] [BLOCK milliseconds] STREAMS key [key …] ID [ID …]entryId
读取消息xrangekey start end [COUNT count]entryId
信息监控xinfo[CONSUMERS key groupname] [GROUPS key] [STREAM key] [HELP]
取元素数xlenxlen keyStream长度
删除消息delkey [key …]删除消息个数
结束消息xackkey groupname id [id…]受理消息数
创建组xgroup creat[CREATE key groupname id-or- ] [ S E T I D k e y i d − o r − ] [SETID key id-or- ][SETIDkeyidor] [DESTROY key groupname] [DELCONSUMER key groupname consumername]ok
重新分配消息xclaimkey group consumer min-idle-time ID [ID …] [IDLE ms] [TIME ms-unix-time] [RETRYCOUNT count] [force] [justid]消息信息列表使用justid时为entryId列表
取未结束消息xpendingkey groupname[start end count] [consumer]group统计信息或消息明细
取流信息xinfo streamkey流概要信息
取流的组xinfo groupskey组信息列表
取consumer明细xinfo consumerskey groupnameConsumer信息列表
重设游标xgroup setid[CREATE key groupname id-or- ] [ S E T I D k e y i d − o r − ] [SETID key id-or- ][SETIDkeyidor] [DESTROY key groupname] [DELCONSUMER key groupname consumername]ok
删除Consumerxgroupdel consumerkey groupname consumer未ACK消息数
读取消息xreadgroupgroup groupname consumer [count count] [block n] streams key [key…] id> [id…]

2.详解stream命令

1)添加消息

XADD key ID field string [field string …]
key名称自己定义,例:Queue_SQLHandle01:20191211
ID:默认*,表示由 Redis 生成消息ID,时间戳-序号:-,时间戳是毫秒级单位,是生成消息的 Redis 服务器时间,它是个64位整型(int64)。序号是在这个毫秒时间点内的消息序号,它也是个64位整型。也可以自己定义:形式必须是整数-整数,而且必须是后面加入的消息的ID要大于前面的消息ID。
field string可以有多个,类似key-value

127.0.0.1:6379> xadd ma * name liming id 1
"1575989114765-0"

通过multi批处理,添加多条内容:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> xadd mq * msg 6
QUEUED
127.0.0.1:6379> xadd mq * msg 7
QUEUED
127.0.0.1:6379> xadd mq * msg 8
QUEUED
127.0.0.1:6379> exec
1) "1576034576429-0"
2) "1576034576429-1"
3) "1576034576429-2"

使用文件批量处理:
新建mq.txt,添加:

xadd mq * msg 9
xadd mq * msg 10
xadd mq * msg 11
[root@localhost redis-5.0.0]# cat mq.txt |redis-cli
"1576034912023-0"
"1576034912023-1"
"1576034912024-0"

2)读取消息

xread [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]

ID:读取id比你写的大的id的消息,0取所有

127.0.0.1:6379> xread streams ma 0
1) 1) "ma"
   2) 1) 1) "1575989114765-0"
         2) 1) "name"
            2) "liming"
            3) "id"
            4) "1"

count:取id比你写的大的消息,数量取前3个,这里因为没有3个比id大的消息,返回一个符合条件的。

 11) 1) "1576034912023-1"
          2) 1) "msg"
             2) "10"
      12) 1) "1576034912024-0"
          2) 1) "msg"
             2) "11"
127.0.0.1:6379> xread streams mq 1576034912023-1
1) 1) "mq"
   2) 1) 1) "1576034912024-0"
         2) 1) "msg"
            2) "11"
127.0.0.1:6379> xread count 3 streams mq 1576034912023-1
1) 1) "mq"
   2) 1) 1) "1576034912024-0"
         2) 1) "msg"
            2) "11"

  • BLOCK :参数去指定允许阻塞的时间。如果不指定,表示不阻塞,立刻返回 nil。注意这一点跟 BLPOP 不同,BLPOP 一类的命令,默认是永久阻塞的。
  • ID,用于设置由哪个消息ID开始读取。使用0表示从第一条消息开始。(本例中就是使用0)此处需要注意,消息队列ID是单调递增的,所以通过设置起点,可以向后读取。在阻塞模式中,可以使用$,表示最新的消息ID。(在非阻塞模式$无意义)。
  • block 0:block表示命令要阻塞,0表示阻塞时间为无限大,不超时,如果设置为>0的整数,即为阻塞超时时间,单位毫秒。
  • 阻塞后,拿到一条数据监听就失效,与zk的watcher雷同。要想继续拿,还要继续执行xread命令,官方推荐下一次拿entry使用上一次得到的ID。注意千万别乱设置很大的ID ,否则你可能永远拿不到entry。
127.0.0.1:6379> xread block 0 streams mq $
1) 1) "mq"
   2) 1) 1) "1576039867690-0"
         2) 1) "msg"
            2) "14"
(26.55s)

3)读取消息

xrange key start end [COUNT count]

start end送- + 表示 ID 范围的起始位置,后者表示 ID 范围的末尾位置。
count可定义取的消息数量

127.0.0.1:6379> xrange mq - + count 2
1) 1) "1575555047885-0"
   2) 1) "msg"
      2) "1"
2) 1) "1575555047885-1"
   2) 1) "msg"
      2) "2"
7.0.0.1:6379> xrange mq 1575555047885-1 + count 3
1) 1) "1575555047885-1"
   2) 1) "msg"
      2) "2"
2) 1) "1575555047885-2"
   2) 1) "msg"
      2) "3"
3) 1) "1575555047885-3"
   2) 1) "msg"
      2) "3"
xrevrange key end start [COUNT count]
127.0.0.1:6379> xrevrange mq + - count 2
1) 1) "1576039867690-0"
   2) 1) "msg"
      2) "14"
2) 1) "1576035935677-0"
   2) 1) "msg"
      2) "13"

4)信息监控

xinfo [CONSUMERS key groupname] [GROUPS key] [STREAM key] [HELP]

可查看消费者,组,流的信息

127.0.0.1:6379> xinfo stream ma
 1) "length"
 2) (integer) 1
 3) "radix-tree-keys"
 4) (integer) 1
 5) "radix-tree-nodes"
 6) (integer) 2
 7) "groups"
 8) (integer) 0
 9) "last-generated-id"
10) "1575989114765-0"
11) "first-entry"
12) 1) "1575989114765-0"
    2) 1) "name"
       2) "liming"
       3) "id"
       4) "1"
13) "last-entry"
14) 1) "1575989114765-0"
    2) 1) "name"
       2) "liming"
       3) "id"
       4) "1"

5)删除消息

真正删除stream

del key [key ...]
127.0.0.1:6379> del ma
(integer) 1

xdel stream_name id,删除消息并不是真正的物理删除,队列的长度不变,指示标记当前消息被删除

xdel key ID [ID ...]

2.消费者命令

1)添加消费者组

xgroup [CREATE key groupname id-or-$] [SETID key id-or-$] [DESTROY key groupname] [DELCONSUMER key groupname consumername]

在消息队列mq添加消费者组writer,最后一个参数0,表示该组从第一条消息开始消费。(意义与XREAD的0一致)。除了支持CREATE外,还支持SETID设置起始ID,DESTROY销毁组,DELCONSUMER删除组内消费者等操作。

127.0.0.1:6379> xgroup create mq writer 0
OK

2) 消费者消费消息

xreadgroup GROUP group consumer [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]

消费者A消费第一条消息

xreadgroup group writer writerA count 1 streams mq >

用于组writer内消费者writerA 在队列mq中消费
参数>表示未被组内消费的起始消息
参数count 1表示获取一条

  • 语法与XREAD基本一致,不过是增加了组的概念。可以进行组内消费的基本原理是,STREAM类型会为每个组记录一个最后处理(交付)的消息ID(last_delivered_id),这样在组内消费时,就可以从这个值后面开始读取,保证不重复消费。
127.0.0.1:6379> xreadgroup group writer writerA count 1 streams mq >
1) 1) "mq"
   2) 1) 1) "1575555047885-0"
         2) 1) "msg"
            2) "1"

消费组消费时,若某个消费者,消费了某条消息,但是并没有处理成功时(例如消费者进程宕机),这条消息可能会丢失,因为组内其他消费者不能再次消费到该消息了

3) Pending 等待列表

xpending key group [start end count] [consumer]

为了解决组内消息读取但处理期间消费者崩溃带来的消息丢失问题,STREAM 设计了 Pending 列表,用于记录读取但并未处理完毕的消息。命令XPENDIING 用来获消费组或消费内消费者的未处理完毕的消息。演示如下:

127.0.0.1:6379> xpending mq writer
1) (integer) 1 # 1个已读取但未处理的消息
2) "1575555047885-0" # 起始ID
3) "1575555047885-0" # 结束ID
4) 1) 1) "writerA" # 消费者A有1个
      2) "1"

再加上消费者参数,获取具体某个消费者的Pending列表

127.0.0.1:6379> xpending mq writer - + 3 writerA
1) 1) "1575555047885-0"
   2) "writerA"
   3) (integer) 919776
   4) (integer) 1

每个Pending的消息有4个属性:消息ID所属消费者IDLE,已读取时长delivery counter,消息被读取次数上面的结果我们可以看到,我们之前读取的消息,都被记录在Pending列表中,说明全部读到的消息都没有处理,仅仅是读取了。那如何表示消费者处理完毕了消息呢?使用命令 XACK 完成告知消息处理完成

4) XACK消息处理完成

通知消息处理结束,用消息ID标识

127.0.0.1:6379> xack mq writer 1575555047885-0
(integer) 1

再次查看Pending列表

127.0.0.1:6379> xpending mq writer
1) (integer) 0
2) (nil)
3) (nil)
4) (nil)

有了这样一个Pending机制,就意味着在某个消费者读取消息但未处理后,消息是不会丢失的。等待消费者再次上线后,可以读取该Pending列表,就可以继续处理该消息了,保证消息的有序和不丢失。此时还有一个问题,就是若某个消费者宕机之后,没有办法再上线了,那么就需要将该消费者Pending的消息,转义给其他的消费者处理,就是消息转移。

4) XCLAIM消息转移

消息转移的操作时将某个消息转移到自己的Pending列表中。使用语法XCLAIM来实现,需要设置组、转移的目标消费者和消息ID,同时需要提供IDLE(已被读取时长),只有超过这个时长,才能被转移。演示如下:
消费者A读取消息2,B读取消息3、4

127.0.0.1:6379> xreadgroup group writer consumerA count 1 streams mq >
1) 1) "mq"
   2) 1) 1) "1575555047885-1"
         2) 1) "msg"
            2) "2"
127.0.0.1:6379> xreadgroup group writer consumerB count 2 streams mq >
1) 1) "mq"
   2) 1) 1) "1575555047885-2"
         2) 1) "msg"
            2) "3"
      2) 1) "1575555047885-3"
         2) 1) "msg"
            2) "3"

当前属于消费者A的消息1575555047885-1,已经191,948ms未处理了

127.0.0.1:6379> xpending mq writer - + 4 consumerA
1) 1) "1575555047885-1"
   2) "consumerA"
   3) (integer) 191948
   4) (integer) 1

查看消费者B的pending列表

127.0.0.1:6379> xpending mq writer - + 5 consumerB 
1) 1) "1575555047885-2"
   2) "consumerB"
   3) (integer) 393838
   4) (integer) 1
2) 1) "1575555047885-3"
   2) "consumerB"
   3) (integer) 393838
   4) (integer) 1

转移超过36s的消息1575555047885-1到消费者B的Pending列表

xclaim key group consumer min-idle-time ID [ID ...] [IDLE ms] [TIME ms-unix-time] [RETRYCOUNT count] [force] [justid]
127.0.0.1:6379> xclaim mq writer consumerB 36000 1575555047885-1
1) 1) "1575555047885-1"
   2) 1) "msg"
      2) "2"

消息1575555047885-1已经转移到消费者B的Pending中

127.0.0.1:6379> xpending mq writer - + 5 consumerB
1) 1) "1575555047885-1"
   2) "consumerB"
   3) (integer) 90892 # 注意IDLE,被重置了
   4) (integer) 1# 注意,读取次数也累加了1次
2) 1) "1575555047885-2"
   2) "consumerB"
   3) (integer) 716190
   4) (integer) 1
3) 1) "1575555047885-3"
   2) "consumerB"
   3) (integer) 716190
   4) (integer) 1

读之前

127.0.0.1:6379> xreadgroup group writer consumerA count 1 streams mq >
1) 1) "mq"
   2) 1) 1) "1575555047885-4"
         2) 1) "msg"
            2) "4"
127.0.0.1:6379> xpending mq writer - + 6 consumerA
1) 1) "1575555047885-4"
   2) "consumerA"
   3) (integer) 66343
   4) (integer) 1
127.0.0.1:6379> xclaim mq writer consumerB 36000 1575555047885-4
1) 1) "1575555047885-4"
   2) 1) "msg"
      2) "4"
127.0.0.1:6379> xpending mq writer - + 10 consumerB
1) 1) "1575555047885-1"
   2) "consumerB"
   3) (integer) 622668
   4) (integer) 1
2) 1) "1575555047885-2"
   2) "consumerB"
   3) (integer) 1247966
   4) (integer) 1
3) 1) "1575555047885-3"
   2) "consumerB"
   3) (integer) 1247966
   4) (integer) 1
4) 1) "1575555047885-4"
   2) "consumerB"
   3) (integer) 36008
   4) (integer) 1

以上代码,完成了一次消息转移。转移除了要指定ID外,还需要指定IDLE,保证是长时间未处理的才被转移。被转移的消息的IDLE会被重置,用以保证不会被重复转移,以为可能会出现将过期的消息同时转移给多个消费者的并发操作,设置了IDLE,则可以避免后面的转移不会成功,因为IDLE不满足条件。例如下面的连续两条转移,第二条不会成功。127.0.0.1:6379> XCLAIM mq mqGroup consumerB 3600000 1553585533795-1
127.0.0.1:6379> XCLAIM mq mqGroup consumerC 3600000 1553585533795-1这就是消息转移。至此我们使用了一个Pending消息的ID,所属消费者和IDLE的属性,还有一个属性就是消息被读取次数,delivery counter,该属性的作用由于统计消息被读取的次数,包括被转移也算。这个属性主要用在判定是否为错误数据上。

5) 坏消息问题,Dead Letter,死信问题

正如上面所说,如果某个消息,不能被消费者处理,也就是不能被XACK,这是要长时间处于Pending列表中,即使被反复的转移给各个消费者也是如此。此时该消息的delivery counter就会累加(上一节的例子可以看到),当累加到某个我们预设的临界值时,我们就认为是坏消息(也叫死信,DeadLetter,无法投递的消息),由于有了判定条件,我们将坏消息处理掉即可,删除即可。删除一个消息,使用XDEL语法,演示如下:# 删除队列中的消息
127.0.0.1:6379> XDEL mq 1553585533795-1
(integer) 1
查看队列中再无此消息

127.0.0.1:6379> XRANGE mq - +
1) 1) "1553585533795-0"
   2) 1) "msg"
      2) "1"
2) 1) "1553585533795-2"
   2) 1) "msg"
      2) "3"
    

注意本例中,并没有删除Pending中的消息因此你查看Pending,消息还会在。可以执行XACK标识其处理完毕!

6) 信息监控

XINFOStream提供了XINFO来实现对服务器信息的监控,可以查询:查看队列信息

127.0.0.1:6379> Xinfo stream mq
 1) "length"
 2) (integer) 7
 3) "radix-tree-keys"
 4) (integer) 1
 5) "radix-tree-nodes"
 6) (integer) 2
 7) "groups"
 8) (integer) 1
 9) "last-generated-id"
10) "1553585533795-9"
11) "first-entry"
12) 1) "1553585533795-3"
    2) 1) "msg"
       2) "4"
13) "last-entry"
14) 1) "1553585533795-9"
    2) 1) "msg"
       2) "10"消费组信息127.0.0.1:6379> Xinfo groups mq
1) 1) "name"
   2) "mqGroup"
   3) "consumers"
   4) (integer) 3
   5) "pending"
   6) (integer) 3
   7) "last-delivered-id"
   8) "1553585533795-4"消费者组成员信息127.0.0.1:6379> XINFO CONSUMERS mq mqGroup
1) 1) "name"
   2) "consumerA"
   3) "pending"
   4) (integer) 1
   5) "idle"
   6) (integer) 18949894
2) 1) "name"
   2) "consumerB"
   3) "pending"
   4) (integer) 1
   5) "idle"
   6) (integer) 3092719
3) 1) "name"
   2) "consumerC"
   3) "pending"
   4) (integer) 1
   5) "idle"
   6) (integer) 23683256

至此,消息队列的操作说明大体结束!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值