2012-08-04 16 views
13

मैं सत्र-स्टोर बेसिंग रेडिस को कार्यान्वित करना चाहता हूं, मैंने सत्र डेटा को रेडिस में रखा है। लेकिन मुझे नहीं पता कि सत्र-समाप्ति को कैसे संभाला जाए। मैं सभी रेडिस कुंजियों (सत्रिद) को लूप कर सकता हूं और अंतिम और अधिकतम डेटा को उजागर कर सकता हूं, इस प्रकार मुझे क्लाइंट में सभी चाबियाँ लोड करने की आवश्यकता है, और शायद 1000 मीटर सत्र कुंजी हो सकती है और हो सकता है बहुत पूल I/O प्रदर्शन का नेतृत्व करें।
मैं चाहता हूं कि रेडिस का समय समाप्त हो जाए, लेकिन जब कोई समय समाप्त हो जाए तो श्रोता या कॉलबैक नहीं होता है, इसलिए HttpSessionListener को बाघ करना असंभव है। कोई सलाह?सत्र की समाप्ति को रेडिस के आधार पर कैसे संभाला जाए?

+0

रेडिस में नहीं, लेकिन आप यह देखना चाहते हैं कि यह टारनटूल में कैसे किया जाता है: https://github.com/mailru/tntlua/blob/master/expirationd.lua संक्षेप में, टारनटूल में डेटाबेस में अपनी खुद की लुआ स्क्रिप्ट चला सकते हैं, और उनमें अपनी खुद की समाप्ति नीतियां सेट कर सकते हैं। कोई बाहरी डिमन्स की आवश्यकता नहीं है। – Kostja

उत्तर

33

तो आपको Redis में सत्र समाप्त होने पर अधिसूचित होने के लिए आपके आवेदन की आवश्यकता है।

जबकि रेडिस इस सुविधा का समर्थन नहीं करता है, वहां कई चालें हैं जिनका उपयोग आप इसे लागू करने के लिए कर सकते हैं।

अपडेट: संस्करण 2.8.0 से, Redis का समर्थन इस http://redis.io/topics/notifications

सबसे पहले, लोगों को इसके बारे में सोच रहे हैं करता है: यह अभी भी चर्चा के अंतर्गत है, लेकिन यह Redis के भविष्य के संस्करणों में जोड़ा जा सकता है। निम्न समस्याओं देखें:

अब, यहाँ कुछ समाधान आप वर्तमान Redis संस्करणों के साथ उपयोग कर सकते हैं।

समाधान 1: Redis

असल पैचिंग, जब Redis कुंजी समाप्ति करता है एक साधारण सूचना जोड़ने की है कि मुश्किल नहीं है। इसे Redis स्रोत कोड की db.c फ़ाइल में 10 लाइन जोड़कर कार्यान्वित किया जा सकता है।

https://gist.github.com/3258233

इस छोटे पैच पदों #expired सूची के लिए एक महत्वपूर्ण है, तो कुंजी समाप्त हो गई है और एक '@' चरित्र (मनमाने ढंग से चुनाव) के साथ शुरू होता है: यहाँ एक उदाहरण है। इसे आसानी से आपकी जरूरतों के अनुरूप अनुकूलित किया जा सकता है।

अपने सत्र ऑब्जेक्ट्स के लिए समाप्ति समय निर्धारित करने के लिए EXPIRE या SETEX कमांड का उपयोग करना और फिर एक छोटा डिमन लिखना है जो "#expired" सूची से निकालने के लिए BRPOP पर लूप करता है, और आपके अधिसूचना को प्रसारित करता है आवेदन।

एक महत्वपूर्ण बात यह समझना है कि समाप्ति तंत्र रेडिस में कैसे काम करता है। वास्तव में समाप्ति के लिए दो अलग-अलग पथ हैं, दोनों एक ही समय में सक्रिय हैं:

  • आलसी (निष्क्रिय) तंत्र। प्रत्येक बार एक कुंजी का उपयोग होने पर समाप्ति हो सकती है।

  • सक्रिय तंत्र। एक आंतरिक नौकरी नियमित रूप से (यादृच्छिक रूप से) समाप्ति सेट के साथ कई चाबियों का नमूना देती है, जो कि समाप्त होने के लिए ढूंढने की कोशिश कर रही हैं।

ध्यान दें कि उपर्युक्त पैच दोनों पथों के साथ ठीक काम करता है।

परिणाम रेडिस समाप्ति समय सटीक नहीं है।यदि सभी चाबियों की समाप्ति हो रही है, लेकिन केवल एक ही समाप्त होने वाला है, और इसका उपयोग नहीं किया जाता है, तो सक्रिय समाप्ति कार्य में कुंजी खोजने और इसे समाप्त करने में कई मिनट लग सकते हैं। अगर आपको अधिसूचना में कुछ सटीकता की आवश्यकता है, तो यह जाने का रास्ता नहीं है।

