2011-12-27 10 views
26

का उपयोग कर एक खुले रेडिस कनेक्शन को बनाए रखना क्या किसी के पास BookSleeve लाइब्रेरी के माध्यम से रेडिस लाने का ठोस पैटर्न है?BookSleeve

मेरा मतलब है:

BookSleeve के लेखक @MarcGravell recommends खोलने के लिए नहीं & कनेक्शन हर बार बंद, बल्कि पूरे एप्लिकेशन में एक कनेक्शन को बनाए रखने। लेकिन आप नेटवर्क ब्रेक कैसे संभालेंगे? यानी कनेक्शन पहले स्थान पर सफलतापूर्वक खोला जा सकता है, लेकिन जब कुछ कोड रेडिस को पढ़ने/लिखने की कोशिश करता है, तो संभावना है कि कनेक्शन गिरा दिया गया है और आपको इसे फिर से खोलना होगा (और अगर यह खुला नहीं होगा तो कृपापूर्वक असफल हो जाएंगे - लेकिन यह आपकी डिजाइन आवश्यकताओं पर निर्भर है।)

मैं सामान्य स्निस कनेक्शन खोलने के लिए कोड स्निपेट की तलाश करता हूं, और सामान्य 'जीवित' चेक (+ जीवित नहीं होने पर वैकल्पिक जागृत) जो प्रत्येक पढ़ने से पहले उपयोग किया जाएगा /लिखना।

This question समस्या के लिए एक अच्छा रवैया पता चलता है, लेकिन यह केवल आंशिक है (यह उदाहरण के लिए, एक खो कनेक्शन को ठीक नहीं करता है), और उस प्रश्न का accepted answer सही तरीके से ड्रॉ लेकिन ठोस कोड प्रदर्शित नहीं करता है।

मुझे आशा है कि इस धागे को ठोस जवाब मिलेंगे और आखिरकार बुक स्लीव के उपयोग के साथ .NET अनुप्रयोगों के उपयोग के साथ विकी का एक प्रकार बन जाएगा।

-----------------------------

महत्वपूर्ण अद्यतन (21/3/2014):

-----------------------------

मार्क Gravell (@MarcGravell)/स्टैक एक्सचेंज है recently releasedStackExchange.Redis लाइब्रेरी जो आखिरकार बुक्सलीव को प्रतिस्थापित करती है। यह नई लाइब्रेरी, अन्य चीजों के साथ, आंतरिक रूप से पुनर्निर्देशन को संभालती है और मेरे प्रश्न को अनावश्यक प्रस्तुत करती है (यानी, यह पुस्तकें के लिए अनावश्यक नहीं है और न ही मेरा उत्तर नीचे है, लेकिन मुझे लगता है कि आगे बढ़ने का सबसे अच्छा तरीका नया स्टैक एक्सचेंज। रीडिस लाइब्रेरी का उपयोग शुरू करना है)।

+0

अवधि के साथ दिल की धड़कन धागे का उपयोग करें alphazero

+0

हां, मुझे वास्तव में पुन: कनेक्ट तर्क की आवश्यकता है ... एक मजबूत और साफ कोड में ... बीटीडब्ल्यू अच्छा यूट्यूब वीडियो। पहली बार मुझे एसओ में इसका सामना करना पड़ता है। –

+1

शानदार - उत्तर अपडेट उसी दिन आता है जब हम पहली बार समस्या देखते हैं। – Anthony

उत्तर

29

जब से मैं किसी भी अच्छे जवाब नहीं मिला है, मैं इस समाधान (Btw धन्यवाद के साथ आया था @ आपके उत्तरों के लिए साइमन और @ एलेक्स!)।

मैं इसे सभी समुदाय के संदर्भ के रूप में साझा करना चाहता हूं। बेशक, किसी भी सुधार की अत्यधिक सराहना की जाएगी।

using System; 
using System.Net.Sockets; 
using BookSleeve; 

namespace Redis 
{ 
    public sealed class RedisConnectionGateway 
    { 
     private const string RedisConnectionFailed = "Redis connection failed."; 
     private RedisConnection _connection; 
     private static volatile RedisConnectionGateway _instance; 

     private static object syncLock = new object(); 
     private static object syncConnectionLock = new object(); 

