2012-08-07 10 views
14

में परमाणु संचालन मैं नीला तालिका भंडारण में एक पृष्ठ दृश्य काउंटर लागू करने के लिए देख रहा हूँ। यदि दो उपयोगकर्ता एक ही समय में पृष्ठ पर जाते हैं, और PageViews = 100 पर वर्तमान मान, तो क्या यह गारंटी है कि अद्यतन ऑपरेशन के बाद पृष्ठ दृश्य = 102?नीला तालिका भंडारण

+1

मुझे सवाल नहीं पता है, लेकिन क्यों एक महीने में $ 5 के लिए केवल 100 एमबी एसक्यूएल डेटाबेस जोड़ें। ताले के साथ एसक्यूएल सौदा। – Paparazzi

उत्तर

23

जवाब कैसे आप अपने काउंटर को लागू पर निर्भर करता है। :-)

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

  1. प्रक्रिया एक पृष्ठदृश्य की मूल्य पढ़ता है और प्राप्त करता है 100
  2. प्रक्रिया बी पृष्ठदृश्य की मूल्य पढ़ता है और प्राप्त करता है 100
  3. प्रक्रिया एक अवलोकनों का अर्थ है एक सशर्त अद्यतन करता है: इस प्रवाह होगा "पृष्ठ दृश्य को 101 तक सेट करें जब तक कि यह वर्तमान में 100 है।" यह सफल होता है।
  4. प्रक्रिया बी एक ही आपरेशन करता है और विफल रहता है, क्योंकि पूर्व शर्त (पृष्ठदृश्य == 100) गलत है।

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

अन्य संभावनाएं हैं, और हमने वास्तव में स्केलेबल काउंटर को कार्यान्वित करने के तरीके के बारे में एक संपूर्ण क्लाउड कवर एपिसोड किया: http://channel9.msdn.com/Shows/Cloud+Cover/Cloud-Cover-Episode-43-Scalable-Counters-with-Windows-Azure

क्या है कि वीडियो में वर्णित है, तो टकराव की संभावना नहीं है शायद overkill है। यानी, यदि आपकी हिट दर एक-प्रति-सेकंड है, तो सामान्य "पढ़ना, वृद्धि, लिखना" पैटर्न सुरक्षित और कुशल होगा। यदि, दूसरी तरफ, आपको प्रति सेकंड 1000 हिट मिलती हैं, तो आप कुछ बेहतर करना चाहेंगे।

संपादित

बस लोग हैं जो इस पढ़ आशावादी संगामिति को समझने के लिए स्पष्ट करने के लिए चाहता था ... सशर्त आपरेशन नहीं वास्तव में "101 के पृष्ठ दृश्य सेट जब तक यह वर्तमान में 100 है" है यह "पेज पेज को 101 तक सेट करता है जब तक कि मैंने पिछली बार इसे देखा नहीं था।" (यह ईटीएजी का उपयोग करके पूरा किया जाता है जो HTTP अनुरोध में वापस आया था।)

+0

मैं ऑटोरन्यूविंग का उपयोग करने का सुझाव दूंगा। डूऑन (हमारे अच्छे दोस्त स्मारक द्वारा, http://blog.smarx.com/posts/managing-concurrency-in-windows-azure-with-leases) :) –

+0

जितना मुझे लोगों को पसंद है मेरे कोड का उपयोग कर :-), मुझे नहीं लगता कि मैं इसका पालन करता हूं कि इससे कैसे मदद मिलेगी? – smarx

+0

ओह, DoOnce गलत था, लेकिन मैं एक ब्लॉब पर ऑटोरन्यूविंग का उपयोग करूंगा जिसका नाम = पृष्ठ दृश्य। पार्टिशनकी + "_" + पेज व्यू। रोकी। एक बार यह ब्लॉब लॉक हो जाने पर यह उस रिकॉर्ड को प्राप्त करेगा और गिनती बढ़ाएगा। इस तरह आप सुनिश्चित कर सकते हैं कि प्रत्येक पृष्ठ दृश्य के लिए जिम्मेदार है। और यह सब यह सुनिश्चित करने के लिए क्षणिक गलती हैंडलिंग का उपयोग कर रहा है कि - मुद्दों के मामले में - कोड तब तक पुनः प्रयास करता है जब तक कि यह पृष्ठदृश्य लॉग न कर सके। –

8

आप 'गिनती' भाग पर पुनर्विचार भी कर सकते हैं। इसे दो चरणों की प्रक्रिया में क्यों न बदलें?

चरण 1 - रिकॉर्डिंग पृष्ठ दृश्य

हर बार किसी एक पृष्ठ एक तालिका में एक रिकॉर्ड जोड़ने के विचार (यह पृष्ठदृश्य कॉल)।

  • PartitionKey = पृष्ठ का नाम दिखना
  • RowKey = यादृच्छिक GUID

कुछ विचारों के बाद आप कुछ इस तरह होगा:: जानकारी आप इन दुकानों में से एक में जोड़ना होगा निम्नलिखित होगा

  • माइपेज।aspx - someGuid
  • MyPage.aspx - someGuid
  • SomePage.aspx - someGuid
  • MyPage.aspx - someGuid

चरण 2 - गिनती पृष्ठ दृश्य

