V5 UUID उत्पन्न करना। नाम और नाम स्थान क्या है?


125

मैं पढ़ा है manपेज, लेकिन मैं नहीं समझने के क्या करना nameऔर namespaceके लिए कर रहे हैं।

संस्करण 3 और संस्करण 5 के लिए UUIDs को अतिरिक्त कमांड लाइन तर्क नाम स्थान और नाम देना होगा। नाम स्थान या तो स्ट्रिंग प्रतिनिधित्व में एक UUID है या आंतरिक रूप से पूर्व-निर्धारित नामस्थान UUIDs के लिए एक पहचानकर्ता है (वर्तमान में "ns: DNS", "ns: URL", "ns: OID", और "ns: X500")। नाम मनमानी लंबाई की एक स्ट्रिंग है।

नामस्थान:

नाम स्थान या तो स्ट्रिंग प्रतिनिधित्व में एक यूयूआईडी है या ए

क्या इसका मतलब है कि मुझे इसे (UUID v4) स्टोर करने की आवश्यकता है जो कि उत्पन्न UUID v5 के संबंध में है? किसी भी मामले में, यह स्वचालित रूप से क्यों नहीं किया जाता है?

नाम मनमानी लंबाई की एक स्ट्रिंग है।

nameएक पूरी तरह से यादृच्छिक स्ट्रिंग? तब इसका उद्देश्य क्या है? क्या इसे यूयूआईडी वी 5 से डिकोड किया जा सकता है?

जवाबों:


106

नाम और नामस्थान का उपयोग (बहुत संभवतः) अद्वितीय यूयूआईडी की पदानुक्रम बनाने के लिए किया जा सकता है।

मोटे तौर पर, एक प्रकार 3 या टाइप 5 यूयूआईडी हैशिंग द्वारा एक नाम के साथ एक नामस्थान पहचानकर्ता द्वारा उत्पन्न किया जाता है। टाइप 3 UUIDs MD5 का उपयोग करें और टाइप 5 UUIDs SHA1 का उपयोग करें। केवल 128-बिट्स उपलब्ध हैं और 5 बिट्स का उपयोग प्रकार निर्दिष्ट करने के लिए किया जाता है, इसलिए सभी हैश बिट्स इसे UUID में नहीं बनाते हैं। (इसके अलावा MD5 को क्रिप्टोग्राफिक रूप से टूटा हुआ माना जाता है, और SHA1 अपने आखिरी पैरों पर है, इसलिए डेटा को सत्यापित करने के लिए इसका उपयोग न करें जिसे "बहुत सुरक्षित" होने की आवश्यकता है)। उस ने कहा, यह आपको प्रायिक्युलर यूनिक 128-बिट वैल्यू पर संभावित पदानुक्रमिक नाम मैपिंग करने के लिए एक रिपीटेबल / वेरिफ़ेबल "हैश" फंक्शन बनाने का एक तरीका देता है, जो संभवतः एक पदानुक्रमित हैश या मैक की तरह काम करता है।

माना कि आपके पास एक (कुंजी, मूल्य) स्टोर है, लेकिन यह केवल एक नामस्थान का समर्थन करता है। आप टाइप 3 या 5 UUIDs का उपयोग करके बड़ी संख्या में अलग-अलग तार्किक नामस्थान उत्पन्न कर सकते हैं। सबसे पहले, प्रत्येक नामस्थान के लिए एक रूट UUID बनाएं। यह एक प्रकार 1 (होस्ट + टाइमस्टैम्प) या टाइप 4 (यादृच्छिक) UUID हो सकता है जब तक कि आप इसे कहीं न कहीं रोक दें। वैकल्पिक रूप से आप बना सकते हैं अपनी रूट के लिए एक यादृच्छिक UUID (या रूट के रूप में nullUUID का उपयोग करें 00000000-0000-0000-0000-000000000000) और फिर " uuid -v5 $ROOTUUID $NAMESPACENAME" का उपयोग करके प्रत्येक नामस्थान के लिए एक प्रतिलिपि प्रस्तुत करने योग्य UUID बनाएं । अब आप एक नामस्थान के भीतर कुंजियों के लिए अद्वितीय यूयूआईडी बना सकते हैं "uuid -v5 $NAMESPACEUUID $KEY"। इन यूयूआईडी को टकराव से बचने की उच्च संभावना के साथ एक एकल कुंजी-मूल्य स्टोर में फेंक दिया जा सकता है। इस प्रक्रिया को पुनरावृत्ति रूप से दोहराया जा सकता है ताकि अगर उदाहरण के लिए, बदले में यूयूआईडी कुंजी से जुड़ा" मूल्य "किसी प्रकार के तार्किक" नाम स्थान का प्रतिनिधित्व करता हो। "एक बाल्टी, कंटेनर या निर्देशिका की तरह, फिर इसके UUID का उपयोग अधिक पदानुक्रमित UUID बनाने के लिए किया जा सकता है।

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

