.NET Short Unique Identifier

前端 未结 23 1178
忘掉有多难
忘掉有多难 2020-12-07 11:27

I need a unique identifier in .NET (cannot use GUID as it is too long for this case).

Do people think that the algorithm used here is a good candidate or do you have

23条回答
  •  广开言路
    2020-12-07 12:06

    In C# a long value has 64 bits, which if encoded with Base64, there will be 12 characters, including 1 padding =. If we trim the padding =, there will be 11 characters.

    One crazy idea here is we could use a combination of Unix Epoch and a counter for one epoch value to form a long value. The Unix Epoch in C# DateTimeOffset.ToUnixEpochMilliseconds is in long format, but the first 2 bytes of the 8 bytes are always 0, because otherwise the date time value will be greater than the maximum date time value. So that gives us 2 bytes to place an ushort counter in.

    So, in total, as long as the number of ID generation does not exceed 65536 per millisecond, we can have an unique ID:

    // This is the counter for current epoch. Counter should reset in next millisecond
    ushort currentCounter = 123;
    
    var epoch = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    // Because epoch is 64bit long, so we should have 8 bytes
    var epochBytes = BitConverter.GetBytes(epoch);
    if (BitConverter.IsLittleEndian)
    {
        // Use big endian
        epochBytes = epochBytes.Reverse().ToArray();
    }
    
    // The first two bytes are always 0, because if not, the DateTime.UtcNow is greater 
    // than DateTime.Max, which is not possible
    var counterBytes = BitConverter.GetBytes(currentCounter);
    if (BitConverter.IsLittleEndian)
    {
        // Use big endian
        counterBytes = counterBytes.Reverse().ToArray();
    }
    
    // Copy counter bytes to the first 2 bytes of the epoch bytes
    Array.Copy(counterBytes, 0, epochBytes, 0, 2);
    
    // Encode the byte array and trim padding '='
    // e.g. AAsBcTCCVlg
    var shortUid = Convert.ToBase64String(epochBytes).TrimEnd('=');
    

提交回复
热议问题