Tạo ID có thể đọc / sử dụng được, ngắn nhưng duy nhất của con người


87
  • Cần xử lý> 1000 nhưng <10000 bản ghi mới mỗi ngày

  • Không thể sử dụng GUID / UUID, số tự động tăng dần, v.v.

  • Tốt nhất nên dài 5 hoặc 6 ký tự, tất nhiên có thể là alpha

  • Muốn sử dụng lại các bí danh nổi tiếng hiện có, nếu có

Có gì ngoài đó không?


Tại sao không sử dụng INT hoặc BIGINT được tự động tăng cường? Nó có lẽ là dễ đọc nhất và có thể dễ dàng xử lý âm lượng.
Malk

theo Q ở trên, cố gắng giữ tối đa 5/6 ký tự và hỗ trợ tối đa 9999 bản ghi mới mỗi ngày
Kumar

@Kumar - Nếu bạn cần hơn 9999 bản ghi trong một ngày thì sao? Giải pháp đề xuất của bạn nghe có vẻ không khả thi.
ChaosPandion

@ChaosPandion: Tôi nghĩ đây có lẽ là những phỏng đoán sơ bộ về tải / lưu lượng truy cập hơn là giới hạn cứng. Tôi không chắc tại sao bạn lại muốn đặt giới hạn tùy ý về số lượng giao dịch hàng ngày.
Paul Sasik

Bạn có thể mã hóa nó thành cơ sở 64 và sử dụng nó. Tôi không chắc bạn có thể giảm nó nhỏ hơn mà vẫn sử dụng các ký tự có thể đọc được. Nhưng tôi lập luận rằng cơ số 64 khó đọc hơn nhiều so với cơ sở 32 vì nó yêu cầu thêm một định nghĩa bổ sung cho hầu hết các ký tự (chữ f viết hoa, chữ o thấp hơn, chữ o thấp hơn so với chỉ f, oo).
Malk

Câu trả lời:


119

Cơ sở 62 được sử dụng bởi tinyurl và bit.ly cho các URL viết tắt. Đó là một phương pháp dễ hiểu để tạo ID "duy nhất", con người có thể đọc được. Tất nhiên bạn sẽ phải lưu trữ các ID đã tạo và kiểm tra các bản sao khi tạo để đảm bảo tính duy nhất. (Xem mã ở cuối câu trả lời)

Chỉ số tính duy nhất cơ sở 62

5 ký tự trong cơ số 62 sẽ cung cấp cho bạn 62 ^ 5 ID duy nhất = 916.132.832 (~ 1 tỷ) Với 10k ID mỗi ngày, bạn sẽ ổn với 91k + ngày

6 ký tự trong cơ số 62 sẽ cung cấp cho bạn 62 ^ 6 ID duy nhất = 56.800.235.584 (hơn 56 tỷ) Với 10k ID mỗi ngày, bạn sẽ ổn trong hơn 5 triệu ngày

Số liệu về tính duy nhất cơ sở 36

6 ký tự sẽ cung cấp cho bạn 36 ^ 6 ID duy nhất = 2.176.782.336 (hơn 2 tỷ)

7 ký tự sẽ cung cấp cho bạn 36 ^ 7 ID duy nhất = 78.364.164.096 (hơn 78 tỷ)

Mã:

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();
    }
}

Đầu ra:

z5KyMg
wd4SUp
uSzQtH
UPrGAT
UIf2IS

QCF9GNM5
0UV3TFSS
3MG91VKP
7NTRF10T
AJK3AJU7

3
trông tuyệt vời, bất cứ điều gì không phân biệt chữ hoa chữ thường?
Kumar

2
Nếu bạn muốn tránh phân biệt chữ hoa chữ thường, bạn có thể sử dụng cơ số 36: codeproject.com/Articles/10619/Base-36-type-for-NET-C nhưng để có được nhiều hoán vị như cơ số 62, bạn sẽ cần sử dụng nhiều ký tự hơn trong TÔI. Đó là một sự đánh đổi. Hoặc bạn có thể cố gắng sử dụng các ký tự khác ngoài alpha, nhưng điều đó trở nên xấu đối với người dùng.
Paul Sasik