हालांकि यह बड़ी संख्या में नाम स्थान और कुंजियों के लिए अच्छी तरह से काम करता है, यह अंततः भाप से बाहर निकलता है यदि आप बहुत बड़ी संख्या के लिए लक्ष्य बना रहे हैं जो बहुत अधिक संभावना के साथ अद्वितीय हैं। बर्थडे प्रॉब्लम के लिए विकिपीडिया प्रविष्टि (उर्फ बर्थडे पैराडॉक्स) में एक तालिका शामिल है, जो विभिन्न संख्याओं की कुंजियों और तालिका आकारों के लिए कम से कम एक टकराव की संभावनाओं को बताती है। 128-बिट्स के लिए, हैशिंग 26 बिलियन कीज़ इस तरह से p=10^-18(नगण्य) के टकराने की संभावना है , लेकिन 26 ट्रिलियन कीज़, कम से कम एक टकराव की संभावना को बढ़ाती हैp=10^-12 (एक ट्रिलियन में) और हैशिंग 26*10^15कीज़ की संभावना को बढ़ाती है, कम से कम एक टक्करp=10^-6(लाखों में एक)। UUID प्रकार को एन्कोड करने वाले 5 बिट्स के लिए समायोजित करना, यह कुछ हद तक तेजी से बाहर निकलेगा, इसलिए एक ट्रिलियन कुंजी में लगभग एक सिंगल-ट्रिलियन एकल टक्कर होने की संभावना है।

संभावना तालिका के लिए http://en.wikipedia.org/wiki/Birthday_problem#Probability_table देखें ।

UUID एनकोडिंग पर अधिक जानकारी के लिए http://www.ietf.org/rfc/rfc4122.txt देखें ।


2
पदानुक्रम के नीचे एक निश्चित स्तर पर, क्या मैं यूयूआईडीवी 5 का उपयोग नामस्थान और यूयूआईडीवी 4 के रूप में कर सकता हूं क्योंकि डेटा में टकराव सुनिश्चित करने के लिए यादृच्छिक कुंजी के रूप में (जो इस जीयूआईडी द्वारा पहचाना जा रहा है) यूयूआईडी को टकराने की संभावना नहीं बढ़ाता है? किसी भी प्रदर्शन के मुद्दों के बारे में मुझे पता होना चाहिए?
18'18

मैं इस अवधारणा के लिए नया हूं और इस बात से हैरान हूं कि आप जिस पदानुक्रम की बात कर रहे हैं वह क्या है। मैं इसे कहां देख सकता हूं आदि ... कुछ स्पष्टता आई एक बार जब मैं स्पष्टीकरण पर अटक गया तो इसका उपयोग नामस्थान के लिए एक प्रतिलिपि प्रस्तुत करने योग्य यूयूआईडी बनाने के लिए किया जा सकता है । मैं सोच रहा हूं कि क्या यह सत्यापित करने का कोई तरीका है कि एक दिया गया UUID (प्रकार 3 या 5 में से) किसी विशेष नामस्थान (इसके UUID) का उपयोग करके उत्पन्न किया गया है?
msciwoj

