8자만의 UUID 생성
UUID 라이브러리는 32글자의 UUID를 생성합니다.
8글자만의 UUID를 생성하고 싶은데 가능한가요?
UUID는 정의당 16바이트 숫자이기 때문에 불가능합니다.단, 물론 8글자의 고유 문자열을 생성할 수 있습니다(다른 답변 참조).
또, ID 의 일부에 고정 바이트가 포함되는 경우가 있기 때문에, 보다 긴 UUID 를 생성해 서브스트링 하는 것에 주의해 주세요(MAC, DCE, MD5 UUID 등).
해 보세요.RandomStringUtils
apache.disclass:
import org.apache.commons.lang3.RandomStringUtils;
final int SHORT_ID_LENGTH = 8;
// all possible unicode characters
String shortId = RandomStringUtils.random(SHORT_ID_LENGTH);
URL도 인간 친화적이지 않은 모든 문자를 포함하므로 주의하시기 바랍니다.
다른 방법도 확인해 주세요.
// HEX: 0-9, a-f. For example: 6587fddb, c0f182c1
shortId = RandomStringUtils.random(8, "0123456789abcdef");
// a-z, A-Z. For example: eRkgbzeF, MFcWSksx
shortId = RandomStringUtils.randomAlphabetic(8);
// 0-9. For example: 76091014, 03771122
shortId = RandomStringUtils.randomNumeric(8);
// a-z, A-Z, 0-9. For example: WRMcpIk7, s57JwCVA
shortId = RandomStringUtils.randomAlphanumeric(8);
다른 사람들이 말했듯이 id가 작을 때 id가 충돌할 가능성이 클 수 있습니다.생일 문제가 당신의 경우에 어떻게 적용되는지 확인해 보세요.이 답변에서 근사치를 계산하는 방법에 대한 좋은 설명을 찾을 수 있습니다.
첫 번째: Java UUID.random에 의해 생성된 고유 ID도 마찬가지입니다.UUID 또는 .net GUID는 100% 고유하지 않습니다.특히 UUID.랜덤UUID는 128비트(시큐어) 랜덤 값입니다.따라서 64비트, 32비트, 16비트(또는 1비트)로 줄이면 고유성이 떨어집니다.
따라서 UUID의 길이는 최소한 리스크에 따라 결정됩니다.
두 번째: "8자만"이라는 말은 보통 인쇄 가능한 8자의 문자열을 의미한다고 생각합니다.
인쇄 가능한 길이가8 문자의 고유 문자열을 원하는 경우 base64 인코딩을 사용할 수 있습니다.이는 문자당 6비트를 의미하므로 총 48비트를 얻을 수 있습니다(매우 고유하지는 않을 수 있지만 애플리케이션에는 문제가 없을 수 있습니다).
방법은 간단합니다. 6바이트 랜덤 어레이 생성
SecureRandom rand;
// ...
byte[] randomBytes = new byte[16];
rand.nextBytes(randomBytes);
String으로 예: Base64 String예를 들어 다음과 같습니다.org.apache.commons.codec.binary.Base64
BTW: 랜덤으로 "uuid"를 생성하는 더 나은 방법이 있다면 애플리케이션에 따라 달라집니다.(UUID를 1초에 1회만 작성하는 경우 타임스탬프를 추가하는 것이 좋습니다). (그런데 2개의 랜덤 값을 조합(xor)하면 결과는 항상 적어도 양쪽 중 가장 랜덤한 값만큼 랜덤합니다).
@Cephalopod가 말했듯이 불가능하지만 UUID를 22자로 줄일 수 있습니다.
public static String encodeUUIDBase64(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return StringUtils.trimTrailingCharacter(BaseEncoding.base64Url().encode(bb.array()), '=');
}
UUID는 아니지만, 이 방법은 유효합니다.
UUID.randomUUID().toString().replace("-","").substring(0,8)
이것은 어떠세요?실제로 이 코드는 최대 13자를 반환하지만 UUID보다 짧습니다.
import java.nio.ByteBuffer;
import java.util.UUID;
/**
* Generate short UUID (13 characters)
*
* @return short UUID
*/
public static String shortUUID() {
UUID uuid = UUID.randomUUID();
long l = ByteBuffer.wrap(uuid.toString().getBytes()).getLong();
return Long.toString(l, Character.MAX_RADIX);
}
이 방법은 Anton Purin의 답변을 기반으로 한 고유한 오류 코드를 생성하기 위해 사용하는 것과 유사하지만 보다 적절한 방법에 의존합니다.org.apache.commons.text.RandomStringGenerator
(한 번, 더 이상) 추천되지 않는 대신org.apache.commons.lang3.RandomStringUtils
:
@Singleton
@Component
public class ErrorCodeGenerator implements Supplier<String> {
private RandomStringGenerator errorCodeGenerator;
public ErrorCodeGenerator() {
errorCodeGenerator = new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(t -> t >= '0' && t <= '9', t -> t >= 'A' && t <= 'Z', t -> t >= 'a' && t <= 'z')
.build();
}
@Override
public String get() {
return errorCodeGenerator.generate(8);
}
}
충돌에 대한 모든 조언이 여전히 적용되므로 주의하시기 바랍니다.
사실 타임스탬프 기반의 더 짧은 고유 식별자를 원하기 때문에 아래 프로그램을 사용해 보았습니다.
로 추측할 수 있다.nanosecond + ( endians.length * endians.length )
콤비네이션입니다.
public class TimStampShorterUUID {
private static final Character [] endians =
{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
private static ThreadLocal<Character> threadLocal = new ThreadLocal<Character>();
private static AtomicLong iterator = new AtomicLong(-1);
public static String generateShorterTxnId() {
// Keep this as secure random when we want more secure, in distributed systems
int firstLetter = ThreadLocalRandom.current().nextInt(0, (endians.length));
//Sometimes your randomness and timestamp will be same value,
//when multiple threads are trying at the same nano second
//time hence to differentiate it, utilize the threads requesting
//for this value, the possible unique thread numbers == endians.length
Character secondLetter = threadLocal.get();
if (secondLetter == null) {
synchronized (threadLocal) {
if (secondLetter == null) {
threadLocal.set(endians[(int) (iterator.incrementAndGet() % endians.length)]);
}
}
secondLetter = threadLocal.get();
}
return "" + endians[firstLetter] + secondLetter + System.nanoTime();
}
public static void main(String[] args) {
Map<String, String> uniqueKeysTestMap = new ConcurrentHashMap<>();
Thread t1 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t3 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t4 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t5 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t6 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t7 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
}
}
업데이트: 이 코드는 단일 JVM에서 작동하지만 분산 JVM에서 생각해야 합니다.따라서 DB가 있는 솔루션과 DB가 없는 솔루션을 2개 생각하고 있습니다.
DB 포함
회사명(짧은 이름 3자) ----Random_Number ---- 키 고유의 redis 카운터
(3글자) ----------------------------------------------------------------------------------------------------------------------------------------------------------
DB 없음
IPADDRESS ----TRAD_NUMBER ----INCR_NUMBER ----에폭밀리초
(5글자) ----------------------------------------------------------------------------------------------------------------------------------------------------------
코딩이 완료되면 업데이트가 됩니다.
나는 그것이 가능하다고 생각하지 않지만 너는 좋은 해결책을 가지고 있다.
- 서브스트링()을 사용하여 UUID의 끝을 잘라냅니다.
- 코드를 사용하다
new Random(System.currentTimeMillis()).nextInt(99999999);
최대 8자 길이의 랜덤 ID가 생성됩니다. 영숫자 ID 생성:
char[] chars = "abcdefghijklmnopqrstuvwxyzABSDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray(); Random r = new Random(System.currentTimeMillis()); char[] id = new char[8]; for (int i = 0; i < 8; i++) { id[i] = chars[r.nextInt(chars.length)]; } return new String(id);
언급URL : https://stackoverflow.com/questions/4267475/generating-8-character-only-uuids
'source' 카테고리의 다른 글
MySQL "IN" 쿼리에서 순서 유지 (0) | 2023.01.09 |
---|---|
반복기를 목록으로 변환하는 가장 빠른 방법 (0) | 2023.01.09 |
지연 배열을 $.when()에 전달합니다. (0) | 2023.01.09 |
여기서 구는 조건을 건너뜁니다. (0) | 2023.01.09 |
Vue js : _이것.$syslog는 함수가 아닙니다. (0) | 2023.01.09 |