2
tại đây stackoverflow.com/questions/9543892/… & cảm ơn rất nhiều
Kumar

11
Một ý nghĩ. Có lẽ nên loại bỏ các nguyên âm để ngăn chặn việc vô tình tạo ra các từ chửi thề. Đặc biệt nếu nó phải đối mặt với công chúng.
Damien Sawyer

4
Tùy thuộc vào nơi bạn đang sử dụng mã này (đặc biệt nếu con người được mong đợi sẽ đọc và nhập lại mã), bạn có thể muốn xem xét loại bỏ các ký tự khó hiểu: 0 / O và I / l / 1. Điều này có thể được giảm thiểu trong một số trường hợp bằng cách lựa chọn phông chữ tốt, nhưng tôi không thể nói từ câu hỏi liệu OP có kiểm soát điều đó hay không.
GrandOpener

17

Tôi đề xuất http://hashids.org/ chuyển đổi bất kỳ số nào (ví dụ: DB ID) thành một chuỗi (sử dụng muối).

Nó cho phép giải mã chuỗi này trở lại số. Vì vậy, bạn không cần phải lưu trữ nó trong cơ sở dữ liệu.

Có libs cho JavaScript, Ruby, Python, Java, Scala, PHP, Perl, Swift, Clojure, Objective-C, C, C ++ 11, Go, Erlang, Lua, Elixir, ColdFusion, Groovy, Kotlin, Nim, VBA, CoffeeScript và cho Node.js & .NET.


1
Bạn có thể cung cấp bất kỳ tùy chọn nào khác tương tự như đề xuất của bạn không? - - Nó rất thú vị. Tôi muốn biết nếu có bất kỳ tùy chọn mặc định nào như vậy trong PostgreSQL.
Léo Léopold Hertz 준영

1
Đây là phiên bản .NET của nó, nhưng bạn có thể giải thích cách nó hoạt động mà không cần lưu trữ trong cơ sở dữ liệu không? Tôi có thể chỉ tạo số ngẫu nhiên duy nhất mà không cần nhập số làm đầu vào và không có muối không?
shaijut

@Slawa Tôi cần một cái gì đó giống như băm cho .NET nhưng băm cuối cùng sẽ được lưu trữ trong db trong một cột có độ dài cố định, có thể nói luôn tạo băm với độ dài tối đa là N không?
Anon Dev

6

Tôi đã có những yêu cầu tương tự như OP. Tôi đã xem xét các thư viện có sẵn nhưng hầu hết chúng đều dựa trên sự ngẫu nhiên và tôi không muốn điều đó. Tôi thực sự không thể tìm thấy bất kỳ thứ gì không dựa trên ngẫu nhiên và vẫn còn rất ngắn ... Vì vậy, tôi đã kết thúc việc tự làm dựa trên kỹ thuật mà Flickr sử dụng , nhưng được sửa đổi để yêu cầu ít phối hợp hơn và cho phép thời gian ngoại tuyến lâu hơn.

Nói ngắn gọn:

  • Máy chủ trung tâm phát hành các khối ID bao gồm 32 ID mỗi khối
  • Trình tạo ID cục bộ duy trì một nhóm các khối ID để tạo ID mỗi khi một ID được yêu cầu. Khi hồ bơi gần hết, nó tìm nạp thêm khối ID từ máy chủ để lấp đầy lại.

Nhược điểm:

  • Yêu cầu phối hợp trung tâm
  • ID ít nhiều có thể dự đoán được (ít hơn so với id DB thông thường nhưng chúng không phải ngẫu nhiên)

Ưu điểm

  • Lưu trữ trong vòng 53 bit (kích thước tối đa của Javascript / PHP cho các số nguyên)
  • ID rất ngắn
  • Cơ sở 36 được mã hóa để con người rất dễ đọc, viết và phát âm
  • ID có thể được tạo cục bộ trong một thời gian rất dài trước khi cần liên hệ lại với máy chủ (tùy thuộc vào cài đặt nhóm)
  • Về mặt lý thuyết không có cơ hội collissions

Tôi đã xuất bản cả thư viện Javascript cho phía máy khách, cũng như triển khai máy chủ Java EE. Việc triển khai máy chủ bằng các ngôn ngữ khác cũng phải dễ dàng.

