मानव-पठनीय / उपयोग करने योग्य, संक्षिप्त लेकिन अद्वितीय आईडी बनाना


86
  • प्रति दिन 1000 लेकिन <10000 नए रिकॉर्ड को संभालने की आवश्यकता है

  • GUID / UUIDs, ऑटो वेतन वृद्धि संख्या आदि का उपयोग नहीं कर सकते

  • आदर्श रूप से 5 या 6 चार्ट लंबा होना चाहिए, निश्चित रूप से अल्फा हो सकता है

  • यदि उपलब्ध हो तो मौजूदा, प्रसिद्ध अल्गोस का पुन: उपयोग करना चाहेंगे

वहाँ कुछ भी?


एक INT या BIGINT का उपयोग क्यों नहीं किया जाता है जो कि स्वत: स्फूर्त है? यह शायद सबसे अधिक पठनीय है और आसानी से वॉल्यूम को संभाल सकता है।
मलक

ऊपर क्यू के अनुसार, इसे 5/6 चार्ट अधिकतम करने की कोशिश कर रहा है और 9999 तक एक दिन में नए रिकॉर्ड का समर्थन कर रहा है
कुमार

@ कुमार - अगर आपको एक दिन में 9999 से अधिक रिकॉर्ड की आवश्यकता है तो क्या होगा? आपका प्रस्तावित समाधान टेनबल नहीं लगता है।
चोसपंडियन

@ पेटोसपांडियन: मुझे लगता है कि ये हार्ड बाउंड के बजाय लोड / ट्रैफ़िक के मोटे तौर पर अनुमान हैं। मुझे यकीन नहीं है कि आप दैनिक लेनदेन की संख्या पर एक मनमाना कैप क्यों सेट करना चाहते हैं।
पॉल शशिक

आप इसे 64 बेस पर एनकोड कर सकते हैं और इसका उपयोग कर सकते हैं। मुझे यकीन नहीं है कि आप इसे उससे कम कर सकते हैं और अभी भी पठनीय पात्रों का उपयोग कर सकते हैं। लेकिन मैं यह दलील दूंगा कि बेस 64 बेस 32 की तुलना में बहुत कम पठनीय है क्योंकि इसमें अधिकांश वर्णों (कैपिटल एफ, लोअर ओ, लोअर ओ बनाम एफ, ओओ) के लिए एक अतिरिक्त क्वालीफायर जोड़ने की आवश्यकता होती है।
मलक

जवाबों:


118

बेस 62 का उपयोग छोटे यूआरएल और संक्षिप्त URL के लिए किया जाता है। यह "अद्वितीय", मानव-पढ़ने योग्य आईडी बनाने के लिए एक अच्छी तरह से समझी गई विधि है। बेशक, आपको विशिष्ट पहचान सुनिश्चित करने के लिए बनाई गई आईडी को स्टोर करना होगा और निर्माण पर डुप्लिकेट की जांच करनी होगी। (जवाब के नीचे कोड देखें)

बेस 62 विशिष्टता मेट्रिक्स

आधार 62 में 5 चार्ट आपको 62 ^ 5 अद्वितीय आईडी = 916,132,832 (~ 1 बिलियन) देगा 10k आईडी पर प्रति दिन आप 91k + दिनों के लिए ठीक होंगे

आधार 62 में 6 चार्ट आपको 62 ^ 6 अद्वितीय आईडी = 56,800,235,584 (56+ बिलियन) प्रति दिन 10k आईडी पर आपको 5+ मिलियन दिनों के लिए ठीक होंगे

बेस 36 विशिष्टता मेट्रिक्स

6 चार्ट आपको 36 ^ 6 अद्वितीय आईडी = 2,176,782,336 (2+ बिलियन) देंगे

7 चार्ट आपको 36 ^ 7 अद्वितीय आईडी = 78,364,164,096 (78+ बिलियन) देंगे

कोड:

public void TestRandomIdGenerator()
{
    // create five IDs of six, base 62 characters
    for (int i=0; i<5; i++) Console.WriteLine(RandomIdGenerator.GetBase62(6));

    // create five IDs of eight base 36 characters
    for (int i=0; i<5; i++) Console.WriteLine(RandomIdGenerator.GetBase36(8));
}

public static class RandomIdGenerator 
{
    private static char[] _base62chars = 
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
        .ToCharArray();

    private static Random _random = new Random();

    public static string GetBase62(int length) 
    {
        var sb = new StringBuilder(length);

        for (int i=0; i<length; i++) 
            sb.Append(_base62chars[_random.Next(62)]);

        return sb.ToString();
    }       

    public static string GetBase36(int length) 
    {
        var sb = new StringBuilder(length);

        for (int i=0; i<length; i++) 
            sb.Append(_base62chars[_random.Next(36)]);

        return sb.ToString();
    }
}

आउटपुट:

z5KyMg
wd4SUp
uSzQtH
UPrGAT
UIf2IS

QCF9GNM5
0UV3TFSS
3MG91VKP
7NTRF10T
AJK3AJU7