क्या हम क्या करना चाहते हैं अब उन सभी रिकॉर्ड प्राप्त हैं, उन्हें गिनें, कहीं काउंटर बढ़ाएं और सभी रिकॉर्ड हटा दें। आइए मान लें कि आपके पास कई कर्मचारी चल रहे हैं। आपके दोनों कर्मचारियों के पास 1 और 10 मिनट के बीच यादृच्छिक रूप से चलने वाला लूप होगा। प्रत्येक बार कार्यकर्ता का समय बीत जाने पर यह किसी भी पट्टे पर लीज नहीं लेता है, यदि कोई पट्टा अभी तक नहीं लिया गया है (यह हमेशा एक ही ब्लॉब होना चाहिए, आप ऑटोरन्यूविंग का उपयोग कर सकते हैं)।

पहले कार्यकर्ता ताला हो रही आगे जाना है और उनकी गिनती कर सकते हैं:

  1. जाओ PageViewRecordings तालिका प्रति पृष्ठ सभी पेज व्यू से या कैश से
  2. गणना सभी रिकॉर्ड
  3. अद्यतन कहीं गिनती

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

यही कारण है कि मैं निम्नलिखित का सुझाव दूंगा। में एक ही तालिका (पृष्ठ दृश्य) में, आप उसी पृष्ठ में कुल पृष्ठ दृश्य भी रिकॉर्ड करेंगे। लेकिन डेटा हो जाएगा थोड़ी अलग है (यह कुल संख्या पकड़े एक भी है कि विभाजन में रिकॉर्ड हो जाएगा):

  • PartitionKey = पृष्ठ का नाम दिखना
  • RowKey = Guid.Empty (बस एक यादृच्छिक GUID का उपयोग नहीं करते , इस तरह हम एक रिकॉर्ड किए गए पृष्ठ दृश्य और कुल गणना वाले रिकॉर्ड के बीच का अंतर जानते हैं)।
  • गणना = वर्तमान पृष्ठ देखे जाने की संख्या

यह पूरी तरह से संभव है क्योंकि तालिका भंडारण स्कीमा कम है। और हम यह क्यों कर रहे हैं? क्योंकि हमारे पास लेन-देन होते हैं यदि हम 100 इकाइयों के अधिकतम वर्ग के साथ एक ही तालिका + विभाजन में खुद को सीमित करते हैं। हम इसके साथ क्या कर सकते हैं?

  1. टेक का उपयोग करके, हमें उस तालिका + विभाजन से 100 रिकॉर्ड प्राप्त होते हैं।
  2. पहला रिकॉर्ड जो हमें मिलेगा वह 'काउंटर' रिकॉर्ड है। क्यूं कर? क्योंकि इसके rowkey Guid.Empty है और छंटाई lexicographical
  3. गणना इन रिकॉर्ड है काउंटर रिकॉर्ड की
  4. अद्यतन गणना संपत्ति (-1 क्योंकि पहले रिकॉर्ड एक पृष्ठ दृश्य नहीं है, यह सिर्फ हमारे काउंटर प्लेसहोल्डर है)
  5. 99 (या कम) अन्य रिकॉर्ड
  6. बैच का उपयोग करके SaveChanges हटाएं।
  7. तब तक दोहराएं जब तक केवल 1 रिकॉर्ड शेष न हो (काउंटर रिकॉर्ड)।

और प्रत्येक एक्स मिनट आपके श्रमिकों को देखेंगे कि ब्लॉब पर पट्टा नहीं है, पट्टा प्राप्त करें और प्रक्रिया को पुनरारंभ करें।

क्या यह उत्तर पर्याप्त है या क्या मुझे कुछ कोड जोड़ना चाहिए?

+0

अब मैं समझता हूं कि आप ब्लॉब पट्टे के बारे में क्या कह रहे हैं। यह समझदार है, लेकिन मैं अभी भी sharding की तरह कुछ पसंद करते हैं (जैसे क्लाउड कवर एपिसोड में)। – smarx

+0

मुझे यह विचार पसंद है। कोड की कोई ज़रूरत नहीं है, मैं इसे स्पष्ट रूप से समझता हूं। लेकिन आपका मतलब था, "अगर वहां ** ** पट्टा नहीं है तो कर्मचारी पट्टा लेता है और प्रक्रिया को फिर से शुरू करता है" सही? – States

+0

हां, मैंने जवाब अपडेट किया है। –

1

मैं एक ही प्रश्न के साथ आया था। एज़ूर पायथन लाइब्रेरी के साथ, मैं लॉक के बजाय eTag और If-Match का उपयोग करके एक सरल काउंटर वृद्धि विकसित कर रहा हूं। मूल विचार यह है कि काउंटर को बढ़ाने के लिए पुनः प्रयास करना है जब तक कि अद्यतन किसी निश्चित मानदंड के तहत सफलतापूर्वक चलता न हो, जो कि कोई अन्य अपडेट इस चल रहे अद्यतन में हस्तक्षेप नहीं करता है। यदि अपडेट का अनुरोध भारी है, तो शेडिंग लागू की जानी चाहिए।

https://github.com/flyakite/simple-scalable-datastore/blob/master/datastore/azuretable.py

1

तो Azure वेबसाइटें का उपयोग कर, तो Azure कतार और WebJobs एक और विकल्प है। मेरा एक परिदृश्य में हालांकि मैं वास्तव में शेरिंग दृष्टिकोण लेने जा रहा हूं और वेबजब्स समय-समय पर समेकित अद्यतन करता हूं। PartitionKey = उपयोगकर्ता और RowKey = पृष्ठ के साथ UserPageViews की एक Azure तालिका संग्रहण तालिका। एक ही उपयोगकर्ता आईडी वाले दो एक साथ उपयोगकर्ता की अनुमति नहीं दी जाएगी।

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