     public static RedisConnectionGateway Current 
     { 
      get 
      { 
       if (_instance == null) 
       { 
        lock (syncLock) 
        { 
         if (_instance == null) 
         { 
          _instance = new RedisConnectionGateway(); 
         } 
        } 
       } 

       return _instance; 
      } 
     } 

     private RedisConnectionGateway() 
     { 
      _connection = getNewConnection(); 
     } 

     private static RedisConnection getNewConnection() 
     { 
      return new RedisConnection("127.0.0.1" /* change with config value of course */, syncTimeout: 5000, ioTimeout: 5000); 
     } 

     public RedisConnection GetConnection() 
     { 
      lock (syncConnectionLock) 
      { 
       if (_connection == null) 
        _connection = getNewConnection(); 

       if (_connection.State == RedisConnectionBase.ConnectionState.Opening) 
        return _connection; 

       if (_connection.State == RedisConnectionBase.ConnectionState.Closing || _connection.State == RedisConnectionBase.ConnectionState.Closed) 
       { 
        try 
        { 
         _connection = getNewConnection(); 
        } 
        catch (Exception ex) 
        { 
         throw new Exception(RedisConnectionFailed, ex); 
        } 
       } 

       if (_connection.State == RedisConnectionBase.ConnectionState.Shiny) 
       { 
        try 
        { 
         var openAsync = _connection.Open(); 
         _connection.Wait(openAsync); 
        } 
        catch (SocketException ex) 
        { 
         throw new Exception(RedisConnectionFailed, ex); 
        } 
       } 

       return _connection; 
      } 
     } 
    } 
} 
+0

