2011-04-15 17 views
12

मैं हैश को ~ 100k रिकॉर्ड प्रति हैश के साथ स्टोर करने के लिए रेडिस का उपयोग कर रहा हूं। मैं किसी दिए गए हैश के भीतर रिकॉर्डिंग (फ़ेसटिंग) रिकॉर्ड को कार्यान्वित करना चाहता हूं। ध्यान दें कि हैश एंट्री एन फिल्टर से संबंधित हो सकती है।फ़िल्टरिंग रेडिस हैश प्रविष्टियां

  1. फिल्टर प्रति एक क्रमबद्ध सेट को लागू करें:

    this और this पढ़ने के बाद ऐसा लगता है कि मैं चाहिए लग रहा है। एसईटी के भीतर मूल्य एक हैश के भीतर कुंजी के अनुरूप है।

  2. दिए गए फ़िल्टर एसईटी से हैश कुंजी पुनर्प्राप्त करें।
  3. एक बार मेरे पास एसईटी से हैश कुंजी हैश से संबंधित प्रविष्टियां प्राप्त करती है। यह मुझे फ़िल्टर से संबंधित सभी प्रविष्टियां देनी चाहिए।

सबसे पहले उपरोक्त दृष्टिकोण उच्च स्तर पर सही है?

दृष्टिकोण मानना ​​ठीक है कि मुझे याद आ रही है कि हैश प्रविष्टियों को पुनर्प्राप्त करने के लिए सबसे प्रभावी कार्यान्वयन क्या है? क्या मैं सोचने में सही हूं कि मेरे पास हैश कुंजी है तो मुझे प्रत्येक HASH कुंजी से गुजरने वाले एकाधिक HGETALL आदेशों को कतारबद्ध करने के लिए एक PIPELINE का उपयोग करना चाहिए? क्या कोई बेहतर दृष्टिकोण है?

एक पीआईपीईलाइन का उपयोग करने के बारे में मेरी चिंता यह है कि मुझे विश्वास है कि यह आदेश देने के दौरान अन्य सभी ग्राहकों को अवरुद्ध कर देगा। मैं फ़िल्टर किए गए परिणामों को प्रति पृष्ठ 500 परिणामों के साथ पेजिंग कर दूंगा। फ़िल्टरिंग करने वाले कई ब्राउज़र आधारित क्लाइंट्स के साथ, एसईटी और एचएएसएचएस को पॉप्युलेट करने वाली बैक एंड प्रक्रियाओं का उल्लेख न करने के लिए ऐसा लगता है कि यदि पीआईपीईलाइन ब्लॉक करता है तो बहुत सारी विवादों की संभावना है। क्या कोई इस पर एक दृश्य प्रदान कर सकता है?

यदि यह मदद करता है तो मैं 2.2.4 रेडिस का उपयोग कर रहा हूं, वेब क्लाइंट के लिए predis और बैक एंड के लिए servicestack।

धन्यवाद, पॉल

+0

मैं इसी तरह के फ़िल्टर करने की कोशिश कर रहा हूं, लेकिन मेरे पास फ़िल्टर करने के लिए बड़े सेट (1 मिलियन रिकॉर्ड) हैं। क्या आपको रेडिस में फ़िल्टर करने का कोई बेहतर तरीका मिला? –

उत्तर

4

रेडिस लॉक-फ्री गैर-अवरुद्ध एसिंक सर्वर है इसलिए पाइपलाइनिंग का उपयोग करते समय विवाद कोई जोड़ा नहीं गया है। Redis hums प्रत्येक ऑपरेशन को खुशी से प्रसंस्करण के साथ-साथ प्रैक्टिस में प्राप्त करने के साथ-साथ कई पाइपलाइन परिचालनों को संसाधित कर सकते हैं। संक्षेप में रेडिस-सर्वर वास्तव में परवाह नहीं करता है कि ऑपरेशन पाइपलाइन है या नहीं, यह केवल प्रत्येक ऑपरेशन को संसाधित करता है क्योंकि यह उन्हें प्राप्त करता है।

पाइपलाइनिंग का लाभ क्लाइंट विलंबता को कम करना है, जहां अगले ऑपरेशन से पहले प्रत्येक ऑपरेशन के लिए रेडिस-सर्वर से प्रतिक्रिया की प्रतीक्षा करने के बजाय, क्लाइंट केवल एक ही लिखने में सभी ऑपरेशन पंप कर सकता है, फिर सभी को वापस पढ़ें एक ही पढ़ने में प्रतिक्रियाएं।

कार्रवाई में इस का एक उदाहरण मेरे Redis mini StackOverflow clone में है प्रत्येक क्लिक ToQuestionResults() के लिए एक कॉल जो क्योंकि संचालन pipelined कर रहे हैं में 1 सॉकेट अवरुद्ध पढ़ा जो और अधिक के बजाय कुशल है 1 सॉकेट लिखने फोन पर सभी कार्यों के परिणाम भेजता है और पढ़ता है बनाता है एक अवरुद्ध प्रति कॉल पढ़ें:

https://github.com/ServiceStack/ServiceStack.Examples/blob/master/src/RedisStackOverflow/RedisStackOverflow.ServiceInterface/IRepository.cs#L180

