8 자 전용 UUID 생성
UUID 라이브러리는 32 자 UUID를 생성합니다.
8 자 전용 UUID를 생성하고 싶습니다. 가능합니까?
UUID는 정의당 16 바이트 숫자이므로 불가능합니다. 물론 8 자 길이의 고유 한 문자열을 생성 할 수 있습니다 (다른 답변 참조).
또한 ID의 일부가 고정 된 바이트를 포함 할 수 있으므로 더 긴 UUID를 생성하고 하위 문자열을 지정할 때주의해야합니다 (예 : MAC, DCE 및 MD5 UUID의 경우).
RandomStringUtils
apache.commons에서 수업을 시도 할 수 있습니다 .
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.randomUUID 또는 .net GUID에서 생성 된 고유 ID조차도 100 % 고유하지 않습니다. 특히 UUID.randomUUID는 128 비트 (보안) 임의 값 "전용"입니다. 따라서 64 비트, 32 비트, 16 비트 (또는 1 비트)로 줄이면 단순히 덜 고유 해집니다.
따라서 최소한 위험 기반 결정, uuid가 얼마나 길어야 하는가입니다.
둘째 : "8 자만"이라는 말은 일반 인쇄 가능한 8 자 문자열을 의미한다고 가정합니다.
길이가 8 개의 인쇄 가능한 문자로 된 고유 한 문자열을 원한다면 base64 인코딩을 사용할 수 있습니다. 이것은 문자 당 6 비트를 의미하므로 총 48 비트를 얻게됩니다 (그다지 고유하지는 않지만 응용 프로그램에 적합 할 수도 있음).
따라서 방법은 간단합니다. 6 바이트 임의 배열 생성
SecureRandom rand;
// ...
byte[] randomBytes = new byte[16];
rand.nextBytes(randomBytes);
그런 다음 예를 들어 다음과 같이 Base64 문자열로 변환합니다. org.apache.commons.codec.binary.Base64
BTW : 무작위로 "uuid"를 만드는 더 좋은 방법이 있는지 응용 프로그램에 따라 다릅니다. (초당 한 번만 UUID를 생성하는 경우 타임 스탬프를 추가하는 것이 좋습니다.) (참고 : 두 개의 임의 값을 결합 (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()), '=');
}
이것은 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가없는 솔루션을 생각하고 있습니다.
DB로
회사 이름 (짧은 이름 3 자) ---- Random_Number ---- 키 특정 redis COUNTER
(3 자) -------------------------- ---------------------- (2 자) ---------------- (11 자)
DB없이
IPADDRESS ---- THREAD_NUMBER ---- INCR_NUMBER ---- epoch milliseconds
(5 chars) ----------------- (2char) ----------------------- (2 char) ----------------- (6 char)
will update you once coding is done.
How about this one? Actually, this code returns 13 characters max, but it shorter than 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);
}
I do not think that it is possible but you have a good workaround.
- cut the end of your UUID using substring()
- use code
new Random(System.currentTimeMillis()).nextInt(99999999);
this will generate random ID up to 8 characters long. generate alphanumeric 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
'Programing' 카테고리의 다른 글
데이터베이스 호출에 대한 단위 테스트를 작성하는 방법 (0) | 2020.11.28 |
---|---|
Scala 및 Haskell 유형 시스템의 차이점과 유사점은 무엇입니까? (0) | 2020.11.28 |
Jenkins (Hudson)에서 플러그인을 제거하려면 어떻게해야합니까? (0) | 2020.11.28 |
R 패키지 개발 버전을 설치하는 방법 github 저장소 (0) | 2020.11.28 |
jQuery에 요소가 있는지 정말로 확인해야합니까? (0) | 2020.11.27 |