समाधान 2: zsets

विचार यहाँ Redis कुंजी समाप्ति तंत्र पर भरोसा नहीं है, लेकिन एक अतिरिक्त सूचकांक के साथ साथ एक मतदान डेमॉन का उपयोग करके इसे अनुकरण है साथ अनुकरण समाप्ति। यह एक unmodified Redis 2.6 संस्करण के साथ काम कर सकते हैं।

हर बार एक सत्र Redis में जोड़ा जाता है, तो आप चला सकते हैं:

MULTI 
SET <session id> <session content> 
ZADD to_be_expired <current timestamp + session timeout> <session id> 
EXEC 

to_be_expired अनुसार क्रमबद्ध सेट पहली कुंजी है कि समय सीमा समाप्त हो जाना चाहिए का उपयोग करने की सिर्फ एक कारगर तरीका है। शुरू करने के लिए स्क्रिप्ट होगा

local res = redis.call('ZRANGEBYSCORE',KEYS[1], 0, ARGV[1], 'LIMIT', 0, 10) 
if #res > 0 then 
    redis.call('ZREMRANGEBYRANK', KEYS[1], 0, #res-1) 
    return res 
else 
    return false 
end 

आदेश:: एक डेमॉन निम्नलिखित लुआ सर्वर साइड स्क्रिप्ट का उपयोग कर to_be_expired पर मतदान कर सकते हैं

EVAL <script> 1 to_be_expired <current timestamp> 

डेमॉन पर सबसे 10 आइटम मिल जाएगा। उनमें से प्रत्येक के लिए, सत्रों को हटाने और एप्लिकेशन को सूचित करने के लिए इसे DEL आदेश का उपयोग करना होगा। यदि एक आइटम वास्तव में संसाधित किया गया था (यानी लुआ लिपि की वापसी खाली नहीं है), तो डिमन तुरंत लूप होना चाहिए, अन्यथा 1 सेकंड प्रतीक्षा स्थिति पेश की जा सकती है।

लुआ लिपि के लिए धन्यवाद, समानांतर में कई मतदान डिमन्स लॉन्च करना संभव है (स्क्रिप्ट गारंटी देता है कि दिए गए सत्र को केवल एक बार संसाधित किया जाएगा, चूंकि कुंजियों को lua स्क्रिप्ट द्वारा स्वयं से हटाया जाता है)।

समाधान 3: एक बाहरी वितरित टाइमर

एक अन्य समाधान के लिए एक बाहरी वितरित टाइमर पर भरोसा करने के लिए है का उपयोग करें। beanstalk lightweight queuing system इस

प्रत्येक बार एक सत्र सिस्टम में जोड़ा जाने के लिए एक अच्छी संभावना है, एप्लिकेशन सत्र समय के अनुरूप देरी के साथ सत्र आईडी को बीनस्टॉक कतार में पोस्ट करता है। एक डिमन कतार सुन रहा है। जब यह किसी आइटम को डिलीक कर सकता है, तो इसका मतलब है कि एक सत्र समाप्त हो गया है। इसे सिर्फ रेडिस में सत्र साफ करना है, और आवेदन को सूचित करना है।

+0

कमाल का जवाब - बहुत बहुत धन्यवाद! क्या आप इस वाक्य को स्पष्ट कर सकते हैं हालांकि: "डिमन को तुरंत लूप करना चाहिए, अन्यथा 1 सेकंड प्रतीक्षा स्थिति पेश की जा सकती है"। इस संदर्भ में लूपिंग का अर्थ क्या है - और यह 1 सेकंड प्रतीक्षा क्यों है? –

+0

डेमन्स निवासी कार्यक्रम हैं जो कभी-कभी सिस्टम में कुछ गतिविधि करने के लिए जागते हैं। चूंकि वे लगातार चल रहे हैं, अधिकांश कोड मुख्य लूप में संलग्न है। लूपिंग के दौरान 100% सीपीयू लेने से बचने के लिए अब एक डिमन को एक प्रतीक्षा स्थिति की आवश्यकता होती है। रेडिस के साथ एक जेसेट से जुड़ा कोई अवरोधक आदेश नहीं है (सूची के लिए बीएलपीओपी/बीआरपीओपी के विपरीत), इसलिए इसे कुछ भी लौटाए जाने पर मतदान और सोने से अनुकरण किया जाना चाहिए। –

+2

यह पहले से ही रेडिस में लागू किया गया है। वे मुद्दे बंद हैं। अगर कोई इस जवाब को अपडेट करता है तो यह अच्छा होगा। –

संबंधित मुद्दे