Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

写入Ringbuffer时,生成的ID会跳过某些时间 #96

Open
qqyycom opened this issue Jul 26, 2024 · 1 comment
Open

写入Ringbuffer时,生成的ID会跳过某些时间 #96

qqyycom opened this issue Jul 26, 2024 · 1 comment

Comments

@qqyycom
Copy link

qqyycom commented Jul 26, 2024

JDK VERSION:openjdk@17.0.11
uid-genertor version: Latest

// 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;
    }

问题:当填入ID时,预先生成ID,判断ringBuffer是否填满的逻辑在ringBuffer.put()最开始。导致总有lastSecond生成了ID,但因为ringBuffer已满,而被废弃。
padding-factor = 50时 每boost-power + 1 个 lastSecond,就有一个被废弃
解决:通过配置padding-factor != 50,使每次生成的UID序列不能完整的加入ringbuffer就出发了ringBuffer已满已满的逻辑
优化:修改put()方法, 当填入一个后,再次判断是否填满

// 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;
    }
@ijaychang
Copy link

其实感觉跳过几个lastSecond又怎么样呢,这个也不能叫浪费吧,不过你的解决方案挺秒的!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants