Stackexchange.redis: Exception of type 'System.OutOfMemoryException' was thrown. at StackExchange.Redis.ConnectionMultiplexer.add_ConnectionRestored

Created on 1 Aug 2019  ·  3Comments  ·  Source: StackExchange/StackExchange.Redis

Hello

I have an "OutOfMemoryException" error using .NET CORE 2.2.

The full description of the error is:

System.OutOfMemoryException:
   at System.MulticastDelegate.CombineImpl (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
   at StackExchange.Redis.ConnectionMultiplexer.add_ConnectionRestored (StackExchange.Redis, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = c219ff1ca8c2ce46)
   at V1.Sdk.Infra.Repository.RedisRepository.RegisterEvent (V1.Sdk.Infra, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null)
   at V1.Sdk.Infra.Repository.RedisRepository.get_ConnectionMultiplexer (V1.Sdk.Infra, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null)
   at V1.Sdk.Infra.Repository.RedisRepository.GetDatabase (V1.Sdk.Infra, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null)
   at Vix.V1.Application.Services.Motorista.MotoristaService + d__17.MoveNext (Vix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = nullVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: d: \ a \ 1 \ s \ Vix.V1.Application \ Services \ Driver \ DriverService.ObterLogado.csVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: 31)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
   at Vix.V1.Application.Services.Location.LocationService + d__2.MoveNext (Vix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = nullVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: d: \ a \ 1 \ s \ Vix.V1.Application \ Services \ Location \ LocationService.UpdatePosition.csVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: 27)

The class you use to access redis is:

public class RedisRepository
    {
        private static readonly object Locker = new object ();
        private static IConnectionMultiplexer _connMultiplexer;

        private static IConnectionMultiplexer ConnectionMultiplexer
        {
            get
            {
                if (_connMultiplexer == null ||! _connMultiplexer.IsConnected)
                {
                    lock (Locker)
                    {
                        if (_connMultiplexer == null ||! _connMultiplexer.IsConnected)
                        {
                            _connMultiplexer = Connection;
                        }
                    }
                }

                RegisterEvent ();

                return _connMultiplexer;
            }
        }

        private static readonly Lazy <ConnectionMultiplexer> LazyConnection = new Lazy <ConnectionMultiplexer> (() =>
        {
            var connection = StackExchange.Redis.ConnectionMultiplexer.Connect (AppContextSdk.Configuration.GetConnectionString ("RedisConnection"));

            return connection;
        });

        private static ConnectionMultiplexer Connection => LazyConnection.Value;

        public static IDatabase GetDatabase ()
        {
            return ConnectionMultiplexer.GetDatabase (0);
        }

        private static void RegisterEvent ()
        {
            _connMultiplexer.ConnectionRestored + = ConnMultiplexer_ConnectionRestored;
            _connMultiplexer.ConnectionFailed + = ConnMultiplexer_ConnectionFailed;
            _connMultiplexer.ErrorMessage + = ConnMultiplexer_ErrorMessage;
            _connMultiplexer.InternalError + = ConnMultiplexer_InternalError;
        }

        private static void ConnMultiplexer_ConnectionRestored (object sender, ConnectionFailedEventArgs and)
        {

        }

        private static void ConnMultiplexer_ConnectionFailed (object sender, ConnectionFailedEventArgs and)
        {

        }

        private static void ConnMultiplexer_ErrorMessage (object sender, RedisErrorEventArgs e)
        {
        }

        private static void ConnMultiplexer_InternalError (object sender, InternalErrorEventArgs e)
        {
        }
    }

The Redis used is Azure Redis Cache Premium 6GB.

Any idea what it might be or what you should do to solve it? Until then the solution is to restart App Service

Most helpful comment

ConnectionMultiplexer is thread-safe and does not require a lock,
` public static ConnectionMultiplexer Instance
{
get
{
return conn.Value;
}
}

    private static Lazy<ConnectionMultiplexer> conn = new Lazy<ConnectionMultiplexer>(
    () =>
    {
        _instance = ConnectionMultiplexer.Connect(RedisPath);
        //adds additional event registrations
        _instance.ConnectionFailed += MuxerConnectionFailed;
        _instance.ConnectionRestored += MuxerConnectionRestored;
        _instance.ErrorMessage += MuxerErrorMessage;
        _instance.HashSlotMoved += MuxerHashSlotMoved;
        _instance.InternalError += MuxerInternalError;
        return _instance;
    }
    );`

and you can try using my packaged tool to search 'Banana.Utility' in nuget.

All 3 comments

The problem is your ConnectionMultiplexer property. Every single time it is accessed, it adds additional event registrations. Eventually, this will explode. Before then, it is just a really bad idea. So... don't do that?

Perfect! It was exactly this point!
Thank you!

ConnectionMultiplexer is thread-safe and does not require a lock,
` public static ConnectionMultiplexer Instance
{
get
{
return conn.Value;
}
}

    private static Lazy<ConnectionMultiplexer> conn = new Lazy<ConnectionMultiplexer>(
    () =>
    {
        _instance = ConnectionMultiplexer.Connect(RedisPath);
        //adds additional event registrations
        _instance.ConnectionFailed += MuxerConnectionFailed;
        _instance.ConnectionRestored += MuxerConnectionRestored;
        _instance.ErrorMessage += MuxerErrorMessage;
        _instance.HashSlotMoved += MuxerHashSlotMoved;
        _instance.InternalError += MuxerInternalError;
        return _instance;
    }
    );`

and you can try using my packaged tool to search 'Banana.Utility' in nuget.

Was this page helpful?
0 / 5 - 0 ratings