2011-10-12 7 views
8

में PostgreSQL के साथ निरंतर सूची लाने का सबसे अच्छा तरीका मैं HTTP पर एपीआई बना रहा हूं जो पोस्टग्रेएसक्यूएल से बड़ी पंक्तियों को अंकन के साथ लाता है। सामान्य मामलों में, मैं आमतौर पर बेवकूफ OFFET/LIMIT खंड के माध्यम से इस तरह के पेजिनेशन लागू करता हूं। हालांकि, इस मामले में कुछ विशेष आवश्यकताओं हैं:वेब

  • पंक्तियों की बहुत सारे हैं, लेकिन मेरा मानना ​​है कि उपयोगकर्ताओं को अंत तक नहीं पहुँच सकता (कल्पना ट्विटर के समय)।
  • पेजों को यादृच्छिक रूप से सुलभ नहीं किया जाना चाहिए लेकिन अनुक्रमिक रूप से।
  • एपीआई एक यूआरएल वापस करेगा जिसमें एक कर्सर टोकन होता है जो निरंतर भाग के पृष्ठ पर निर्देशित करता है।
  • कर्सर टोकन स्थायी रूप से मौजूद नहीं हैं लेकिन कुछ समय के लिए।
  • इसके आदेश में लगातार उतार चढ़ाव (रेडडिट रैंकिंग की तरह) है, हालांकि निरंतर कर्सर को लगातार क्रमबद्ध रखना चाहिए।

मैं मिशन कैसे प्राप्त कर सकता हूं? मैं इसके लिए अपना पूरा डेटाबेस स्कीमा बदलने के लिए तैयार हूं!

+0

बस यह सुनिश्चित करने के लिए कि आप क्या पूछ रहे हैं। क्या आप बहुत सारी पंक्तियां या वास्तव में विस्तृत पंक्तियां कह रहे हैं, या दोनों? – Kuberchaun

+0

@ स्टारशिप 3000 धन्यवाद। बहुत सारी पंक्तियां – minhee

उत्तर

6

मान लीजिए कि यह केवल उन परिणामों के क्रम का आदेश है जो पंक्तियों में डेटा में उतार-चढ़ाव करते हैं, फ्रेडरिक का जवाब समझ में आता है। स्मृति में के बजाय array प्रकार का उपयोग कर एक PostgreSQL तालिका में

  • दुकान आईडी सूची: हालांकि, मैं निम्नलिखित जोड़ने के सुझाव चाहते हैं। इसे स्मृति में करना, जब तक कि आप स्वचालित रूप से ऑटो एक्सपिररी और मेमोरी सीमाओं के साथ रेडिस जैसे कुछ का उपयोग न करें, तो डीओएस मेमोरी खपत के हमले के लिए स्वयं को स्थापित कर रहा है।मुझे लगता है यह कुछ इस तरह दिखेगा:

    create table foo_paging_cursor (
        cursor_token ..., -- probably a uuid is best or timestamp (see below) 
        result_ids integer[], -- or text[] if you have non-integer ids 
        expiry_time TIMESTAMP 
    ); 
    
  • आपको तय करना है, तो cursor_token और result_ids उपयोगकर्ताओं को अपने भंडारण आवश्यकताओं और समय प्रति उपयोगकर्ता प्रारंभिक क्वेरी चलाने के लिए आवश्यक कम करने के लिए दोनों के बीच साझा किया जा सकता है की जरूरत है। अगर उन्हें साझा किया जा सकता है, तो कैश विंडो चुनें, 1 या 5 मिनट का कहना है, और उसके बाद एक नए अनुरोध पर उस समय अवधि के लिए cache_token बनाएं और फिर यह देखने के लिए जांचें कि क्या परिणाम आईडी पहले से ही टोकन के लिए गणना की गई हैं या नहीं। यदि नहीं, तो उस टोकन के लिए एक नई पंक्ति जोड़ें। आपको नए टोकन के लिए समवर्ती अनुरोधों को संभालने के लिए चेक/डालने कोड के चारों ओर एक लॉक जोड़ना चाहिए।

  • एक निर्धारित पृष्ठभूमि नौकरी है जो पुराने टोकन/परिणामों को शुद्ध करती है और सुनिश्चित करें कि आपका ग्राहक कोड समाप्त/अमान्य टोकन से संबंधित किसी भी त्रुटि को संभाल सकता है।

भी इस बात के लिए असली db कर्सर उपयोग करने पर विचार करें।

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

+0