213

टाइप 3 और टाइप 5 यूयूआईडी केवल यूयूआईडी में हैश भरवाने की एक तकनीक है ।

एक SHA1 हैश 160 बिट्स (20 बाइट्स) का उत्पादन करता है; हैश का परिणाम यूयूआईडी में परिवर्तित हो जाता है।

SHA1 से 20-बाइट हैश के साथ:

SHA1 Digest:   74738ff5 5367 e958 9aee 98fffdcd1876 94028007
UUID (v5):     74738ff5-5367-5958-9aee-98fffdcd1876
                             ^_low nibble is set to 5, to indicate type 5
                                  ^_first two bits set to 1 and 0, respectively

(ध्यान दें कि '9' के पहले दो टुकड़े क्रमशः 1 और 0 हैं, इसलिए इसका कोई प्रभाव नहीं है)।

मेरे पास क्या है?

आप शायद सोच रहे हैं कि ऐसा क्या है जो मैं हैश करने वाला हूं। मूल रूप से आप का संघटन है:

sha1([NamespaceUUID]+[AnyString]);

आप नाम के टकराव को रोकने के लिए एक तथाकथित नाम स्थान के साथ अपनी स्ट्रिंग उपसर्ग करते हैं ।

UUID आरएफसी आप के लिए चार नामस्थान पहले से परिभाषित करता है:

  • NameSpace_DNS: {6ba7b810-9dad-11d1-80b4-00c04fd430c8}
  • NameSpace_URL: {6ba7b811-9dad-11d1-80b4-00c04fd430c8}
  • NameSpace_OID: {6ba7b812-9dad-11d1-80b4-00c04fd430c8}
  • NameSpace_X500: {6ba7b814-9dad-11d1-80b4-00c04fd430c8}

तो, आप एक साथ हैश कर सकते हैं:

StackOverflowDnsUUID = sha1(Namespace_DNS + "stackoverflow.com");
StackOverflowUrlUUID = sha1(Namespace_URL + "stackoverflow.com");

RFC तब परिभाषित करता है:

  • SHA1 से 160 बिट लें
  • और इसे UUID के 128 बिट में परिवर्तित करें

मूल जिस्ट केवल पहले 128 बिट्स लेने के लिए है, टाइप रिकॉर्ड 5में एक सामान है , और फिर अनुभाग के पहले दो बिट्स को क्रमशः 1 और 0 पर सेट करें ।clock_seq_hi_and_reserved

और ज्यादा उदाहरण

अब जब आपके पास एक फ़ंक्शन है जो एक तथाकथित नाम उत्पन्न करता है , तो आपके पास फ़ंक्शन (छद्म कोड में) हो सकता है:

UUID NameToUUID(UUID NamespaceUUID, String Name)
{
    byte[] hash = sha1(NamespaceUUID.ToBytes() + Name.ToBytes());
    UUID result;
    Copy(hash, result, 16);
    result[6] &= 0x0F; 
    result[6] |= 0x50;
    result[8] &= 0x3F; 
    result[8] |= 0x80;
    return result;
}

(ध्यान दें कि आपके सिस्टम का एंडियन-नेस उपरोक्त बाइट्स के सूचकांक को प्रभावित कर सकता है)

आप कॉल कर सकते हैं:

uuid = NameToUUID(Namespace_DNS, 'www.stackoverflow.com');
uuid = NameToUUID(Namespace_DNS, 'www.google.com');
uuid = NameToUUID(Namespace_URL, 'http://www.stackoverflow.com');
uuid = NameToUUID(Namespace_URL, 'http://www.google.com/search&q=rfc+4112');
uuid = NameToUUID(Namespace_URL, 'http://stackoverflow.com/questions/5515880/test-vectors-for-uuid-version-5-converting-hash-into-guid-algorithm');

अब वापस अपने सवाल पर