आप कोड डबल-चेक लॉकिंग चीज कर रहे हैं जो [वास्तव में टूटा हुआ है] (http: // www। cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html) (कम से कम जावा प्लेटफार्म पर, लेकिन मुझे संदेह होगा कि सी # पर्यावरण मूल रूप से अलग है) –

+0

@AlexPopescu, .NET CLR उपयोग करने से संबंधित मुद्दों को हल करता है _Double-Check Locking_ जो अन्य वातावरण में आम हैं। कृपया देखें: http://msdn.microsoft.com/en-us/library/ff650316.aspx। लेकिन आपकी टिप्पणी के लिए धन्यवाद, मैंने देखा है कि मुझे _volatile_ कीवर्ड को __instance_ में जोड़ना चाहिए। धन्यवाद! –

+0

मैं आपके समाधान का प्रयास कर रहा था और औसत पर यह हर बार एक नया कनेक्शन लौटने के मेरे खराब हैक की तुलना में 120 मिमी धीमी है। http://pastie.org/3965493। क्या आप आज इस कोड का उपयोग कर रहे हैं या आपने इस पर कोई संशोधन किया है? –

2

अन्य सिस्टम (जैसे ADO.NET) के साथ, यह कनेक्शन पूल का उपयोग करके हासिल किया जाता है। आपको वास्तव में कभी भी एक नया कनेक्शन ऑब्जेक्ट नहीं मिलता है, लेकिन वास्तव में पूल से एक प्राप्त करें।

पूल स्वयं कॉलर के कोड से स्वतंत्र रूप से नए कनेक्शन और मृत कनेक्शन प्रबंधित करता है। यहां विचार बेहतर प्रदर्शन करना है (एक नया कनेक्शन स्थापित करना महंगा है), और नेटवर्क समस्याओं से बचें (सर्वर के नीचे कॉलर कोड विफल हो जाएगा लेकिन जब यह ऑनलाइन वापस आता है तब फिर से शुरू होगा)। असल में एक पूल प्रति ऐपडोमेन, प्रति "प्रकार" कनेक्शन है।

जब आप ADO.NET कनेक्शन स्ट्रिंग देखते हैं तो यह व्यवहार पारदर्शी होता है। उदाहरण के लिए एसक्यूएल सर्वर कनेक्शन स्ट्रिंग (ConnectionString Property) में 'पूलिंग', 'मैक्स पूल साइज', 'मिन पूल साइज' इत्यादि की धारणा है। यह ClearAllPools विधि भी है जिसका प्रयोग प्रोग्रामेटिकल को वर्तमान ऐपडोमेन पूल को रीसेट करने के लिए किया जाता है, यदि आवश्यक हो तो उदाहरण।

मुझे बुकस्लीव कोड में इस तरह की सुविधा के करीब कुछ भी नहीं दिख रहा है, लेकिन ऐसा लगता है कि अगली रिलीज के लिए योजना बनाई गई है: BookSleeve RoadMap

इसी समय, मुझे लगता है कि आप अपना कनेक्शन पूल लिख सकते हैं क्योंकि RedisConnection में एक त्रुटि ईवेंट है जिसका उपयोग आप मृत होने पर पता लगाने के लिए कर सकते हैं।

+0

बुकस्लीव के साथ काम करने का सही तरीका नियमित कनेक्शन डीबी कनेक्शन पूलिंग के तरीके के विपरीत एक कनेक्शन बनाए रखना है। यही कारण है कि मैंने इस सवाल से पूछा ... कृपया @ मार्कग्रावेल का जवाब देखें [यहां] (http://stackoverflow.com/a/6478883/290343)। वह कहता है: _ "एक नोट: कनेक्शन थ्रेड सुरक्षित है और इसे बड़े पैमाने पर साझा करने का इरादा है)"; प्रति ऑपरेशन कनेक्शन न करें। "_ –

+0

मुझे वह मिला, लेकिन एक RedisConnection सॉकेट त्रुटियों से नहीं बचा है क्योंकि यह सदस्य सॉकेट संदर्भ पर बैठता है, इसलिए आपको कानूनी रूप से कुछ प्रकार के पूल तंत्र की आवश्यकता होती है, और यह रोडमैप में है। –

+0

लेकिन अब क्या करना है कि उनके पास अभी भी सुविधा नहीं है? मुझे एक कामकाजी पैटर्न की आवश्यकता है (और मैं कई अन्य लोगों पर विश्वास करता हूं ...) और हमेशा RedisConnection को खोलना/बंद करना (इसे 'उपयोग' में लपेटना) वर्तमान बुकस्लीव रिलीज, एडीओ.NET कनेक्शन के विपरीत, बहुत अधिक ओवरहेड है। –

2

मैं एक सी # प्रोग्रामर नहीं हूँ, लेकिन जिस तरह से मैं इस समस्या को देखने चाहते हैं निम्नलिखित है:

  1. मैं एक सामान्य समारोह है कि के रूप में ले जाएगा कोड होता redis कनेक्शन और एक पैरामीटर लैम्ब्डा अभिव्यक्ति Redis आदेश

  2. यदि प्रतिनिधित्व करने Redis आदेश एक अपवाद एक कनेक्टिविटी समस्या की ओर इशारा में परिणाम होगा पर अमल करने की कोशिश कर रहा है, मैं गया है कनेक्शन को पुनः आरंभ कर और कार्रवाई का पुनः प्रयास

  3. कोई उत्कृष्टता अगर ption सिर्फ परिणाम

यहाँ लौट उठाया है छद्म कोड के कुछ प्रकार है:

function execute(redis_con, lambda_func) { 
    try { 
     return lambda_func(redis_con) 
    } 
    catch(connection_exception) { 
     redis_con = reconnect() 
     return lambda_func(redis_con) 
    } 
} 
+0

ए 'try..catch' ब्लॉक वास्तव में समाधान का हिस्सा होना चाहिए, लेकिन सूक्ष्म स्तर में, मुझे विश्वास है। समग्र इंटरफ़ेस एक होना चाहिए एक सिंगलटन की तरह जो हमेशा उपयोग के लिए एक वैध कनेक्शन प्रदान करेगी। आंतरिक रूप से यह जांच करेगा कि "वर्तमान" कनेक्शन जिंदा है या इसे बढ़ाने का प्रयास करें (यह टुकड़ा एक कोशिश में होगा .. पकड़ो), और यदि यह विफल हो जाता है, तो यह एक अपवाद फेंक देगा। Sinc ई शुरुआती प्रश्न पूछने के लगभग 2 सप्ताह पहले, मैंने स्वयं कोड पर काम करना शुरू कर दिया और मैं इसे यहां प्रकाशित करूंगा। (पहली जगह में मैंने http://en.wikipedia.org/wiki/Reinventing_the_wheel का पालन करने की कोशिश की) –