Dưới đây là các dự án:

suid - Dịch vụ được phân phối-ID duy nhất ngắn và hấp dẫn

suid-server-java - Triển khai suid-server cho ngăn xếp công nghệ Java EE.

Cả hai thư viện đều có sẵn theo giấy phép nguồn mở Creative Commons tự do. Hy vọng điều này có thể giúp những người khác đang tìm kiếm các ID ngắn duy nhất.


Bạn có thể vui lòng so sánh stackoverflow.com/a/29372036/54964 với đề xuất của mình suidkhông?
Léo Léopold Hertz 준영

1
Nó dựa trên các số ngẫu nhiên. Nó thực sự là khá tuyệt vời. Nhưng ID của bạn sẽ không ngắn như chúng có thể. Tôi đã viết SUID để bắt đầu đánh số từ 1 nên bạn sẽ bắt đầu với những ID cực kỳ ngắn . Suy nghĩ 3 hoặc 4 ký tự. Thêm vào đó, nó có một số lợi thế tuyệt vời khác là có (gần như) các ID được sắp xếp tăng dần, ngoài việc bắt đầu với những ID thực sự ngắn.
Stijn de Witt

3

Tôi đã sử dụng cơ sở 36 khi giải quyết vấn đề này cho một ứng dụng mà tôi đang phát triển vài năm trước. Tôi cần tạo một số duy nhất hợp lý có thể đọc được của con người (dù sao thì trong năm dương lịch hiện tại). Tôi đã chọn sử dụng thời gian tính bằng mili giây từ nửa đêm ngày 1 tháng 1 của năm hiện tại (vì vậy mỗi năm, dấu thời gian có thể trùng lặp) và chuyển nó thành số cơ sở 36. Nếu hệ thống đang được phát triển gặp sự cố nghiêm trọng, nó sẽ tạo ra số cơ sở 36 (7 ký tự) được hiển thị cho người dùng cuối thông qua giao diện web, người này sau đó có thể chuyển tiếp sự cố gặp phải (và số) cho người hỗ trợ kỹ thuật (người sau đó có thể sử dụng nó để tìm điểm trong nhật ký nơi ngăn xếp bắt đầu). Một số như 56af42g7người dùng đọc và chuyển tiếp dễ dàng hơn vô cùng so với dấu thời gian như 2016-01-21T15: 34: 29.933-08: 00 hoặc UUID ngẫu nhiên như 5f0d3e0c-da96-11e5-b5d2-0a1d41d68578 .


4
Bạn có thể vui lòng cung cấp mã giả trong một biểu mẫu có cấu trúc về đề xuất của mình không? Nghe thú vị.
Léo Léopold Hertz 준영

0

Tôi thực sự thích sự đơn giản của việc chỉ mã hóa một GUID bằng định dạng Base64 và cắt bớt dấu == để có được một chuỗi gồm 22 ký tự (cần một dòng mã và bạn luôn có thể chuyển đổi nó trở lại GUID). Đáng buồn thay, nó đôi khi bao gồm các ký tự + và /. OK cho cơ sở dữ liệu, không tốt cho URL, nhưng nó đã giúp tôi đánh giá cao các câu trả lời khác :-)

Từ https://www.codeproject.com/Tips/1236704/Reducing-the-string-Length-of-a-Guid của Christiaan van Bergen

Chúng tôi nhận thấy rằng việc chuyển đổi Guid (16 byte) thành biểu diễn ASCII bằng cách sử dụng Base64 dẫn đến một messageID duy nhất và có thể sử dụng được chỉ gồm 22 ký tự.

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

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

Ví dụ: Hướng dẫn 'e6248889-2a12-405a-b06d-9695b82c0a9c' (độ dài chuỗi: 36) sẽ nhận được biểu diễn Base64: 'iYgk5hIqWkCwbZaVuCwKnA ==' (độ dài chuỗi: 24)

Biểu diễn Base64 kết thúc bằng các ký tự '=='. Bạn chỉ có thể cắt bớt những thứ này mà không ảnh hưởng gì đến tính độc đáo. Để lại cho bạn một mã định danh chỉ dài 22 ký tự.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.