संस्करण 3 और संस्करण 5 के लिए UUIDs को अतिरिक्त कमांड लाइन तर्क नाम स्थान और नाम देना होगा। नाम स्थान या तो स्ट्रिंग प्रतिनिधित्व में एक UUID है या आंतरिक रूप से पूर्व-निर्धारित नामस्थान UUIDs के लिए एक पहचानकर्ता है (वर्तमान में "ns: DNS", "ns: URL", "ns: OID", और "ns: X500")। नाम मनमानी लंबाई की एक स्ट्रिंग है।

नाम स्थान जो कुछ भी आप की तरह UUID है। यह पूर्व-परिभाषित लोगों में से एक हो सकता है, या आप अपना खुद का बना सकते हैं, जैसे:

UUID Namespace_RectalForeignExtractedObject = '8e884ace-bee4-11e4-8dfc-aa07a5b093db'

नाम मनमानी लंबाई की एक स्ट्रिंग है।

नाम सिर्फ वह पाठ है जिसे आप नेमस्पेस में जोड़ा जाना चाहते हैं, फिर हैशेड और यूआईडी में भर दिया है:

uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'screwdriver');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'toothbrush');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'broomstick');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'orange');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'axe handle');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'impulse body spray');
uuid = NameToUUID('8e884ace-bee4-11e4-8dfc-aa07a5b093db', 'iPod Touch');

नोट : कोई भी कोड सार्वजनिक डोमेन में जारी किया गया। कोई एट्रिब्यूशन की आवश्यकता नहीं है।


45
पूरी तरह से स्पष्टीकरण के लिए धन्यवाद। अगर मैं अपने लिए बोनस अंक दे सकता था Namespace_RectalForeignExtractedObject
बूडल

क्या नाम को डिकोड करना संभव है या नामस्थान UUID से डिकोड किया गया है?
शतेश

3
@ सथेश नहीं, हैश को डिकोड करना संभव नहीं है; हैश एक तरह से कार्य हैं। उदाहरण के लिए, पूरे स्टार ट्रेक टीएनजी ब्लू-रे संग्रह 81 जीबी है, और इसमें C5740BBB2424115276D4AB60A020ED3ADE01192 का हैश है । यह समझने का कोई तरीका नहीं है कि 20-बाइट हैश 81 जीबी में वापस आ गई है। यदि आपको वास्तव में जरूरत है, तो आप सभी संभावित GUID और संभावित स्ट्रिंग्स को हैशिंग तक आज़मा सकते हैं जब तक कि आपको वही संयोजन न मिले जो समान परिणाम देता है। किसी भी लूक के साथ आप इसे हमेशा और अनंत काल के बीच में पाएंगे।
इयान बॉयड

22

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

यूयूआईडी को एक एकल नामस्थान के रूप में देखा जा सकता है जो इतना विशाल है कि यह हर चीज के लिए एक अनूठा नाम प्रदान कर सकता है ; यही "सार्वभौमिक" का अर्थ है। लेकिन आप अन्य नामस्थानों में मौजूदा नामों को UUID में कैसे मैप करते हैं?

एक स्पष्ट समाधान यह है कि प्रत्येक आइटम के लिए यूयूआईडी (वी 1 या वी 4) उत्पन्न किया जाए ताकि पुराने नामों को उनके असम्बद्ध नामस्थानों में बदल दिया जा सके। नकारात्मक पक्ष यह है कि वे बहुत बड़े हैं, आपको सभी नए नामों को उन सभी लोगों से संवाद करना होगा जिनके पास आपके डेटासेट की एक प्रति है, अपने सभी एपीआई अपडेट करें, आदि हैं। आप वास्तव में पुराने नामों से पूरी तरह छुटकारा नहीं पा सकते हैं वैसे भी, जिसका अर्थ है कि अब हर वस्तु के दो नाम हैं, तो क्या आपने चीजों को बेहतर या बदतर बना दिया है?