अभी तक बेहतर, ** एक ** अस्थायी तालिका कि सुनिश्चित करें। तेज़, कम डिस्क लोड। डॉस हमले के बारे में चिंता करने की कोई ज़रूरत नहीं है, अस्थायी सारणी केवल सीमित रैम का उपयोग कर सकती हैं (मैन्युअल में ['temp_buffers'] के बारे में पढ़ें (http://www.postgresql.org/docs/9.1/interactive/runtime-config-resource.html # क्रम-config-संसाधन-स्मृति) और डिस्क के लिए लिखा जाता है जब राम पर्याप्त नहीं है। –

+1

अस्थायी तालिकाओं सत्र स्थानीय कर रहे हैं और सत्र समाप्ति पर नष्ट हो जाती हैं। इस प्रकार, कि डाटाबेस कनेक्शन पूलिंग या इस मामले में जहां http के साथ काम नहीं करेंगे एपीआई एंडपॉइंट को कई नोड्स में वितरित किया जाता है और विभिन्न कनेक्शनों का उपयोग किया जाता है। यह तब भी समस्या का कारण बनता है जब एक ऐपसेवर पुनरारंभ होता है और उसे डीबी से फिर से कनेक्ट करना पड़ता है। उसने कहा, आपको तालिका को मेमोरी-बैक में डालकर वही लाभ मिलते हैं tmpfs) टेबल-स्पेस। http://magazine.redhat.com/2007/12/12/tip-from-an-rhce-memory-storage-on-postgresql/ –

+0

आपकी सलाह के लिए धन्यवाद देखें। मैं memcached और दुकान का उपयोग करने का निर्णय लिया समाप्ति समय के साथ अल्पविराम से अलग ids (जो कर्सर टोकन हैं)। धन्यवाद कहां! – minhee

1

मैं PostgreSQL के बारे में बिल्कुल कुछ भी नहीं पता है, लेकिन मैं एक बहुत सभ्य एसक्यूएल सर्वर डेवलपर हूं, तो मैं वैसे भी इस पर एक शॉट लेने के लिए करना चाहते हैं :)

कितने पंक्तियों/पृष्ठों जैसा कि आप उम्मीद करते हैं एक उपयोगकर्ता अधिकतम सत्र के माध्यम से ब्राउज़ करेंगे? उदाहरण के लिए, यदि आप उम्मीद करते हैं कि उपयोगकर्ता प्रत्येक सत्र के लिए अधिकतम 10 पृष्ठों [50 पंक्तियों वाले प्रत्येक पृष्ठ] के माध्यम से पृष्ठ पर पहुंचने की अपेक्षा करता है, तो आप अधिकतम ले सकते हैं और webservice सेटअप कर सकते हैं ताकि जब उपयोगकर्ता पहले पृष्ठ का अनुरोध करे, तो आप कैश करें 10 * 50 पंक्तियां (या केवल पंक्तियों के लिए आईडी: एस इस बात पर निर्भर करती है कि आपको कितनी मेमोरी/एक साथ मिलती है)।

यह निश्चित रूप से एक से अधिक तरीकों से आपके webservice को तेज़ी से बढ़ाने में मदद करेगा। और इसे लागू करना काफी आसान है। तो:

  • जब कोई उपयोगकर्ता पृष्ठ # 1 से डेटा का अनुरोध करता है। एक क्वेरी चलाएं (ऑर्डर के साथ पूरा करें, चेक में शामिल हों, आदि), सभी आईडी को एक सरणी में स्टोर करें (लेकिन अधिकतम 500 आईडी)। आईडी 0 के साथ आईडी के अनुरूप होता है जो सरणी में आता है: 0-9 पदों पर सरणी में।
  • जब उपयोगकर्ता पृष्ठ # 2-10 का अनुरोध करता है। आईडी पर मेल खाता है जो मंदांक में है: सरणी में सरणी में (पृष्ठ -1) * 50 - (पृष्ठ) * 50-1।

आप संख्याओं को भी बढ़ा सकते हैं, 500 int की एक सरणी केवल 2K स्मृति पर कब्जा कर लेगी, लेकिन यह भी निर्भर करती है कि आप अपनी प्रारंभिक क्वेरी/प्रतिक्रिया कितनी तेजी से चाहते हैं।

मैंने लाइव वेबसाइट पर एक समान तकनीक का उपयोग किया है, और जब उपयोगकर्ता पिछले पृष्ठ 10 जारी रखता है, तो मैंने सिर्फ प्रश्नों पर स्विच किया। मुझे लगता है कि एक और समाधान सरणी को विस्तार/भरना जारी रखना होगा। (फिर से क्वेरी चला रहा है, लेकिन पहले से शामिल आईडी को छोड़कर)।

वैसे भी, उम्मीद है कि इससे मदद मिलती है!

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