【问题标题】:BookSleeve BlockingRemoveLeft is only returning some of the items pushed into the listBookSleeve BlockingRemoveLeft 只返回一些推入列表的项目
【发布时间】:2014-01-11 23:34:51
【问题描述】:

我正在尝试根据 BookSleeve 组合一个 super 简单的排队示例。

这是我目前为止队列消费者方面的内容:

using System;
using System.Text;
using BookSleeve;

static class Program
{
    static void Main()
    {
        using (var redis = new RedisConnection("127.0.0.1"))
        {
            redis.Open();
            while (true)
            {
                // BRPOP the queue
                var t = redis.Lists.BlockingRemoveFirst(0, new[] { "test" }, 0);
                t.Wait();
                var val = Encoding.UTF8.GetString(t.Result.Item2);
                Console.WriteLine("Got: {0}", val);
            }
        }
    }
}

我作为生产者在LINQPad 中运行以下命令:

using(var redis = new RedisConnection("localhost")) 
{
    redis.Open();
    foreach(var i in Enumerable.Range(0, 10)) 
    {
        // LPUSH
        redis.Lists.AddFirst(0, "test", "foo" + i)
            // Call wait to keep things in order
            .Wait();
    }   

    Thread.Sleep(500); // Let Redis do it's thing
    Console.WriteLine("queue length: " + redis.Lists.GetLength(0, "test").Result);
}

我得到了一些非常奇怪的结果:

第一次运行:

Got: foo2
Got: foo5
Got: foo7
Got: foo9

第二次运行:

Got: foo1
Got: foo4
Got: foo7

第三次运行:

Got: foo0
Got: foo3
Got: foo6
Got: foo8

此外,每次运行后,LINQPad 输出:queue length: 0,使用实际的 redis 客户端运行 LLEN test 返回(integer) 0

我不禁觉得我在这里遗漏了一些东西,很可能与异步的东西有关,但我就是看不到。

我的redis版本是2.8.3,BookSleeve版本是1.3.41。

这里的实际问题是:为什么 BookSleeve 只返回发送到 redis 列表的消息的子集?

【问题讨论】:

  • 今晚会看。作为旁注:我通常会说“避免阻塞呼叫(更喜欢发布/订阅通知)” - 它对多路复用器造成了疯狂的伤害。但是,它应该可以工作。稍后再说。
  • 随机想法:你不可能有第二个消费者 exe 副本在某处运行并拿走一些项目?
  • 实际上,这是我检查的第一件事。它是当时唯一连接到redis的进程。
  • k - 目前忙于家庭事务,但稍后再看

标签: c# redis booksleeve


【解决方案1】:

我根本无法让它出错。您绝对确定您只有 1 个消费者吗?请注意,order 不可预测的原因是因为您将它用作堆栈而不是队列 - 要获得可靠的顺序,您应该添加到开头并从末尾删除,或者添加到结束并从头开始删除。如果你从一开始就添加和删除它是随机顺序。

但是,它对我来说很好用。控制台输出:

Got: foo0
Got: foo1
Got: foo3
Got: foo5
Got: foo6
Got: foo8
Got: foo9
Got: foo7
Got: foo4
Got: foo2
queue length: 0

我建议在monitor 模式下使用redis-cli - 对我来说,我得到以下输出:

redis 127.0.0.1:6379> monitor
OK
1389454168.068869 [0 127.0.0.1:4957] "INFO"
1389454168.068869 [0 127.0.0.1:4957] "CONFIG" "GET" "timeout"
1389454168.068869 [0 127.0.0.1:4957] "DEL" "test"
1389454168.129869 [0 127.0.0.1:4958] "INFO"
1389454168.129869 [0 127.0.0.1:4958] "CONFIG" "GET" "timeout"
1389454168.136869 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.139872 [0 127.0.0.1:4959] "INFO"
1389454168.139872 [0 127.0.0.1:4959] "CONFIG" "GET" "timeout"
1389454168.139872 [0 127.0.0.1:4959] "LPUSH" "test" "foo0"
1389454168.142869 [0 127.0.0.1:4959] "LPUSH" "test" "foo1"
1389454168.142869 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.142869 [0 127.0.0.1:4959] "LPUSH" "test" "foo2"
1389454168.143871 [0 127.0.0.1:4959] "LPUSH" "test" "foo3"
1389454168.143871 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.143871 [0 127.0.0.1:4959] "LPUSH" "test" "foo4"
1389454168.143871 [0 127.0.0.1:4959] "LPUSH" "test" "foo5"
1389454168.144870 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.144870 [0 127.0.0.1:4959] "LPUSH" "test" "foo6"
1389454168.144870 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.144870 [0 127.0.0.1:4959] "LPUSH" "test" "foo7"
1389454168.145869 [0 127.0.0.1:4959] "LPUSH" "test" "foo8"
1389454168.145869 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.145869 [0 127.0.0.1:4959] "LPUSH" "test" "foo9"
1389454168.145869 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.146869 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.146869 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.147870 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.147870 [0 127.0.0.1:4958] "BLPOP" "test" "0"
1389454168.648594 [0 127.0.0.1:4959] "LLEN" "test"

这里的连接 4957 只是删除密钥(以确保已知状态); 4958是消费者,4959是生产者。

作为参考,我在上述测试中使用了2.6.12 Windows build(因为我在我的 Windows 笔记本电脑上,并且没有时间设置 linux VM) - 但是:我希望在官方的 linux 也可以编译。

再说一遍:你确定(通过redis-cli)你这里只有两个连接吗?

如果我换成AddLast:

Got: foo0
Got: foo1
Got: foo2
Got: foo3
Got: foo4
Got: foo5
Got: foo6
Got: foo7
Got: foo8
Got: foo9
queue length: 0

【讨论】:

  • 附加想法:您还可以使用client list 来查看当前连接以及它们的最后一个命令、它们的当前状态等。特别是,flags 属性包含一个b,如果它是一个阻塞操作。
  • 我会试一试。让我难过的是我在重新启动 redis(我在 Linux VM 中运行)后立即出现了这种行为。
  • 有趣的是:为什么你的输出是非连续的?我认为我发布的代码应该产生 FIFO 行为
  • @ross 我在回答中解释了这一点,并(见最后)展示了如何解决它。基本上,不,你没有写 FIFO
  • 我发现了发生了什么(它确实与孤立的连接有关),打算写一篇关于它的博客文章。
猜你喜欢
  • 2021-04-18
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多