Do not lock when generating time based uuid (#52436)

Currently we lock when generating time based uuids. The lock is
implemented to prevent concurrent writes to the last timestamp. The uuid
generation is an area of contention when indexing. This commit modifies
the code to use atomic compare and set operations to update the last
timestamp.
This commit is contained in:
Tim Brooks 2020-02-18 08:09:07 -07:00
parent 123b3c6f55
commit 8038f9bba6
No known key found for this signature in database
GPG Key ID: C2AA3BB91A889E77
1 changed files with 13 additions and 11 deletions

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common;
import java.util.Base64;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* These are essentially flake ids but we use 6 (not 8) bytes for timestamp, and use 3 (not 2) bytes for sequence number. We also reorder
@ -37,7 +38,7 @@ class TimeBasedUUIDGenerator implements UUIDGenerator {
private final AtomicInteger sequenceNumber = new AtomicInteger(SecureRandomHolder.INSTANCE.nextInt());
// Used to ensure clock moves forward:
private long lastTimestamp;
private final AtomicLong lastTimestamp = new AtomicLong(0);
private static final byte[] SECURE_MUNGED_ADDRESS = MacAddressProvider.getSecureMungedAddress();
@ -58,21 +59,22 @@ class TimeBasedUUIDGenerator implements UUIDGenerator {
@Override
public String getBase64UUID() {
final int sequenceId = sequenceNumber.incrementAndGet() & 0xffffff;
long timestamp = currentTimeMillis();
long currentTimeMillis = currentTimeMillis();
synchronized (this) {
// Don't let timestamp go backwards, at least "on our watch" (while this JVM is running). We are still vulnerable if we are
// shut down, clock goes backwards, and we restart... for this we randomize the sequenceNumber on init to decrease chance of
// collision:
timestamp = Math.max(lastTimestamp, timestamp);
long timestamp = this.lastTimestamp.updateAndGet(lastTimestamp -> {
// Don't let timestamp go backwards, at least "on our watch" (while this JVM is running). We are
// still vulnerable if we are shut down, clock goes backwards, and we restart... for this we
// randomize the sequenceNumber on init to decrease chance of collision:
long nonBackwardsTimestamp = Math.max(lastTimestamp, currentTimeMillis);
if (sequenceId == 0) {
// Always force the clock to increment whenever sequence number is 0, in case we have a long time-slip backwards:
timestamp++;
// Always force the clock to increment whenever sequence number is 0, in case we have a long
// time-slip backwards:
nonBackwardsTimestamp++;
}
lastTimestamp = timestamp;
}
return nonBackwardsTimestamp;
});
final byte[] uuidBytes = new byte[15];
int i = 0;