मुझे कब अजगर में uuid.uuid1 () बनाम uuid.uuid4 () का उपयोग करना चाहिए?


207

मैं डॉक्स से दोनों के बीच के अंतर को समझता हूं

uuid1():
एक होस्ट आईडी, अनुक्रम संख्या और वर्तमान समय से एक UUID उत्पन्न करें

uuid4():
एक यादृच्छिक UUID उत्पन्न करें।

इसलिए uuid1UUID बनाने के लिए मशीन / अनुक्रम / समय की जानकारी का उपयोग करता है। प्रत्येक का उपयोग करने के पेशेवरों और विपक्ष क्या हैं?

मुझे पता है uuid1()कि गोपनीयता की चिंता हो सकती है, क्योंकि यह मशीन-जानकारी से दूर है। मुझे आश्चर्य है कि अगर एक या दूसरे को चुनते समय कोई और अधिक सूक्ष्म है। मैं अभी उपयोग करता हूं uuid4(), क्योंकि यह पूरी तरह यादृच्छिक UUID है। लेकिन मुझे आश्चर्य है कि अगर मुझे uuid1टक्करों के जोखिम को कम करने के लिए उपयोग किया जाना चाहिए ।

मूल रूप से, मैं एक बनाम दूसरे का उपयोग करने पर सर्वोत्तम प्रथाओं के लिए लोगों की युक्तियों की तलाश कर रहा हूं। धन्यवाद!


3
यहां यूयूआईडी का एक वैकल्पिक तरीका है। हालांकि टक्कर की संभावना असीम है UUID विशिष्टता की गारंटी नहीं देता है। विशिष्टता की गारंटी के लिए आप यौगिक कुंजी को [<सिस्टम आईडी>, <स्थानीय आईडी>] के रूप में उपयोग कर सकते हैं। डेटा साझाकरण में भाग लेने वाले प्रत्येक सिस्टम के पास सिस्टम की अपनी विशिष्ट आईडी होनी चाहिए जो सिस्टम सेट-अप के दौरान सौंपी गई हो या आईडी के सामान्य पूल से प्राप्त की गई हो। स्थानीय आईडी किसी विशेष प्रणाली के भीतर एक विशिष्ट आईडी है। इसमें अधिक परेशानी शामिल है लेकिन विशिष्टता की गारंटी देता है। ऑफॉपिक के लिए क्षमा करें, बस मदद करने की कोशिश कर रहा है।
oᴉɹǝɥɔ

3
"गोपनीयता की चिंताओं" का उल्लेख नहीं करता है
श्रेय

जवाबों:


253

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

आप 100 से कम में 2 14 से अधिक uuid1 बनाकर डुप्लिकेट बना सकते हैं , लेकिन अधिकांश उपयोग के मामलों के लिए यह कोई समस्या नहीं है।

uuid4()उत्पन्न करता है, जैसा कि आपने कहा, एक यादृच्छिक यूयूआईडी। टक्कर का मौका वास्तव में, वास्तव में, वास्तव में छोटा है। काफी छोटा, कि आपको इसकी चिंता नहीं करनी चाहिए। समस्या यह है, कि एक खराब रैंडम-नंबर जनरेटर से टकराव की संभावना अधिक होती है।

बॉब अमन के इस बेहतरीन जवाब ने इसे अच्छी तरह से गाया। (मैं पूरे उत्तर को पढ़ने की सलाह देता हूं।)

स्पष्ट रूप से, दुर्भावनापूर्ण अभिनेताओं के बिना एक एकल अनुप्रयोग स्थान में, धरती पर सभी जीवन का विलुप्त होने से बहुत पहले ही आपको टक्कर मिल जाएगी, यहां तक ​​कि एक संस्करण 4 यूयूआईडी पर, भले ही आप प्रति सेकंड कुछ यूयूआईडी उत्पन्न कर रहे हों।


क्षमा करें, मैंने पूरी तरह से शोध किए बिना टिप्पणी की - एक संस्करण 1 uuid से टकराने से एक संस्करण 4 uuid रखने के लिए बिट्स आरक्षित हैं। मैं अपनी मूल टिप्पणी को हटा दूंगा। उपकरण देखें ।ietf.org
मार्क रैनसम

1
@ हाँ, जो मैं पढ़ रहा था उससे समझ में आता है। uuid1 "अधिक अद्वितीय" है, जबकि uuid4 अधिक गुमनाम है। इसलिए मूल रूप से uuid1 का उपयोग करें जब तक कि आपके पास कोई कारण न हो। @मार्क फिरौती: जब मैंने uuid1 / uuid4 की खोज की तो बहुत बढ़िया जवाब नहीं आया। सीधे घोड़े के मुंह से, ऐसा लगता है।
रॉकेटमोनकीज

