检索和反序列化大量Redis缓存项目

问题描述

我们正计划在现有解决方案中添加Redis缓存。

我们拥有这个核心实体,每次会话获取了很多次。该实体由13列组成,其中大多数字符少于20个字符。通常,它是通过父ID检索的,但有时是通过ID列表获取的子集。为了解决这个问题,我们正在考虑实施以下解决方案,但是问题是,这是否是一个好主意?通常,该列表大约有400个项目,但在某些情况下,可能多达3000个项目。

我们将使用以下密钥模式将实例存储在列表中:EntityName:{ParentId}:{ChildId},其中ParentIdChildId是整数。

然后基于ParentId检索列表,我们将使用EntityName:{ParentId}:*作为pattern-argument的值调用以下方法:

public async Task<List<T>> GetMatches<T>(string pattern)
{
    var keys = _multiPlexer.GetServer(_multiPlexer.GetEndPoints(true)[0]).Keys(pattern: pattern).ToArray();
    var values = await Db.StringGetAsync(keys: keys);

    var result = new List<T>();
    foreach (var value in values.Where(x => x.HasValue))
    {
        result.Add(JsonSerializer.Deserialize<T>(value));
    }

    return result;
}

要检索特定的项目列表,我们将调用以下方法并列出确切的键:

public async Task<List<T>> GetList<T>(string[] keys)
{
    var values = await Db.StringGetAsync(keys: keys.Select(x => (RedisKey)x).ToArray());

    var result = new List<T>();
    foreach (var value in values.Where(x => x.HasValue))
    {
        result.Add(JsonSerializer.Deserialize<T>(value));
    }

    return result;
}

这里明显的担心是要反序列化的对象数量和System.Text.Json的性能。

一种替代方法是将数据存储两次,既作为列表,也可以单独存储,但这仅在我们通过ParentId获取数据的情况下才有用。我们也只能将数据存储为列表,并且每次都仅有时使用子集来检索它。

有没有更好的方法来解决这个问题?

非常感谢所有输入!谢谢!


修改

我编写了一个小型控制台应用程序,以对替代项进行负载测试,使用模式匹配,以2020ms的时间获取2000项100次,而获取列表的时间为1568ms。我认为我们可以忍受这种差异,并进行模式匹配。

解决方法

@Xerillio似乎是正确的。我使用托管服务进行了一些负载测试,然后使用模式匹配来获取列表要慢将近三倍,然后再直接从SQL接收列表就慢了三倍。因此,要回答我自己的问题,如果这是个好主意,我会说不,不是。大部分增加的时间不是因为反序列化,而是因为使用模式匹配来获取密钥。

这是从一个循环中获取2000个项目100个项目的结果:

  • 直接从db = 8625ms获取
  • 使用精确键列表= 5663ms进行提取
  • 使用match = 13098ms提取
  • 获取完整列表= 5352ms

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...