首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成随机UUID非阻塞

生成随机UUID非阻塞
EN

Stack Overflow用户
提问于 2020-02-06 13:46:51
回答 1查看 3.1K关注 0票数 12

通过使用Blockhound io.projectreactor.tools块-junit-平台,我发现UUID.randomUUID是一个阻塞调用,这对我们来说是一个问题,因为我们使用的是SpringBootWeb通量版本2.2.2.RELEASE。

是否有其他方法可以以非阻塞的方式获得随机uuid,或者是否有任何其他java库推荐用于非阻塞生成随机字符串。

从封锁犬的堆栈跟踪:

代码语言:javascript
复制
java.lang.Error: Blocking call! java.io.FileInputStream#readBytes
at reactor.blockhound.BlockHound$Builder.lambda$new$0(BlockHound.java:196) ~[blockhound-1.0.1.RELEASE.jar:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain][ExceptionHandlingWebHandler]
Stack trace:
    at reactor.blockhound.BlockHound$Builder.lambda$new$0(BlockHound.java:196) ~[blockhound-1.0.1.RELEASE.jar:na]
    at reactor.blockhound.BlockHound$Builder.lambda$install$6(BlockHound.java:318) ~[blockhound-1.0.1.RELEASE.jar:na]
    at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:46) ~[na:na]
    at java.base/java.io.FileInputStream.readBytes(FileInputStream.java) ~[na:na]
    at java.base/java.io.FileInputStream.read(FileInputStream.java:279) ~[na:na]
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:133) ~[na:na]
    at java.base/sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:424) ~[na:na]
    at java.base/sun.security.provider.NativePRNG$RandomIO.ensureBufferValid(NativePRNG.java:526) ~[na:na]
    at java.base/sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:545) ~[na:na]
    at java.base/sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:220) ~[na:na]
    at java.base/java.security.SecureRandom.nextBytes(SecureRandom.java:741) ~[na:na]
    at java.base/java.util.UUID.randomUUID(UUID.java:150) ~[na:na]
EN

回答 1

Stack Overflow用户

发布于 2021-12-09 07:57:54

这是关于如何使用uuid-创造者来减少Linux上线程争用的三个示例的列表。

另一个示例使用乌利德-创造者生成单调性ULID,然后将它们转换为RFC-4122UUID(标准)。单调的ULID生成非常快。

基准代码可在GitHub吉斯特上使用。

示例1:使用UuidCreatorSHA1PRNG

如何设置SHA1PRNG算法供UuidCreator使用

代码语言:javascript
复制
# Append to /etc/environment or ~/.profile
# Use the the algorithm SHA1PRNG for SecureRandom
export UUIDCREATOR_SECURERANDOM="SHA1PRNG"
代码语言:javascript
复制
// generate a random-based UUID
UUID uuid = UuidCreator.getRandomBased();

UuidCreator使用固定的SecureRandom池。变量UUIDCREATOR_SECURERANDOM告诉UuidCreator使用另一个SecureRandom算法,而不是在Linux上使用NativePRNGUuidCreatorSHA1PRNG算法生成的UUID比UUID.randomUUID()具有更少的线程争用(更少阻塞)。

请参见使用4个线程的基准测试:

代码语言:javascript
复制
----------------------------------------------------------------------
Benchmark                      Mode  Cnt      Score     Error   Units
----------------------------------------------------------------------
UUID.randomUUID()             thrpt    5   1423,060 ±  30,125  ops/ms
UuidCreator.getRandomBased()  thrpt    5  10616,016 ± 281,486  ops/ms
----------------------------------------------------------------------

示例2:使用ThreadLocalRandom

如何使用ThreadLocalRandom实现UUID生成器

代码语言:javascript
复制
public class UuidGenerator {

    private static final RandomBasedFactory UUID_FACTORY;

    static {
        UUID_FACTORY = new RandomBasedFactory((int length) -> {
            final byte[] bytes = new byte[length];
            ThreadLocalRandom.current().nextBytes(bytes);
            return bytes;
        });
    }

    public static UUID generate() {
        return UUID_FACTORY.create();
    }
}

ThreadLocalRandom是一个快速(且不安全)的随机生成器,没有线程争用(非阻塞)。

请参见使用4个线程的基准测试:

代码语言:javascript
复制
----------------------------------------------------------------------
Benchmark                     Mode  Cnt      Score      Error   Units
----------------------------------------------------------------------
UUID.randomUUID()            thrpt    5   1423,060 ±   30,125  ops/ms
UuidGenerator.generate()     thrpt    5  85390,979 ± 1564,589  ops/ms
----------------------------------------------------------------------

示例3:使用RandomBasedFactory[]SHA1PRNG

如何使用RandomBasedFactorySHA1PRNG算法的ana数组实现UUID生成器:

代码语言:javascript
复制
    public static class UuidGenerator {

        private static final int SIZE = 8; // you choose
        private static final RandomBasedFactory[] FACTORIES;

        static {
            FACTORIES = new RandomBasedFactory[SIZE];
            try {
                for (int i = 0; i < FACTORIES.length; i++) {
                    // SHA1PRNG or DRBG can be used to reduce thread contention.
                    SecureRandom argument = SecureRandom.getInstance("SHA1PRNG");
                    FACTORIES[i] = new RandomBasedFactory(argument);
                }
            } catch (NoSuchAlgorithmException e) {
                // oops!
            }
        }

        public static UUID generate() {
            // calculate the factory index given the current thread ID
            final int index = (int) Thread.currentThread().getId() % SIZE;
            return FACTORIES[index].create();
        }
    }

RandomBasedFactory with和SHA1PRNG算法的数组可以生成线程争用较少(阻塞较少)的UUID。

请参见使用4个线程的基准测试:

代码语言:javascript
复制
----------------------------------------------------------------------
Benchmark                     Mode  Cnt      Score      Error   Units
----------------------------------------------------------------------
UUID.randomUUID()            thrpt    5   1423,060 ±   30,125  ops/ms
UuidGenerator.generate()     thrpt    5  10048,747 ±  195,209  ops/ms
----------------------------------------------------------------------

示例4:使用UlidCreatorMonotonic ULIDs

如何使用乌利德-创造者单调性ULID生成RFC-4122 UUID

代码语言:javascript
复制
// create a Monotonic ULID and convert it to RFC-4122 UUID v4
UUID uuid = UlidCreator.getMonotonicUlid().toRfc4122().toUuid();

请参见使用4个线程的基准测试:

代码语言:javascript
复制
-----------------------------------------------------------------------
Benchmark                       Mode  Cnt     Score      Error   Units
-----------------------------------------------------------------------
UUID.randomUUID()              thrpt    5  1423,060 ±   30,125  ops/ms
UlidCreator.getMonotonicUlid() thrpt    5  7391,917 ±  871,799  ops/ms
-----------------------------------------------------------------------

编辑:添加了第四个使用单调ULID的示例。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60096442

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档