StackExchange.Redis.RedisConnectionException:System.OutOfMemoryException:

时间:2019-02-11 17:56:57

标签: azure caching redis publish-subscribe stackexchange.redis

我正在尝试将我所有的运行时静态值存储到MemoryCache和Redis Cache中。 MemoryCache的用法类似于本地缓存,如果本地缓存中没有指定缓存键的缓存值,则它将从Redis服务器中获取并还原该值。通过使用StackExchange.Redis.IDatabaseAsync中的“ PublishAsync”方法,我将消息发布到给定的通道,以在所有其他服务或实例中保留本地缓存的值。

这里的问题是该方法将被称为'n'次以存储和获取缓存值,因此在实现此方案后,redis存储空间不足,并在AppInsights中记录以下引发的错误。我无法找出根本原因,“ PublishAsync”方法导致了问题或任何想法?

StackExchange.Redis.RedisConnectionException:
 System.OutOfMemoryException: at System.Array.Resize (mscorlib, 
 Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
 at StackExchange.Redis.PhysicalConnection.EnsureSpaceAndComputeBytesToRead 
 (StackExchange.Redis.StrongName, Version=1.2.6.0, Culture=neutral, 
 PublicKeyToken=c219ff1ca8c2ce46) at 
 StackExchange.Redis.PhysicalConnection.BeginReading 
 (StackExchange.Redis.StrongName, Version=1.2.6.0, Culture=neutral, 
 PublicKeyToken=c219ff1ca8c2ce46)    at 
 StackExchange.Redis.PhysicalConnection+<>c.<.cctor>b__104_0 
 (StackExchange.Redis.StrongName, Version=1.2.6.0, Culture=neutral, 
 PublicKeyToken=c219ff1ca8c2ce46)

以下是我设置缓存的方式,

 public static void AddToCache<T>(TenantInfo tenant, string cacheKey, T result, bool isInteractiveUser = false, string hashKey = default(string), TimeSpan? specifiedExpirationTime = null, bool IsincludeMemoryCache = true)
 {
        try
        {
            var expiration = TimeSpan.FromMinutes(default(int));
            if (specifiedExpirationTime != null)
                expiration = specifiedExpirationTime.Value;
            else
                expiration = (isInteractiveUser && !IsRedisCachingEnabled) ? TimeSpan.FromMinutes(3) : TimeSpan.FromMinutes(lifetimeMinutes);

            tenant = tenant ?? TenantInfo.GetTenantInfoForRequest();

            if (IsincludeMemoryCache)
            {
                CacheValue cValue = ManageMemoryCache(tenant, cacheKey, result, hashKey, expiration, IsincludeMemoryCache);

                PublishCacheData(tenant.TenantId, cacheKey, cValue, hashKey);
            }
            if (IsRedisCachingEnabled)
            {
                IDatabase redisCacheDb = Connection.GetDatabase();
                if (redisCacheDb != null)
                {
                    if (!string.IsNullOrWhiteSpace(hashKey))
                    {
                        redisCacheDb.HashSetAsync(FormatCacheKey(tenant.TenantId, hashKey), (CachePrefix + cacheKey), JsonConvert.SerializeObject(FormatCacheValue(expiration, result, IsincludeMemoryCache))).Forget();
                        redisCacheDb.KeyExpireAsync(FormatCacheKey(tenant.TenantId, hashKey), expiration).Forget();
                    }
                    else
                    {
                        redisCacheDb.StringSetAsync((CachePrefix + cacheKey), JsonConvert.SerializeObject(FormatCacheValue(expiration, result, IsincludeMemoryCache)), expiration).Forget();
                    }
                }
            }
        }
        catch (TimeoutException e)
        {
            AppInsightsRuntime.TelemetryClient.TrackTrace(e.Message, Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
            // ignore, timeouts happen, not necessarily a problem. we'll just lay off of redis for a short while to allow it to cool down
            tokenCacheFailures++;
            if (tokenCacheFailures > 2)
            {
                tokenCachingDisabled = DateTimeOffset.Now.AddSeconds(30);
                AppInsightsRuntime.TelemetryClient.TrackTrace("Disabling validate token cache for 30 seconds due to timeouts", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
            }
        }
        catch (Exception e)
        {
            LogCacheError(e);
        }
  }

这是发布缓存数据的方式,

private static void PublishCacheData(Guid tenantId, string cacheKey, CacheValue data, string hashKey)
{
        if (!IsConnected) return;

        IDatabase redisCacheDb = Connection.GetDatabase();

        //Publish changes to redis to trigger update in all servers (in case of scale out)
        //Will also write to memory cache if the object is not there
        CacheSyncPayload payload = new CacheSyncPayload
        {
            HashKey = !string.IsNullOrWhiteSpace(hashKey) ? FormatCacheKey(tenantId, hashKey) : null,
            CacheKeys = new[] { cacheKey },
            NonHashedCacheKeys = null,
            IsClearCache = false,
            Payload = data
        };
        redisCacheDb.PublishAsync(string.Concat(CallbackChannel, tenantId.ToString()), JsonConvert.SerializeObject(payload)).Forget();
 }

0 个答案:

没有答案