3
शानदार लग रहा है, कुछ भी जो संवेदनशील नहीं है?
कुमार

2
आप आधार 36 इस्तेमाल कर सकते हैं आप केस संवेदी से बचना चाहते हैं: codeproject.com/Articles/10619/Base-36-type-for-NET-C लेकिन यह है कि कई क्रमपरिवर्तन आधार 62 के रूप में आप में अधिक वर्णों का उपयोग करने की आवश्यकता होगी पाने के लिए अपने आईडी। यह एक व्यापार है। या आप अल्फा के अलावा अन्य वर्णों का उपयोग करने की कोशिश कर सकते हैं, लेकिन यह उपयोगकर्ताओं के लिए बदसूरत हो जाता है।
पॉल शशिक

2
यहाँ stackoverflow.com/questions/9543892/… और बहुत धन्यवाद
कुमार

11
एक ने सोचा। शायद स्वर की आकस्मिक पीढ़ी को रोकने के लिए स्वरों को बाहर निकालें। खासकर अगर यह सार्वजनिक सामना कर रहा है।
डेमियन सॉयर

4
इस बात पर निर्भर करता है कि आप इसका उपयोग कहां कर रहे हैं (विशेषकर यदि मनुष्यों से कोड पढ़ने और फिर से दर्ज करने की अपेक्षा की जाती है), आप विचार से उलझे हुए वर्णों को हटाने पर विचार कर सकते हैं: 0 / O और I / l / 1। यह कुछ मामलों में अच्छे फ़ॉन्ट विकल्प द्वारा कम किया जा सकता है, लेकिन मैं इस सवाल से नहीं कह सकता कि क्या ओपी का उस पर नियंत्रण होगा।
ग्रैंडऑपनर

17

मैं http://hashids.org/ की सलाह देता हूं जो किसी भी संख्या (जैसे DB ID) को एक स्ट्रिंग (नमक का उपयोग करके) में परिवर्तित करता है।

यह इस स्ट्रिंग को संख्या में वापस डिकोड करने की अनुमति देता है। इसलिए आपको इसे डेटाबेस में संग्रहीत करने की आवश्यकता नहीं है।

JavaScript, Ruby, Python, Java, Scala, PHP, Perl, Swift, Clojure, Objective-C, C, C ++ 11, Go, Erlang, Lua, Elixir, ColdFusion, Groovy, Kotlin, Nim, VBA के लिए libs है। CoffeeScript और Node.js और .NET के लिए।


1
क्या आप अपने प्रस्ताव को अनुकरणीय कोई अन्य विकल्प प्रदान कर सकते हैं? - - यह बहुत रोचक है। मैं जानना चाहूंगा कि क्या PostgreSQL में ऐसा कोई डिफ़ॉल्ट विकल्प है।
लेओ लेपोल्ड हर्ट्ज '28

1
यहाँ इसका .NET संस्करण है, लेकिन क्या आप बता सकते हैं कि डेटाबेस में इसे स्टोर किए बिना यह कैसे काम करता है? क्या मैं इनपुट के रूप में और बिना नमक के नंबर दिए बिना सिर्फ अनोखे रैंडम उत्पन्न कर सकता हूं?
शैजुत

@ शलावा को .NET के लिए हैशिड्स की तरह कुछ चाहिए, लेकिन अंतिम हैश को निश्चित लंबाई वाले कॉलम में db में संग्रहीत किया जाएगा, क्या यह कहना संभव है कि हमेशा N की अधिकतम लंबाई के साथ हैश उत्पन्न करें?
आनोन देव

6

मुझे ओपी के समान आवश्यकताएं थीं। मैंने उपलब्ध पुस्तकालयों में देखा लेकिन उनमें से अधिकांश यादृच्छिकता पर आधारित हैं और मैं ऐसा नहीं चाहता था। मुझे वास्तव में कुछ भी नहीं मिला जो यादृच्छिक और अभी भी बहुत कम पर आधारित नहीं था ... इसलिए मैंने अपनी खुद की तकनीक फ़्लिकर उपयोग के आधार पर रोलिंग को समाप्त कर दिया , लेकिन कम समन्वय की आवश्यकता के लिए संशोधित किया और लंबे समय तक ऑफ़लाइन रहने की अनुमति दी।

संक्षेप में:

  • एक केंद्रीय सर्वर 32 आईडी से मिलकर आईडी ब्लॉक जारी करता है
  • स्थानीय आईडी जनरेटर हर बार एक अनुरोध करने के लिए आईडी बनाने के लिए आईडी ब्लॉक का एक पूल रखता है। जब पूल कम चलता है तो इसे फिर से भरने के लिए सर्वर से अधिक आईडी ब्लॉक प्राप्त होते हैं।

नुकसान:

  • केंद्रीय समन्वय की आवश्यकता है
  • आईडी अधिक या कम अनुमानित हैं (नियमित डीबी आईडी से कम लेकिन वे यादृच्छिक नहीं हैं)

