2012-01-24 12 views
10

मेरे पास एक HBase स्कीमा-डिज़ाइन संबंधित प्रश्न है। समस्या काफी सरल है - मैं hbase में "अधिसूचनाएं" संग्रहित कर रहा हूं, जिनमें से प्रत्येक में एक स्थिति है ("नया", "देखा", और "पढ़ा")। यहाँ एपीआई मैं प्रदान करने के लिए की जरूरत है:विशिष्ट प्रश्नों का सर्वोत्तम समर्थन करने के लिए HBase स्कीमा डिज़ाइन करना

  • एक उपयोगकर्ता के लिए सभी सूचनाएं प्राप्त
  • जाओ सब एक उपयोगकर्ता
  • के लिए 'नई' सूचनाएं एक उपयोगकर्ता के लिए सभी 'नई' सूचनाओं की संख्या प्राप्त करें
  • एक अधिसूचना के लिए
  • स्थिति अपडेट एक उपयोगकर्ता के सभी सूचनाएं लिए
  • स्थिति अपडेट
  • सब 'नई' सूचनाएं डेटाबेस पर समन्वयित हो जाओ
  • सूचनाएं थानेदार उल्टा रिवर्स कालक्रम क्रम में स्कैन करने योग्य और अंकन की अनुमति दें।

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

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

अगली संभावना (2) पंक्ति को भी स्थिति में एन्कोड करना है, इसलिए या तो "userId_reverseTimestamp_status" और फिर स्कैन पर पंक्तिकी regex फ़िल्टरिंग कर रहा है। पहली समस्या जो मैं देखता हूं उसे एक पंक्ति को हटाने की आवश्यकता होती है और स्थिति बदलते समय अधिसूचना डेटा को एक नई पंक्ति में कॉपी करना पड़ता है (जो संभवतः प्रति अधिसूचना में दो बार होना चाहिए)। साथ ही, चूंकि स्थिति प्रत्येक उपयोगकर्ता के लिए पंक्तिकुंजी का अंतिम भाग है, इसलिए हम कई अतिरिक्त पंक्तियों को स्कैन करेंगे। क्या यह एक बड़ा प्रदर्शन हिट है? अंत में, स्थिति बदलने के लिए, मुझे यह जानना होगा कि पिछली स्थिति क्या थी (पंक्ति कुंजी बनाने के लिए) या फिर मुझे एक और स्कैन करने की आवश्यकता होगी।

अंतिम विचार मेरे पास था (3) में दो स्तंभ परिवार हैं, एक स्थिर नोटिफ़ डेटा के लिए, और स्थिति के लिए ध्वज के रूप में, यानी "s: read" या "s: new" 'सीएफ और क्वालीफायर के रूप में स्थिति के रूप में। प्रति पंक्ति बिल्कुल एक होगी, और मैं उस सीएफ के खिलाफ एक एकाधिक कॉलमफ्रिक्सफिल्टर या SkipFilter w/ColumnPrefixFilter कर सकता हूं। यहां भी, मुझे स्थिति परिवर्तन पर कॉलम हटाना और बनाना होगा, लेकिन यह पूरी पंक्तियों की प्रतिलिपि बनाने से कहीं अधिक हल्का होना चाहिए। मेरी एकमात्र चिंता एचबीएएस पुस्तक में चेतावनी है कि एचबीज़ "2 या 3 से अधिक कॉलम परिवारों" के साथ अच्छा प्रदर्शन नहीं करता है - शायद अगर सिस्टम को अधिक पूछताछ क्षमताओं के साथ विस्तारित करने की आवश्यकता है, तो बहु-सीएफ रणनीति स्केल नहीं करेगी ।

तो (1) ऐसा लगता है कि इसमें बहुत अधिक नेटवर्क ओवरहेड होगा। (2) ऐसा लगता है कि डेटा की प्रतिलिपि बनाने में व्यर्थ लागत बर्बाद हो जाएगी और (3) कई परिवारों के साथ समस्याएं पैदा कर सकती है। (2) और (3) के बीच, किस प्रकार के फ़िल्टर को बेहतर प्रदर्शन देना चाहिए? दोनों मामलों में, स्कैन उपयोगकर्ता के लिए प्रत्येक पंक्ति को देखेगा, जो संभवतः अधिकतर अधिसूचनाएं पढ़ता है - जो बेहतर प्रदर्शन करेगा। मुझे लगता है कि मैं (3) की तरफ झुका रहा हूं - क्या अन्य विकल्प हैं (या tweaks) जिन्हें मैंने याद किया है?

+0

क्या अधिसूचनाएं नए 'पढ़ने' के लिए केवल एक संभावित संक्रमण के साथ 'नया' और 'पढ़ा' है? इन अधिसूचनाओं की मात्रा क्या है? – Gevorg

उत्तर

2

