【问题标题】:Microsoft Distrubted Redis Cache - Getting keys based on patternMicrosoft 分布式 Redis 缓存 - 基于模式获取密钥
【发布时间】:2019-03-29 19:50:40
【问题描述】:

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

现在我们可以通过下面的代码得到一个key。

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 包的解决方案?

【问题讨论】:

    标签: asp.net-core redis .net-core asp.net-core-mvc


    【解决方案1】:

    IDistributeCache 接口不支持此功能。它旨在获取/设置特定键,而不是返回一系列键。如果你需要做这样的事情,你需要下拉到底层存储,即 Redis。好消息是您不需要任何额外的东西:支持 Redis IDistributedCache 实现所需的相同 StackExchange.Redis 库还提供了一个您可以直接使用的客户端。

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

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

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

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

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

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

    从技术上回答您的问题,考虑到 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");
    

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

    【讨论】:

    • 所以现在您正在使用一个接口,您可以通过 DI 获得一个实现,并向您的应用程序添加实现特定的细节,所以再见 DI 的优势。我真的很难在我们的微服务架构中用 IDistributeCache 实现替换 IMemoryCache 实现,并因为这个问题而停止了。
    • 我提供了唯一可能的方法来实现 OP 正在寻找的东西。不幸的是,是的,这意味着直接依赖 Redis。抽象不涵盖这种情况。但是,这与用 IDistributedCache 替换 IMemoryCache 无关,而且我不确定您的困难到底是什么。这实际上是替代品的下降。唯一的区别是 IDistributedCache 强制序列化,无论如何你都应该这样做。
    • 我知道,我也理解,IDistributedCache 不支持expirationTokens 很烦人,这与IMemoryCache 有很大不同。
    • 您可以通过DistributedCacheEntryOptionsIDistributedCache中设置过期时间。
    【解决方案2】:

    我知道问题有点老了,但基于这个答案:How to get all keys data from redis cache

    这是示例解决方案:

    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"
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 2014-12-16
      • 2016-01-11
      • 1970-01-01
      • 2013-05-23
      相关资源
      最近更新 更多