जब आशावादी ताला काम नहीं करता है तो मुझे क्या करना चाहिए?


11

मेरा यह परिदृश्य है:

  1. एक उपयोगकर्ता ETag के लिए एक GET अनुरोध /projects/1करता है और प्राप्त करता है ।
  2. उपयोगकर्ता चरण # 1 से ETag के साथ एक PUT अनुरोध करता है /projects/1
  3. उपयोगकर्ता /projects/1चरण # 1 से ETag के साथ एक और PUT अनुरोध करता है ।

आम तौर पर, दूसरा PUT अनुरोध 412 प्रतिक्रिया प्राप्त करेगा, क्योंकि ETag अब बासी है - पहला PUT अनुरोध संसाधन को संशोधित करता है, इसलिए ETag अब मेल नहीं खाता है।

लेकिन क्या होगा यदि दो PUT अनुरोध एक ही समय (या बिल्कुल एक के बाद एक) भेजे जाएं? पहले PUT अनुरोध में PUT # 2 आने से पहले संसाधन को संसाधित करने और अद्यतन करने का समय नहीं है, जो PUT # 2 को PUT # 1 को अधिलेखित करने का कारण बनता है। आशावादी ताला लगाने की पूरी बात यह है कि ऐसा न हो ...


3
व्यवसाय-स्तर के लेन-देन में अपने संचालन को कम करें, जैसा कि एसेन नीचे बताते हैं।
रॉबर्ट हार्वे

यदि मैंने लेन-देन का उपयोग करते हुए अपने ऑपरेशन को एटमाइज़ किया तो क्या होगा? PUT # 2 तब तक संसाधित नहीं होगा जब तक PUT # 1 पूरी तरह से संसाधित नहीं हो जाता?
मैक्सिममडुप्रे

7
निराशावादी बनें?
jpmc26

अच्छी तरह से यह ताला लगाने के लिए है।
फटी

सही, निश्चित रूप से रखो # 2 को संसाधित नहीं किया जाना चाहिए - वे अद्वितीय होने चाहिए।
फटी

जवाबों:


21

ETag तंत्र केवल आशावादी लॉकिंग के लिए संचार प्रोटोकॉल को निर्दिष्ट करता है। आशावादी लॉक को लागू करने के लिए समवर्ती अपडेट का पता लगाने के लिए तंत्र को लागू करना एप्लिकेशन सेवा की जिम्मेदारी है।

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


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

1
@ maximedupre: यदि आप लेन-देन का उपयोग कर रहे हैं, तो आपके पास कुछ प्रकार के ताले हैं, हालांकि यह अंतर्निहित ताले हो सकते हैं (जब आप स्पष्ट रूप से अनुरोध के बजाय फ़ील्ड पढ़ते / अपडेट करते हैं तो ताले स्वचालित रूप से अधिग्रहीत हो जाते हैं)। ऊपर वर्णित तंत्र को केवल उन निहित लॉकिंग का उपयोग करके लागू किया जा सकता है। आपके अन्य प्रश्न के रूप में, यह उस डेटाबेस पर निर्भर करता है जिसका आप उपयोग कर रहे हैं, लेकिन कई आधुनिक डेटाबेस MVCC (मल्टी वर्जन कंसीलर कंट्रोल) का उपयोग करते हैं, जिससे कई पाठकों और लेखकों को एक-दूसरे के बिना अनावश्यक रूप से ब्लॉक किए एक ही फ़ील्ड पर काम करने की अनुमति मिलती है।
रेयान

1
चेतावनी: कई DBMSes (PostgreSQL, Oracle, SQL Server, आदि) में, डिफ़ॉल्ट लेनदेन आइसोलेशन स्तर "रीड कमिटेड" है, जहां ओपी की दौड़ की स्थिति को रोकने के लिए आपका दृष्टिकोण पर्याप्त नहीं है। ऐसे DMBSes में, आप इसे AND ETag = ...अपने UPDATEस्टेटमेंट के WHEREक्लॉज़ में शामिल करके और बाद में अपडेट की गई पंक्ति-पंक्ति की जाँच करके इसे ठीक कर सकते हैं । (या एक सख्त लेनदेन अलगाव स्तर का उपयोग करके, लेकिन मैं वास्तव में इसकी सिफारिश नहीं करता हूं।)
रुख

1
@ruakh: यह इस बात पर निर्भर करता है कि आप अपनी क्वेरी कैसे लिखते हैं, हां डिफ़ॉल्ट आइसोलेशन स्तर सभी प्रश्नों के लिए स्वचालित रूप से ऐसा व्यवहार प्रदान नहीं करता है, लेकिन अक्सर अपने लेनदेन को इस तरह से तैयार करना संभव है जो आशावादी लॉकिंग को लागू करने के लिए पर्याप्त होगा। ज्यादातर मामलों में, यदि लेन-देन की स्थिरता आवेदन में महत्वपूर्ण है, तो मैं दोहराए जाने की सिफारिश करूंगा कि डिफ़ॉल्ट अलगाव स्तर के रूप में वैसे भी पढ़ा जा सकता है; MVCC का उपयोग करने वाले डेटाबेस में, दोहराए जाने वाले रीड का ओवरहेड काफी कम होता है और यह एप्लिकेशन को काफी सरल बनाता है।
रयान