6
uuid1यदि आप एक ही नोड पर प्रति सेकंड कई उत्पादन करते हैं, तो आवश्यक रूप से अद्वितीय यूयूआईडी का उत्पादन नहीं करेंगे। उदाहरण: [uuid.uuid1() for i in range(2)]। जब तक निश्चित रूप से कुछ अजीब चल रहा है कि मैं गायब हूं।
माइकल मिओर

1
@ मिचेल: uuid1एक अनुक्रम संख्या (आपके उदाहरण में 4 तत्व) है, इसलिए जब तक आप काउंटर में सभी बिट्स का उपयोग नहीं करते हैं तब तक आपके पास कोई टक्कर नहीं है।
जॉर्ज शाओली

3
@ मिचेल: मैंने परिस्थितियों पर शोध करने की कोशिश की है जब टकराव होता है और मुझे मिली जानकारी को जोड़ दिया है।
जॉर्ज शॉली

32

एक उदाहरण है जब आप विचार कर सकते हैं uuid1()के बजाय uuid4()है जब UUIDs अलग मशीनों पर उत्पादन किया जाता है , उदाहरण के लिए एक से अधिक ऑनलाइन लेनदेन प्रयोजनों के स्केलिंग के लिए कई मशीनों पर प्रक्रिया कर रहे हैं जब।

ऐसी स्थिति में, छद्म यादृच्छिक संख्या जनरेटर के तरीके में खराब विकल्पों के कारण टकराव होने का जोखिम, उदाहरण के लिए, और साथ ही UUIDs की संभावित उच्चतर संख्या ने डुप्लिकेट आईडी बनाने की संभावना को प्रस्तुत किया।

uuid1()उस मामले में एक और दिलचस्पी यह है कि मशीन जहां प्रत्येक GUID को शुरू में उत्पादित किया गया था, वह अंतर्निहित रूप से (UUID के "नोड" भाग में) दर्ज है। यह और समय की जानकारी, केवल डिबगिंग के साथ मदद कर सकता है।


20

मेरी टीम बस एक डेटाबेस अपग्रेड स्क्रिप्ट के लिए UUID1 का उपयोग करके मुसीबत में भाग गई, जहां हमने कुछ मिनटों के भीतर ~ 120k UUIDs उत्पन्न किया। UUID टकराव के कारण प्राथमिक कुंजी बाधा का उल्लंघन हुआ।

हमने 100s सर्वरों को अपग्रेड किया है, लेकिन हमारे अमेज़ॅन EC2 उदाहरणों पर हम कुछ बार इस मुद्दे में भाग गए। मुझे खराब घड़ी के संकल्प पर संदेह है और UUID4 पर स्विच करने से यह हमारे लिए हल हो गया।


5

उपयोग करते समय ध्यान देने वाली एक बात uuid1, यदि आप डिफ़ॉल्ट कॉल ( clock_seqपैरामीटर दिए बिना ) का उपयोग करते हैं , तो आपके पास टक्करों में चलने का एक मौका होता है: आपके पास केवल 14 बिट यादृच्छिकता है (100ns के भीतर 18 प्रविष्टियां पैदा करने से आपको टक्कर का लगभग 1% मौका मिलता है) जन्मदिन विरोधाभास / हमला)। समस्या ज्यादातर उपयोग के मामलों में कभी नहीं होगी, लेकिन खराब घड़ी के संकल्प के साथ एक आभासी मशीन पर यह आपको काट लेगी।


7
@ गिलाइम यह वास्तव में उपयोगी अभ्यास का एक उदाहरण देखने के लिए उपयोगी होगा clock_seq....
eric

@ गिलूम ने 1% के इस मौके की गणना कैसे की है? यादृच्छिकता के 14 बिट्स का अर्थ है कि टक्कर होने की गारंटी होगी यदि आप उत्पन्न करते हैं> = 2 ^ 14 id प्रति 100ns और इसका मतलब है कि टक्कर का 1% मौका तब होता है जब आप प्रति 100 ns लगभग 163 आईडी का उत्पादन करते हैं
maks

1
@ मैक्स जैसा कि मैंने कहा, आपको जन्मदिन के विरोधाभास को देखना चाहिए ।
गिलाउम

3

शायद कुछ जिसका उल्लेख नहीं किया गया है, वह है स्थानीयता।

