Redis在XDEL之后流式传输阻止XREAD的不一致行为

时间:2019-04-03 14:46:20

标签: redis

在XDEL之后调用XREAD不会阻塞流,但是会立即返回。预期的行为是XREAD再次阻止。

127.0.0.1:6379> XADD my-stream * field1 string1
"1554300150697-0"
127.0.0.1:6379> XREAD BLOCK 5000 STREAMS my-stream 1554300150697-0
(nil)
(5.07s)
127.0.0.1:6379> XADD my-stream * field2 string2
"1554300285984-0"
127.0.0.1:6379> XREAD BLOCK 5000 STREAMS my-stream 1554300150697-0
1) 1) "my-stream"
   2) 1) 1) "1554300285984-0"
         2) 1) "field2"
            2) "string2"
127.0.0.1:6379> XDEL my-stream 1554300285984-0
(integer) 1
127.0.0.1:6379> XLEN my-stream
(integer) 1
127.0.0.1:6379> XREAD BLOCK 5000 STREAMS my-stream 1554300150697-0
1) 1) "my-stream"
   2) (empty list or set)
127.0.0.1:6379> 

如您在上面看到的,第一次调用XREAD会阻塞5秒-预期。

对XREAD的第二次调用将立即返回,并给出新的条目-预期。

对XREAD的第三次调用立即返回(empty list or set)-不可预期! 预期:命令应阻塞5秒钟。

我不确定这是一个错误还是我错过了某些东西。请告知。

谢谢

2 个答案:

答案 0 :(得分:0)

您似乎遇到了this known bug

请特别参阅第二条评论,该注释指出所提供的部分修复不能解决您遇到的问题:

  

这不是针对阻塞问题的完整解决方案,因为它仅解决了空流的阻塞行为。

     

如果流中仍然包含某些条目,但是所有ID的ID都比last-received-id参数所请求的ID大,则该请求仍将以空结果列表进行同步答复。

答案 1 :(得分:0)

通过5.0.4的源代码,我找到了一种通过未记录的命令->last_id

来(重新)设置XSETID成员的方法。

尽管在源代码https://github.com/antirez/redis/blob/f72f4ea311d31f7ce209218a96afb97490971d39/src/t_stream.c#L1837中它表示语法为XSETID <stream> <groupname> <id>,但实际上是XSETID <stream> <id>(关于此语法有一个开放的问题:https://github.com/antirez/redis/issues/5519,但我希望他们会为组添加一个新命令,例如XGROUPSETID,并按原样保留该命令),这正是我想要的,所以这样做:

XSETID my-stream 1554300150697-0

会做:

127.0.0.1:6379> XREAD BLOCK 5000 STREAMS my-stream 1554300150697-0
(nil)
(5.08s)
127.0.0.1:6379> 

正常工作-它会阻塞。

  

对于使用此解决方案的任何人(我认为这更像是一种解决方法):请谨慎使用,因为在高吞吐量的机器/系统/环境中,Redis可以使用以下命令生成/添加新的my-stream条目与已删除的1554300285984-0相同的ID,导致客户端可能重复的数据。