Microsoft Distrubted Redis 缓存 - 根据模式获取密钥

问题描述 投票:0回答:2

我们正在使用 .NET core 的 Microsoft 分布式缓存实现。请参阅 https://learn.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.1 了解更多信息。

现在我们可以通过以下代码获取密钥了。

var cacheKey = "application:customer:1234:profile";
var profile = _distributedCache.GetString(cacheKey);

我想做的是执行以下操作:

var cacheKey = "application:customer:1234:*";
var customerData = _distributedCache.GetString(cacheKey);

这样我们就可以用这个模式得到以下键:

  • 应用:客户:1234:简介
  • 申请:客户:1234:订单
  • 应用程序:客户:1234:发票
  • 应用程序:客户:1234:付款

使用任何通配符或没有通配符都无法获得此作品。有没有无需实现另一个 Redis nuget 包的解决方案?

c# asp.net-core .net-core redis asp.net-core-mvc
2个回答
14
投票

IDistributeCache
界面不支持此功能。它旨在获取/设置特定键,而不是返回一系列键。如果您需要执行类似的操作,则需要进入底层存储,即 Redis。好消息是您不需要任何额外的东西:支持 Redis
StackExchange.Redis
实现所需的相同
IDistributedCache
库还提供了您可以直接使用的客户端。

特别是对于您的场景,您需要一些代码,例如:

var server = _redis.GetServer(someServer);
foreach(var key in server.Keys(pattern: cacheKey)) {
    // do something
}

这里,

_redis
ConnectionMultiplexer
的一个实例。这应该已经在您的服务集合中注册,因为它由 Redis
IDistributedCache
实现使用。因此,您可以将其注入到控制器或存在此代码的其他类中。

someServer
变量是对您的 Redis 服务器之一的引用。您可以通过
_redis.GetEndpoints()
获取所有已注册的Redis服务器。这将返回
IEnumerable
的服务器,您可以从中选择或枚举。此外,您可以通过传递主机字符串和端口直接连接到特定服务器:

var server = _redis.GetServer("localhost", 6379);

但请注意,

Keys()
将导致在 Redis 服务器上发出 SCAN 或 KEYS 命令。使用哪个取决于服务器版本,但两者的效率都相当低,因为必须查看整个密钥空间。建议您不要在生产中使用它,或者如果必须的话,请在从服务器上发出它。

从技术上回答了您的问题,考虑到扫描/密钥的复杂性和固有的低效率,您最好这样做:

var cacheKeyPrefix = "application:customer:1234";
var profile = _distributedCache.GetString($"{cacheKeyPrefix}:Profile");
var orders = _distributedCache.GetString($"{cacheKeyPrefix}:Orders");
var invoices = _distributedCache.GetString($"{cacheKeyPrefix}:Invoices");
var payments = _distributedCache.GetString($"{cacheKeyPrefix}:Payments");

最终会快得多,并且不需要任何特殊的东西。


1
投票

我知道问题有点老了,但基于这个答案:如何从 Redis 缓存中获取所有密钥数据

这是示例解决方案:

CustomerRepository.cs

using Newtonsoft.Json;
using StackExchange.Redis;
// ...

public class CustomerRepository : ICustomerRepository
{
    private readonly IDistributedCache _redis;
    private readonly IConfiguration _configuration;

    public CustomerRepository(IDistributedCache redis, IConfiguration configuration)
    {
        _redis = redis;
        _configuration = configuration;
    }

    ///<summary>replace `object` with `class name`</summary>

    public async Task<object> GetCustomersAsync(string name)
    {
        ConfigurationOptions options = ConfigurationOptions.Parse(_configuration.GetConnectionString("DefaultConnection"));
        ConnectionMultiplexer connection = ConnectionMultiplexer.Connect(options);
        IDatabase db = connection.GetDatabase();
        EndPoint endPoint = connection.GetEndPoints().First();
        var pattern = $"application:customer:{name}:*";
        RedisKey[] keys = connection.GetServer(endPoint).Keys(pattern: pattern).ToArray();
        var server = connection.GetServer(endPoint);

        var result = await _redis.GetStringAsync(key);
        return JsonConvert.DeserializeObject<object>(result);
    }
}

appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "localhost:6379,password=YOUR_PASSWORD_HERE"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.