एक मैक एड्रेस या टाइम-बेस्ड ऑर्डरिंग (UUID1) डेटाबेस के प्रदर्शन को बढ़ा सकता है, क्योंकि संख्याओं को क्रमबद्ध रूप से वितरित करने के लिए यह एक साथ कम काम है, जो कि रैंडमली (UUID4) वितरित किए गए हैं ( यहाँ देखें )।

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


1

स्वीकृत उत्तर के अलावा, एक तीसरा विकल्प है जो कुछ मामलों में उपयोगी हो सकता है:

v1 यादृच्छिक मैक के साथ ("v1mc")

आप यादृच्छिक प्रसारण मैक पते के साथ जानबूझकर v1 UUIDs उत्पन्न करके v1 और v4 के बीच एक संकर बना सकते हैं (यह v1 कल्पना द्वारा अनुमति दी गई है)। परिणामी v1 UUID समय निर्भर है (नियमित v1 की तरह), लेकिन सभी होस्ट-विशिष्ट जानकारी (जैसे v4) का अभाव है। यह टक्कर-प्रतिरोध में v4 के बहुत करीब है: v1mc = 60 बिट्स समय + 61 यादृच्छिक बिट्स = 121 अद्वितीय बिट्स; v4 = 122 यादृच्छिक बिट्स।

प्रथम स्थान पर मेरा सामना पोस्टग्रेज के uuid_generate_v1mc () फ़ंक्शन से हुआ था। मैंने तब से निम्नलिखित अजगर का उपयोग किया है:

from os import urandom
from uuid import uuid1
_int_from_bytes = int.from_bytes  # py3 only

def uuid1mc():
    # NOTE: The constant here is required by the UUIDv1 spec...
    return uuid1(_int_from_bytes(urandom(6), "big") | 0x010000000000)

(नोट: मुझे एक लंबा + तेज संस्करण मिला है जो सीधे UUID ऑब्जेक्ट बनाता है; कोई भी चाहे तो पोस्ट कर सकता है)


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

import random
from uuid import uuid1

def uuid1mc_insecure():
    return uuid1(random.getrandbits(48) | 0x010000000000)

इस विधि की तरह लगता है "की तरह" v4 (मेजबान-अज्ञेयवादी), लेकिन इससे भी बदतर (कम बिट्स, यूरेनियम पर निर्भरता, आदि)। क्या सिर्फ uuid4 की तुलना में कोई फायदे हैं?
रॉकेटमनकीज

यह मुख्य रूप से केवल उन मामलों के लिए एक अपग्रेड है जहां v1 समय-आधारित गुणों के लिए उपयोगी है, फिर भी मजबूत टक्कर प्रतिरोध और मेजबान-गोपनीयता वांछित है। एक उदाहरण डेटाबेस के लिए एक प्राथमिक कुंजी के रूप में है - v4 की तुलना में, v1 uuids डिस्क पर लिखते समय बेहतर स्थानीयता होगी, एक अधिक उपयोगी प्राकृतिक प्रकार होगा, आदि। लेकिन अगर आपको एक मामला मिला है जहां एक हमलावर 2 ** की भविष्यवाणी कर रहा है 61 बिट्स एक सुरक्षा मुद्दा है (उदाहरण के लिए uuid a nonce), तो $ डाइटिंग हाँ, इसके बजाय uuid4 का उपयोग करें (मुझे पता है कि मैं करता हूं!)। पुन: बदतर होने के कारण यह यूरेनियम का उपयोग करता है, मुझे यकीन नहीं है कि आपका क्या मतलब है - अजगर के तहत, uuid4 () भी यूरेनियम का उपयोग करता है।
एली कॉलिन्स

अच्छी चीजें, जो समझ में आता है। यह देखना अच्छा नहीं है कि आप क्या कर सकते हैं (आपका कोड), बल्कि यह भी कि आप यह क्यों चाहते हैं। पुन: यूरेनियम, मेरा मतलब है कि आप 2x का उपयोग कर रहे हैं यादृच्छिकता (uuid1 के लिए 1, यूरेनियम के लिए एक और), ताकि सिस्टम एंट्रोपी तेज का उपयोग कर सके।
रॉकेटमनकीज 16

यह वास्तव में uuid4 जितना लगभग आधा है: uuid1 () घड़ी_सेक के लिए 14 बिट्स का उपयोग करता है, जो कि 2 आयामी बाइट्स के साथ गोल होता है। Uuid1mc रैपर 48 बिट्स का उपयोग करता है, जो कि प्रति कॉल खपत किए जाने वाले कुल 8 यूरेनियम (8) उपभोग के लिए 6 बाइट्स का उपयोग करता है। जबकि uuid4 हर कॉल के लिए सीधे यूरेनियम (16) को आमंत्रित करता है।
एली कॉलिन्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.