// com.baidu.fsg.uid.buffer.BufferPaddingExecutor#paddingBuffer()
public void paddingBuffer() {
LOGGER.info("Ready to padding buffer lastSecond:{}. {}", lastSecond.get(), ringBuffer);
// is still running
if (!running.compareAndSet(false, true)) {
LOGGER.info("Padding buffer is still running. {}", ringBuffer);
return;
}
// fill the rest slots until to catch the cursor
boolean isFullRingBuffer = false;
while (!isFullRingBuffer) {
List<Long> uidList = uidProvider.provide(lastSecond.incrementAndGet());
for (Long uid : uidList) {
isFullRingBuffer = !ringBuffer.put(uid);
if (isFullRingBuffer) {
break;
}
}
}
// not running now
running.compareAndSet(true, false);
LOGGER.info("End to padding buffer lastSecond:{}. {}", lastSecond.get(), ringBuffer);
}
// com.baidu.fsg.uid.buffer.RingBuffer#paddingBuffer()
public synchronized boolean put(long uid) {
long currentTail = tail.get();
long currentCursor = cursor.get();
// 判读ringBuffer是否填满的逻辑在最开始
// tail catches the cursor, means that you can't put any cause of RingBuffer is full
long distance = currentTail - (currentCursor == START_POINT ? 0 : currentCursor);
if (distance == bufferSize - 1) {
rejectedPutHandler.rejectPutBuffer(this, uid);
return false;
}
// 1. pre-check whether the flag is CAN_PUT_FLAG
int nextTailIndex = calSlotIndex(currentTail + 1);
if (flags[nextTailIndex].get() != CAN_PUT_FLAG) {
rejectedPutHandler.rejectPutBuffer(this, uid);
return false;
}
// 2. put UID in the next slot
// 3. update next slot' flag to CAN_TAKE_FLAG
// 4. publish tail with sequence increase by one
slots[nextTailIndex] = uid;
flags[nextTailIndex].set(CAN_TAKE_FLAG);
tail.incrementAndGet();
// The atomicity of operations above, guarantees by 'synchronized'. In another word,
// the take operation can't consume the UID we just put, until the tail is published(tail.incrementAndGet())
return true;
}
// com.baidu.fsg.uid.buffer.RingBuffer#paddingBuffer()
public synchronized boolean put(long uid) {
long currentTail = tail.get();
long currentCursor = cursor.get();
// 判读ringBuffer是否填满的逻辑在最开始
// tail catches the cursor, means that you can't put any cause of RingBuffer is full
long distance = currentTail - (currentCursor == START_POINT ? 0 : currentCursor);
if (distance == bufferSize - 1) {
rejectedPutHandler.rejectPutBuffer(this, uid);
return false;
}
// 1. pre-check whether the flag is CAN_PUT_FLAG
int nextTailIndex = calSlotIndex(currentTail + 1);
if (flags[nextTailIndex].get() != CAN_PUT_FLAG) {
rejectedPutHandler.rejectPutBuffer(this, uid);
return false;
}
// 2. put UID in the next slot
// 3. update next slot' flag to CAN_TAKE_FLAG
// 4. publish tail with sequence increase by one
slots[nextTailIndex] = uid;
flags[nextTailIndex].set(CAN_TAKE_FLAG);
// ++++++++++++++
// 判断buffer是否在加入当前ID之后就满了。
boolean result = distance != bufferSize - 2 ;
tail.incrementAndGet();
// The atomicity of operations above, guarantees by 'synchronized'. In another word,
// the take operation can't consume the UID we just put, until the tail is published(tail.incrementAndGet())
return result;
}
JDK VERSION:openjdk@17.0.11 uid-genertor version: Latest
问题:当填入ID时,预先生成ID,判断ringBuffer是否填满的逻辑在
ringBuffer.put()
最开始。导致总有lastSecond生成了ID,但因为ringBuffer已满,而被废弃。 当padding-factor = 50
时 每boost-power + 1
个 lastSecond,就有一个被废弃 解决:通过配置padding-factor != 50,使每次生成的UID序列不能完整的加入ringbuffer就出发了ringBuffer已满已满的逻辑 优化:修改put()方法, 当填入一个后,再次判断是否填满