आपने इसमें बहुत कुछ सोचा है और मुझे लगता है कि सभी तीन उचित हैं!

आप अपनी मुख्य कुंजी टाइम स्टैम्प के साथ समेकित उपयोगकर्ता नाम होना चाहते हैं क्योंकि आपके अधिकांश प्रश्न "उपयोगकर्ता द्वारा" हैं। इससे स्कैन के साथ आसान पेजिनेशन में मदद मिलेगी और उपयोगकर्ता की जानकारी बहुत तेज़ी से ला सकती है।

मुझे लगता है कि आपकी समस्या का क्रूक्स यह बदलती स्थिति हिस्सा है। आम तौर पर, "पढ़ने" की तरह कुछ -> "हटाएं" -> "पुनः लिखना" सभी प्रकार के समवर्ती मुद्दों को प्रस्तुत करता है। यदि आपका कार्य विफल रहता है तो क्या होता है? क्या आपके पास अमान्य स्थिति में डेटा है? क्या आप एक रिकॉर्ड छोड़ देंगे?

मेरा सुझाव है कि आप तालिका के बजाय "केवल संलग्न करें" के रूप में व्यवहार करें। असल में, जो भी आप # 3 के लिए सुझाव देते हैं, लेकिन ध्वज को हटाने के बजाय, इसे वहां रखें। अगर कुछ पढ़ा गया है, तो इसमें तीन "एस: देखा जा सकता है", "एस:" वहां पढ़ें (अगर यह नया है, तो हम मान सकते हैं कि यह खाली है)। आप फैंसी भी हो सकते हैं और तीनों में से प्रत्येक में टाइमस्टैम्प डाल सकते हैं ताकि यह दिखाया जा सके कि वह घटना कब संतुष्ट थी। आपको ऐसा करने से अधिक प्रदर्शन हिट नहीं दिखनी चाहिए और फिर आपको समवर्तीता के बारे में चिंता करने की ज़रूरत नहीं है, क्योंकि सभी परिचालन केवल-लिखने वाले और परमाणु हैं।

मुझे आशा है कि यह सहायक होगा। मुझे यकीन नहीं है कि मैंने सब कुछ जवाब दिया है क्योंकि आपका प्रश्न इतना व्यापक था। कृपया अतिरिक्त प्रश्नों के साथ पालन करें और मुझे कुछ और विस्तृत करने या चर्चा करने में खुशी होगी।

+0

Gppd पॉइंट इसे केवल लिखने के बारे में बताता है। परमाणु अद्यतनों को हैक करने के लिए यह बहुत कम जटिल बनाता है - मेरा फ़िल्टर केवल तब तक होगा जब तक कोई अपठित स्थिति न हो "। किसी अन्य विकल्प का सुझाव दिया गया है कि प्रति पंक्ति एकाधिक कॉलम हों, जहां एक पंक्ति उपयोगकर्ता के लिए सभी नोटिफ़िक है। संभवतः, कॉलम पंक्तियों के समान क्रमबद्ध होते हैं। मेरा सवाल है, क्या यह हमें कुछ देता है? उन्होंने नोटिफ़ पर केवल वैल्यूफिल्टर करने का सुझाव दिया (इसलिए स्थिति को डेटा में ही रहना, जिसे एक अलग सीएफ के बजाय अपडेट किया जाना चाहिए)। मेरा अनुमान है कि यह खराब प्रदर्शन होगा। विचार? – dyross

1

मेरे समाधान है:

प्रत्येक अधिसूचना के लिए HBase में सूचनाएं स्थिति (देखा, नया) न सहेजें। अधिसूचनाओं के लिए सरल स्कीमा का उपयोग करें। कुंजी: userid_timestamp - कॉलम: अधिसूचना_मेसेज।

एक बार क्लाइंट एपीआई पूछता है "सभी नई सूचनाएं प्राप्त करें", टाइमस्टैम्प को सहेजें (सभी नई सूचनाओं को धक्का दिया गया है)। कुंजी: उपयोगकर्ता आईडी - colimn: All_new_notifications_pushed_time

टाइमस्टैम्प के साथ प्रत्येक सूचना से "सभी नई सूचनाएं धक्का दे दिया" ग्रहण "देखा" कम है, और अगर बड़ा मान "नया"

सभी नए सूचनाएं प्राप्त करने हेतु: सबसे पहले मूल्य प्राप्त (timestamp) userid द्वारा All_new_notifications_pushed_time के लिए फिर कुंजी द्वारा अधिसूचना_मेसेज कॉलम पर रेंज स्कैन करें: current_timestamp से All_new_notifications_pushed_time तक।

इससे प्रभावित कॉलम को काफी हद तक सीमित कर दिया जाएगा, और उनमें से अधिकांश यादगार में होना चाहिए।

ग्राहक पर नई सूचनाओं की गणना करें।

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