2015-03-01 12 views
11

Tài liệu Basic Usage cho StackExchange.Redis giải thích rằng ConnectionMultiplexer là thời gian tồn tại lâu dài và dự kiến ​​sẽ được sử dụng lại.Làm thế nào để ConnectionMultiplexer đối phó với ngắt kết nối?

Nhưng điều gì sẽ xảy ra khi kết nối với máy chủ bị hỏng? Liệu ConnectionMultiplexer tự động kết nối lại, hoặc là nó cần thiết để viết mã như trong this answer (trích dẫn câu trả lời):

 if (RedisConnection == null || !RedisConnection.IsConnected) 
     { 
      RedisConnection = ConnectionMultiplexer.Connect(...); 
     } 
     RedisCacheDb = RedisConnection.GetDatabase(); 

Là mã một cái gì đó ở trên tốt để xử lý phục hồi từ ngắt kết nối, hoặc nó sẽ thực sự dẫn đến nhiều ConnectionMultiplexer trường? Dọc theo cùng một dòng, làm thế nào nên các tài sản IsConnected được giải thích?

[Bên cạnh: Tôi tin rằng mã trên là một dạng khởi tạo lười biếng khá tệ, đặc biệt trong môi trường đa luồng - xem Jon Skeet's article on Singletons].

Trả lời

20

Đây là pattern recommended by the Azure Redis Cache team:

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => { 
    return ConnectionMultiplexer.Connect("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=..."); 
}); 

public static ConnectionMultiplexer Connection { 
    get { 
     return lazyConnection.Value; 
    } 
} 

Một vài điểm quan trọng:

  • Nó sử dụng Lazy <T> để xử lý thread-safe khởi
  • Nó đặt "abortConnect = false", điều đó có nghĩa là nếu lần thử kết nối ban đầu không thành công, thì ConnectionMultiplexer sẽ âm thầm thử lại dưới nền thay vì ném một ngoại lệ.
  • không kiểm tra thuộc tính IsConnected, vì ConnectionMultiplexer sẽ tự động thử lại trong nền nếu kết nối bị ngắt.
+0

Bạn có tham chiếu cho đề xuất này không? Tôi đã tìm thấy ví dụ về ứng dụng phim MVC của họ, nhưng sẽ hữu ích khi có thêm nền tảng từ nguồn. Dưới đây là những gì tôi đã tìm thấy: http://azure.microsoft.com/blog/2014/06/05/mvc-movie-app-with-azure-redis-cache-in-15-minutes/ – GaTechThomas

+0

Dường như điều này sẽ là nơi để đi: https://msdn.microsoft.com/en-us/library/dn690521.aspx – GaTechThomas

+0

không hoạt động cho tôi. :( –

0

Có, bạn cần loại xác minh đó để khắc phục các kết nối bị hỏng. Một số chủ đề an toàn cũng nên được yếu tố trong là tốt. Đây là cách tôi thường làm điều này:

private static ConnectionMultiplexer _redis; 
private static readonly Object _multiplexerLock = new Object(); 

private void ConnectRedis() 
{ 
    try 
    { 
     _redis = ConnectionMultiplexer.Connect("...<connection string here>..."); 
    } 
    catch (Exception ex) 
    { 
     //exception handling goes here 
    } 
} 


private ConnectionMultiplexer RedisMultiplexer 
{ 
    get 
    { 
     lock (_multiplexerLock) 
     { 
      if (_redis == null || !_redis.IsConnected) 
      { 
       ConnectRedis(); 
      } 
      return _redis; 
     } 
    } 
} 

Sau đó, tôi sử dụng RedisMultiplexer sở hữu ở khắp mọi nơi tôi cần phải gọi endpoint Redis. Tôi thường không lưu trữ kết quả của cuộc gọi GetDatabase() vì tài liệu cho biết đó là một cuộc gọi khá nhẹ.

+1

Một vấn đề lớn với phương pháp này là các kết nối sẽ bị rò rỉ cho đến khi các trường hợp ConnectionMultiplexer được làm sạch bộ thu gom rác CLR. Nếu bộ nhớ cache bị tải nặng thì có thể đạt đến giới hạn kết nối 10k. Cũng không có cách nào tốt để gọi Dispose() trên ConnectionMultiplexer cũ, vì một thread khác vẫn có thể đang cố gắng sử dụng nó. Cách tiếp cận tốt nhất mà chúng tôi đã tìm thấy là bỏ qua thuộc tính IsConnected và để ConnectionMultiplexer tự thử kết nối lại. –

+0

Cảm ơn bạn, @MikeHarder, tôi cũng sẽ áp dụng mẫu này. – CyberDude

+0

@MikeHarder Tôi đã nghi ngờ, đó là lý do tại sao tôi hỏi câu hỏi. Cảm ơn bạn đã xác nhận và làm rõ. – Gigi

Các vấn đề liên quan