【问题标题】:Redis does not retrieve all data from databaseRedis 不会从数据库中检索所有数据
【发布时间】:2020-04-15 09:34:57
【问题描述】:

在使用 C# 检索我在 Redis 服务器上添加的键的值时,不会检索所有数据。

例如,我有键 192.168.1.1 和这个键的值 A$B$C$D$E$F$G$H 和分隔符 $ 用于拆分。

当我尝试使用此 c# 代码从 Redis 检索 192.168.1.1 的值时;

    public string GetCurrentVersion(string clientName)
    {
        return PipelineGet(redis.GetDatabase().StringGetAsync(clientName + ",Plugins"));
    }

    private string PipelineGet(Task<RedisValue> value)
    {
        try
        {
            var result = redis.GetRedis().Wait(value);
            if (result.ToString() == null)
            {
                return "";
            }
            return result.ToString();
        }
        catch (Exception ex)
        {
            return "";
        }
    }

它返回 192.168.1.1 的值,如 ABCD 或 ABCDE 或 AB 或 ABCDEEFGH。有时检索所有数据,但有时不检索。不等待所有数据稳定检索。有人可以解释一下这个原因吗?

这里是插入函数;

    public void InsertCurrentVersion(string clientName, string pluginName, string currentVersion)
    {
        redis.GetDatabase().StringAppend(clientName + ",Plugins", pluginName + "," + currentVersion + "$");
    }

【问题讨论】:

  • 这似乎不太可能;我很高兴认为出了点问题,但是:你是如何编写这个值的?您是否有可能(并且更有可能?)从正在编写它的东西中看到一个中间状态作为对APPEND 的多次调用?注意:这里不需要使用StringGetAsync - StringGet 应该可以正常工作,但是:无论哪种方式,值都应该是不可变的,所以我认为这无关紧要。
  • 强调:我并不是说它不是库错误,但是......似乎排除一个更有可能的问题是个好主意原因首先(即APPEND)(还有:什么库版本,什么目标框架等)
  • @MarcGravell 我也添加了附加功能。最新 Redis 版本 2.6.1 和 4.8 .Net 框架版本

标签: c# redis stackexchange.redis


【解决方案1】:

根据显示StringAppend 用法的编辑,您似乎只是在查询时看到中间值,尤其是在处理多个线程或多个节点时。最终,如果一个代码路径通过APPEND 建立值,而另一个代码路径在两个追加之间查询值,那么该值就是当时的值时间>。如果您要运行 MONITOR,您可能会看到如下内容:

DEL 192.168.1.1
APPEND 192.168.1.1 A$
APPEND 192.168.1.1 B$
GET 192.168.1.1
APPEND 192.168.1.1 C$
APPEND 192.168.1.1 D$

在这种情况下是的,GET 的值将是 A$B$,因为 这就是当时的值

如果您想要原子性,那么这就是您的代码需要提供的东西;有多种方法可以做到这一点,包括:

  1. 连接代码中的值,然后调用StringSet(这对于像这样的小值非常理想)
  2. 使用MULTI/EXEC(即StackExchange.Redis 中的CreateTransaction())创建一个原子操作块(不确定这在这种情况下是否有意义,但在其他情况下可能有用)
  3. 在构建时将值写入不同的临时键,然后使用RENAME(StackExchange.Redis 中的KeyRename())以原子方式交换键
  4. 通过EVAL(StackExchange.Redis 中的ScriptEvaluate())在 Lua 中执行服务器端的操作块 - 再次,可能与此特定场景无关

我自己会选择选项 1。

【讨论】:

  • Get函数正在等待redis频道广播的ok消息执行。当 Insert 函数完成后,将 ok 消息广播到 redis 频道。当我用redis-cli.exe监控的时候,我分析我认为没有并发。
  • @Heisenberg k,但是:您所描述的内容与这种APPEND 计时错误完全匹配,因此:这似乎是最有可能的罪魁祸首 - 似乎不太可能(不是不可能,但不太可能)您发现库以某种方式读取错误的字节数并且没有注意到的场景(这些是 RESP 术语中的批量字符串,因此有效负载长度是前缀 - 它甚至不需要在这里做任何思考)。你有任何我可以看的可重现的演示吗?额外的想法:您是否正在从可能落后几毫秒(或更多)的副本中查询?
  • 当我测试几次时,我发现存在并发问题。频道消息广播错误的时间。谢谢!
猜你喜欢
  • 2020-06-08
  • 1970-01-01
  • 2011-04-17
  • 2020-07-09
  • 2018-08-11
  • 2016-03-02
  • 2023-04-08
  • 2020-09-25
  • 1970-01-01
相关资源
最近更新 更多