diff --git a/common/src/main/java/org/apache/rocketmq/common/UtilAll.java b/common/src/main/java/org/apache/rocketmq/common/UtilAll.java index ea22aa7397f..a15b4fadf6d 100644 --- a/common/src/main/java/org/apache/rocketmq/common/UtilAll.java +++ b/common/src/main/java/org/apache/rocketmq/common/UtilAll.java @@ -262,6 +262,20 @@ public static String bytes2string(byte[] src) { return new String(hexChars); } + public static void writeInt(char[] buffer, int pos, int value) { + char[] hexArray = HEX_ARRAY; + for (int moveBits = 28; moveBits >= 0; moveBits -= 4) { + buffer[pos++] = hexArray[(value >>> moveBits) & 0x0F]; + } + } + + public static void writeShort(char[] buffer, int pos, int value) { + char[] hexArray = HEX_ARRAY; + for (int moveBits = 12; moveBits >= 0; moveBits -= 4) { + buffer[pos++] = hexArray[(value >>> moveBits) & 0x0F]; + } + } + public static byte[] string2bytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; diff --git a/common/src/main/java/org/apache/rocketmq/common/message/MessageClientIDSetter.java b/common/src/main/java/org/apache/rocketmq/common/message/MessageClientIDSetter.java index 041bf6bae20..57090c17120 100644 --- a/common/src/main/java/org/apache/rocketmq/common/message/MessageClientIDSetter.java +++ b/common/src/main/java/org/apache/rocketmq/common/message/MessageClientIDSetter.java @@ -25,7 +25,7 @@ public class MessageClientIDSetter { private static final String TOPIC_KEY_SPLITTER = "#"; private static final int LEN; - private static final String FIX_STRING; + private static final char[] FIX_STRING; private static final AtomicInteger COUNTER; private static long startTime; private static long nextStartTime; @@ -42,7 +42,7 @@ public class MessageClientIDSetter { tempBuffer.put(ip); tempBuffer.putShort((short) UtilAll.getPid()); tempBuffer.putInt(MessageClientIDSetter.class.getClassLoader().hashCode()); - FIX_STRING = UtilAll.bytes2string(tempBuffer.array()); + FIX_STRING = UtilAll.bytes2string(tempBuffer.array()).toCharArray(); setStartTime(System.currentTimeMillis()); COUNTER = new AtomicInteger(0); } @@ -112,21 +112,22 @@ public static int getPidFromID(String msgID) { } public static String createUniqID() { - StringBuilder sb = new StringBuilder(LEN * 2); - sb.append(FIX_STRING); - sb.append(UtilAll.bytes2string(createUniqIDBuffer())); - return sb.toString(); - } - - private static byte[] createUniqIDBuffer() { - ByteBuffer buffer = ByteBuffer.allocate(4 + 2); + char[] sb = new char[LEN * 2]; + System.arraycopy(FIX_STRING, 0, sb, 0, FIX_STRING.length); long current = System.currentTimeMillis(); if (current >= nextStartTime) { setStartTime(current); } - buffer.putInt((int) (System.currentTimeMillis() - startTime)); - buffer.putShort((short) COUNTER.getAndIncrement()); - return buffer.array(); + int diff = (int)(current - startTime); + if (diff < 0 && diff > -1000_000) { + // may cause by NTP + diff = 0; + } + int pos = FIX_STRING.length; + UtilAll.writeInt(sb, pos, diff); + pos += 8; + UtilAll.writeShort(sb, pos, COUNTER.getAndIncrement()); + return new String(sb); } public static void setUniqID(final Message msg) { diff --git a/common/src/test/java/org/apache/rocketmq/common/message/MessageClientIDSetterTest.java b/common/src/test/java/org/apache/rocketmq/common/message/MessageClientIDSetterTest.java index 0a17c36b57d..1734cbdf755 100644 --- a/common/src/test/java/org/apache/rocketmq/common/message/MessageClientIDSetterTest.java +++ b/common/src/test/java/org/apache/rocketmq/common/message/MessageClientIDSetterTest.java @@ -22,8 +22,30 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.nio.charset.StandardCharsets; + public class MessageClientIDSetterTest { + @Test + public void testGetTimeFromID() { + long t = System.currentTimeMillis(); + String uniqID = MessageClientIDSetter.createUniqID(); + long t2 = MessageClientIDSetter.getNearlyTimeFromID(uniqID).getTime(); + assertThat(t2 - t < 20); + } + + @Test + public void testGetCountFromID() { + String uniqID = MessageClientIDSetter.createUniqID(); + String uniqID2 = MessageClientIDSetter.createUniqID(); + String idHex = uniqID.substring(uniqID.length() - 4); + String idHex2 = uniqID2.substring(uniqID2.length() - 4); + int s1 = Integer.parseInt(idHex, 16); + int s2 = Integer.parseInt(idHex2, 16); + assertThat(s1 == s2 - 1); + } + + @Test public void testGetIPStrFromID() { byte[] ip = UtilAll.getIP();