एक पाइप लाइन के उपयोग के बारे में मेरी चिंता का विषय कि मेरा मानना ​​है कि यह अन्य सभी ग्राहकों जबकि आदेश सर्विसिंग को अवरुद्ध कर देगा है।

यह एक वैध चिंता का विषय नहीं है और मैं अधिक नहीं लगता है कि कैसे Redis यहाँ काम करता है, यह यह सबसे अधिक कुशलता से जहां पाइपलाइनिंग अन्य ग्राहकों आदेशों की प्रोसेसिंग ब्लॉक नहीं करता कर रहा है मान लेते हैं। संकल्पनात्मक रूप से आप सोच सकते हैं कि Redis-server प्रत्येक कमांड (पाइपलाइन या नहीं) को FIFO क्रम में संसाधित करता है (यानी पूरे पाइपलाइन को प्रतीक्षा/पढ़ने में कोई समय बर्बाद नहीं होता है)।

आप बहु/EXEC (यानी रेडिस लेनदेन) के करीब कुछ वर्णन कर रहे हैं, जहां रेडिस सर्वर EXEC (यानी ईओएफ लेनदेन) पढ़ता है, जैसे ही सभी ऑपरेशन एक ही बार में किए जाते हैं। यह कोई समस्या नहीं है और रेडिस-सर्वर अभी भी आपके पूरे लेन-देन को प्राप्त करने के लिए इंतजार कर रहा है, यह आंशिक कमान में आंशिक कमांड को कतार में नहीं देता है जब तक कि वह अंतिम EXEC प्राप्त नहीं करता है जिसे बाद में सभी को संसाधित किया जाता है।

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

इसलिए इस मामले में मैं पाइपलाइनिंग का उपयोग करता हूं क्योंकि यह हमेशा एक जीत है, और अधिक पाइपलाइन जितना अधिक आदेश (जैसे आप अवरुद्ध पढ़ने की गणना को कम करते हैं)।

5

व्यक्तिगत संचालन ब्लॉक करते हैं, लेकिन यह कोई बात नहीं के रूप में वे लंबे समय से चल रहा है नहीं होना चाहिए। ऐसा लगता है कि आपको वास्तव में आवश्यकता से अधिक जानकारी प्राप्त हो रही है - जब आपको केवल 500 की आवश्यकता होती है तो HGETALL 100,000 आइटम लौटाएगा।

500 एचजीईटी ऑपरेशंस भेजना काम कर सकता है (सेट सेट को हैश और कुंजी दोनों स्टोर करता है) हालांकि यह संभव है कि हैश का उपयोग करना बिल्कुल समयपूर्व अनुकूलन का मामला है - आप नियमित कुंजी और एमजीईटी का उपयोग कर बेहतर हो सकते हैं।

+2

टॉम का जवाब देने के लिए धन्यवाद। आप सही हैं, मैं HGETALL के उद्देश्य को गलत समझाऊंगा। जबकि आपका जवाब उपयोगी था, मैं इसे स्वीकार नहीं कर रहा हूं क्योंकि मुझे नहीं लगता कि यह वास्तव में मुझे मूल प्रश्न के करीब आता है। मैं सुनता हूं कि आप समयपूर्व अनुकूलन के बारे में क्या कह रहे हैं लेकिन ऐसा लगता है कि सॉर्ट किए गए सेट फ़िल्टरिंग को लागू करने का स्वीकार्य तरीका हैं और हैश "ऑब्जेक्ट्स" को संग्रहीत करने का सबसे अच्छा तरीका हैं। मुझे लगता है कि मैं कुछ भी असामान्य करने के बजाय केवल सर्वोत्तम अभ्यास का पालन कर रहा हूं। – Paul

2

मुझे लगता है कि आप गलत समझते हैं कि पाइपलाइनिंग क्या करती है। यह अवरुद्ध नहीं करता है जबकि सभी आदेश भेजे जा रहे हैं। यह सब कुछ कर रहा है कमांड को बफर करना, फिर अंत में उन्हें एक साथ निष्पादित करना, इसलिए उन्हें निष्पादित किया जाता है जैसे कि वे एक ही कमांड हैं। किसी भी समय अवरुद्ध नहीं हो रहा है। रेडिस multi/exec के लिए भी यही सच है। रेडिस में अवरुद्ध/लॉक करने के लिए आपको सबसे नज़दीकी चीज watch का उपयोग करके आशावादी लॉकिंग है, जो exec को watch कहने के बाद से रेडिस कुंजी लिखा गया है, विफल होने के कारण exec का कारण बन जाएगा।

इससे भी अधिक कुशल है कि एक पाइप लाइन ब्लॉक के भीतर hget 500 बार बुला सिर्फ hmget('hash-key',*keys) कॉल करने के लिए जहां keys 500 हैश कुंजी आप ऊपर देख रहे हैं की एक सरणी है

। इसके परिणामस्वरूप रेडिस के लिए एक ही कॉल होगा, जो कि जैसा कि यह पाइपलाइन किया गया था, लेकिन निष्पादित करने के लिए तेज़ होना चाहिए क्योंकि आप रूबी में लूप नहीं कर रहे हैं।

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