लाभ

  • 53 बिट्स के भीतर स्थित (पूर्णांक संख्या के लिए जावास्क्रिप्ट / PHP अधिकतम आकार)
  • बहुत ही कम आई.डी.
  • बेस 36 मानवों के लिए पढ़ना, लिखना और उच्चारण करना बहुत आसान है
  • सर्वर से फिर से संपर्क करने की जरूरत से पहले (पूल सेटिंग के आधार पर) आईडी को स्थानीय रूप से बहुत लंबे समय के लिए जनरेट किया जा सकता है
  • सैद्धांतिक रूप से टकराव का कोई मौका नहीं

मैंने क्लाइंट पक्ष के लिए एक जावास्क्रिप्ट पुस्तकालय, साथ ही जावा ईई सर्वर कार्यान्वयन दोनों को प्रकाशित किया है। अन्य भाषाओं में सर्वर को लागू करना आसान होना चाहिए।

यहाँ परियोजनाएं हैं:

suid - वितरित सेवा-विशिष्ट आईडी जो छोटी और प्यारी हैं

suid-server-java - जावा EE टेक्नोलॉजी स्टैक के लिए Suid-server कार्यान्वयन।

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


क्या आप कृपया अपने प्रस्ताव को stackoverflow.com/a/29372036/54964 से तुलना कर सकते हैं suid?
लेओ लेपोल्ड हर्ट्ज़ '28

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

3

जब मैंने इस समस्या को हल किया तो मैंने बेस 36 का उपयोग किया, मैं कुछ साल पहले विकसित कर रहा था। मुझे मानव पठनीय रूप से अद्वितीय संख्या (वर्तमान कैलेंडर वर्ष के भीतर) को उत्पन्न करने की आवश्यकता थी । मैंने चालू वर्ष की पहली जनवरी को आधी रात से मिलीसेकंड में समय का उपयोग करने का विकल्प चुना (इसलिए प्रत्येक वर्ष, टाइमस्टैम्प डुप्लिकेट कर सकता है) और इसे आधार संख्या 36 में बदल सकता है। यदि सिस्टम को विकसित किया जा रहा है, तो यह एक घातक मुद्दे में बदल गया है, इसने बेस 36 नंबर (7 वर्ण) उत्पन्न किया जो कि वेब इंटरफेस के माध्यम से एक अंतिम उपयोगकर्ता को प्रदर्शित किया गया था, जो तब एक तकनीकी सहायता वाले व्यक्ति के सामने आने वाली समस्या (और संख्या) को रिले कर सकता था (जो तब इसका उपयोग लॉग में उस बिंदु को खोजने के लिए किया जा सकता है जहां स्टैकट्रेस शुरू हुआ था)। 56af42g7 जैसा नंबर2016-01-21T15: 34: 29.933-08: 00 या 5f0d3e0c-da96-11e5-bdd2-0a1d41d68578 जैसे यादृच्छिक UUID जैसे टाइमस्टैम्प की तुलना में उपयोगकर्ता को पढ़ना और रिले करना सरल है


4
क्या आप कृपया अपने प्रस्ताव के बारे में एक संरचित रूप में छद्म कोड प्रदान कर सकते हैं? यह दिलचस्प लगता है।
लेओ लेपोल्ड हर्ट्ज़ '28

0

मुझे वास्तव में 22 अक्षरों की एक स्ट्रिंग प्राप्त करने के लिए बेस 64 प्रारूप का उपयोग करके GUID को कूटबद्ध करने और ट्रेलिंग == को छोटा करने की सरलता पसंद है (यह कोड की एक पंक्ति लेता है, और आप इसे हमेशा GUID में बदल सकते हैं)। अफसोस की बात है, इसमें कभी-कभी + और / अक्षर शामिल होते हैं। डेटाबेस के लिए ठीक है, URL के लिए महान नहीं है, लेकिन इससे मुझे अन्य उत्तरों की सराहना करने में मदद मिली :-)

से https://www.codeproject.com/Tips/1236704/Reducing-the-string-Length-of-a-Guid क्रिस्टियन वैन बर्गन से

हमने पाया कि बेस 64 का उपयोग करते हुए ASCII प्रतिनिधित्व के लिए गाइड (16 बाइट्स) को परिवर्तित करने का परिणाम केवल 22 अक्षरों का एक प्रयोग करने योग्य और अभी भी अनूठा संदेश था।

var newGuid = Guid.NewGuid();
var messageID = Convert.ToBase64String(newGuid.ToByteArray());

var message22chars = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0,22);

उदाहरण के लिए: गाइड 'e6248889-2a12-405a-b06d-9695b82c0a9c' (स्ट्रिंग लंबाई: 36) को बेस 64 का प्रतिनिधित्व मिलेगा: 'iYgk5hIqWwCwbbZaVuCwKnA ==' (स्ट्रिंग लंबाई: 24)

Base64 प्रतिनिधित्व '==' वर्णों के साथ समाप्त होता है। आप केवल विशिष्टता पर किसी भी प्रभाव के बिना, इन को काट सकते हैं। लंबाई में केवल 22 अक्षरों के पहचानकर्ता के साथ आपको छोड़कर।

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