यह वह जगह है जहाँ V3 / V5 आते हैं। UUIDs V4 की तरह ही यादृच्छिक दिखते हैं, लेकिन वास्तव में नियतात्मक हैं; किसी भी व्यक्ति के पास एक नामस्थान के लिए सही UUID है और फिर उस नामस्थान के भीतर किसी भी नाम के लिए स्वतंत्र रूप से एक ही UUID उत्पन्न कर सकता है । आपको उन्हें प्रकाशित करने की आवश्यकता नहीं है और न ही उन्हें पूर्व-उत्पन्न करने की आवश्यकता है क्योंकि कोई भी उन्हें आवश्यकतानुसार मक्खी पर बना सकता है!

DNS नाम और URL बहुत ही आमतौर पर उपयोग किए जाने वाले नामस्थान हैं, इसलिए उन लोगों के लिए मानक UUID प्रकाशित किए गए थे; ASN.1 OID और X.500 नाम सामान्य नहीं हैं, लेकिन मानक निकाय उन्हें पसंद करते हैं, इसलिए उन्होंने उनके लिए भी मानक नामस्थान UUIDs प्रकाशित किए।

अन्य सभी नामस्थानों के लिए, आपको अपना स्वयं का नामस्थान UUID (V1 या V4) जनरेट करना होगा और इसे किसी ऐसे व्यक्ति से संवाद करना होगा, जिसे इसकी आवश्यकता है। यदि आपके पास कई नामस्थान हैं, तो प्रत्येक के लिए UUID प्रकाशित करना स्पष्ट रूप से आदर्श नहीं है।

यह वह जगह है जहां पदानुक्रम आता है: आप एक "आधार" UUID (जो भी प्रकार का) बनाते हैं, और फिर अपने अन्य नामस्थानों के नामकरण के लिए एक नामस्थान के रूप में उपयोग करते हैं! इस तरह, आपको केवल आधार UUID प्रकाशित करना होगा (या एक स्पष्ट एक का उपयोग करें), और हर कोई बाकी की गणना कर सकता है।

उदाहरण के लिए, चलो बने रहें हम स्टैकऑवरफ्लो के लिए कुछ यूयूआईडी बनाना चाहते थे; DNS नामस्थान के भीतर एक स्पष्ट नाम है, इसलिए आधार स्पष्ट है:

uuid ns_dns = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
uuid ns_base = uuidv5(ns_dns, 'stackoverflow.com');

StackOverflow में उपयोगकर्ताओं, प्रश्नों, उत्तरों, टिप्पणियों, आदि के लिए अलग-अलग नामस्थान हैं, लेकिन साथ ही साथ ये काफी स्पष्ट भी हैं:

uuid ns_user = uuidv5(ns_base, 'user');
uuid ns_question = uuidv5(ns_base, 'question');
uuid ns_answer = uuidv5(ns_base, 'answer');
uuid ns_comment = uuidv5(ns_base, 'comment');

यह विशेष प्रश्न # 10867405 है, इसलिए इसका UUID होगा:

uuid here = uuidv5(ns_question, '10867405');

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


मैं सोच रहा हूं कि स्टैकओवरफ्लो को यूयूआईडी को दिए गए विशिष्ट रूप से उत्पन्न बड़े पूर्णांक को मैप करने की आवश्यकता क्यों है क्योंकि इसके एपीआई स्पष्ट रूप से केवल बड़े पूर्णांक को एक स्ट्रिंग के रूप में वापस करते हैं। यदि API में नहीं तो UUID का उपयोग कहां किया जाएगा। ऐसा लगता है कि हमें या तो UUID या BIGINT का चयन करना चाहिए? यह हाइब्रिड रणनीति क्यों। फिर भी आपके उत्तर में स्पष्ट स्पष्टीकरण के लिए +1।
निशांत

4
UUID V3 / V5 को तब डिज़ाइन किया गया था जब आपको एक यूयूआईडी नामस्थान पर मौजूदा (और संभावित टकराव) नामस्थान को निर्धारित करने की आवश्यकता होती है, जो डेटासेट्स को मर्ज करते समय अक्सर उपयोगी होता है। यदि आप जो कर रहे हैं उस पर लागू नहीं होता है, तो V1 / V4 के साथ जाएं।
स्टीफन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.