1
@ruakh: बार-बार पढ़े जाने का मुख्य दोष यह है कि समवर्ती लेनदेन होने पर आपको पुनः प्रयास करने या असफल होने के लिए तैयार रहना होगा। यह सामान्य रूप से एक समस्या है, लेकिन एक संगोष्ठी रणनीति के रूप में आशावादी लॉकिंग प्रदान करने वाले अनुप्रयोगों को पहले से ही वैसे भी इस हैंडलिंग की आवश्यकता होगी, इसलिए दोहराने योग्य विफलताओं को स्वाभाविक रूप से आशावादी लॉकिंग विफलताओं के लिए मैप किया जाता है और यह वास्तव में नई कमियां नहीं जोड़ेगा।
रयान

13

आपको निम्नलिखित जोड़ी को परमाणु रूप से निष्पादित करना होगा:

  • वैधता के लिए टैग की जाँच (यानी आज तक)
  • संसाधन को अद्यतन करना (जिसमें उसका टैग अपडेट करना शामिल है)

अन्य इसे लेन-देन कह रहे हैं - लेकिन मौलिक रूप से, इन दोनों कार्यों का परमाणु निष्पादन वह है जो किसी व्यक्ति को समय की दुर्घटना से दूसरे को ओवरराइट करने से रोकता है; इसके बिना आपके पास एक दौड़ की स्थिति है, जैसा कि आप देख रहे हैं।

यह अभी भी आशावादी लॉकिंग माना जाता है, यदि आप बड़ी तस्वीर देखते हैं: कि संसाधन किसी उपयोगकर्ता या किसी भी उपयोगकर्ता द्वारा प्रारंभिक रीड (GET) द्वारा लॉक नहीं किया गया है, जो डेटा को देख रहे हैं, चाहे वह अपडेट करने के इरादे से हो या नहीं।

कुछ परमाणु व्यवहार आवश्यक हैं, लेकिन यह एक ही अनुरोध (पीयूटी) के भीतर होता है बजाय कई नेटवर्क इंटरैक्शन पर लॉक रखने के प्रयास के; यह आशावादी लॉकिंग है: GET द्वारा ऑब्जेक्ट लॉक नहीं किया गया है लेकिन अभी भी PUT द्वारा सुरक्षित रूप से अपडेट किया जा सकता है।

इन दोनों ऑपरेशनों के परमाणु निष्पादन को प्राप्त करने के कई तरीके हैं - संसाधन को लॉक करना एकमात्र विकल्प नहीं है; उदाहरण के लिए, एक हल्का धागा या ऑब्जेक्ट लॉक पर्याप्त हो सकता है और आपके एप्लिकेशन की वास्तुकला और निष्पादन के संदर्भ पर निर्भर करता है।


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

@ AaronM.Eshbach, सहमत हुए और उन लोगों को बाहर बुलाने के लिए धन्यवाद।
एरिक Eidt

1

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

GET /projects/1

सर्वर अनुरोध प्राप्त करता है, रिकॉर्ड के इस संस्करण के लिए ई-टैग को निर्धारित करता है, जो वास्तविक सामग्री के साथ वापस करता है।

200 - OK
E-Tag: "412"
Content-Type: application/json
{modified: false}

चूंकि ग्राहक के पास अब ई-टैग मूल्य है, इसलिए वह PUTअनुरोध के साथ इसे शामिल कर सकता है :

PUT /projects/1
If-Match: "412"
Content-Type: application/json
{modified: true}

इस बिंदु पर आपके आवेदन को निम्नलिखित कार्य करने होंगे:

  • सत्यापित करें कि ई-टैग अभी भी सही है: "412" == "412"?
  • यदि हां, तो अपडेट करें और नए ई-टैग की गणना करें

सफलता की प्रतिक्रिया भेजें।

204 No Content
E-Tag: "543"

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

  • सत्यापित करें कि ई-टैग अभी भी सही है: "412"! = "543"

विफलता पर, विफलता की प्रतिक्रिया भेजें।

412 Precondition Failed

यह वह कोड है जिसे आपको वास्तव में लिखना है। ई-टैग वास्तव में किसी भी पाठ (HTTP कल्पना में परिभाषित सीमा के भीतर) हो सकता है। यह एक संख्या होना जरूरी नहीं है। यह एक हैश मान भी हो सकता है।


यह एक मानक HTTP संकेतन नहीं है जिसका आप यहां उपयोग कर रहे हैं। मानक आज्ञाकारी HTTP में, आप केवल एक प्रतिक्रिया हेडर में ETag का उपयोग करते हैं। आप कभी भी किसी अनुरोध शीर्ष लेख में ETag नहीं भेजते हैं, लेकिन इसके बजाय अनुरोध किए गए शीर्ष लेखों में पहले से अधिग्रहीत ETag मान का उपयोग करें या अनुरोध शीर्ष लेख में कोई भी-मिलान-शीर्षक शीर्ष लेख का उपयोग न करें।
रयान

-2

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

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

"सही एमटी प्रोग्राम्स" से मेरा मतलब है कि कोड लिखना और समझना आसान है, जो किसी भी प्रोग्रामिंग भाषा में एक ही डिजाइन दृष्टिकोण के साथ काम करता है, और किसी भी ऑपरेटिंग सिस्टम पर, और शून्य प्रतीक्षा राज्यों और किसी भी बिंदु के साथ सीपीयू की किसी भी संख्या में तराजू कम रिटर्न

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.