Skip to content

DistributedId 分布式Id

RockyLOMO edited this page Oct 14, 2022 · 4 revisions

顺序

Snowflake

处理了时钟回拨的情况

@Test
public void snowflake() {
    Set<Long> set = new HashSet<>();
    int len = 1 << 12;
    System.out.println(len);
    Snowflake snowflake = Snowflake.DEFAULT;
    for (int i = 0; i < len; i++) {
        Tasks.run(() -> {
            assert set.add(snowflake.nextId());
        });
    }
}

Universally Unique Lexicographically Sortable Identifier (ULID)

基于这篇文章思路改进。

    @Test
    public void ulid() {
        String jstr = toJsonString(ULID.randomULID());
        ULID id = fromJson(jstr, ULID.class);
        assert jstr.substring(1, jstr.length() - 1).equals(id.toString());

        ULID id1 = ULID.newULID(TConfig.NAME_WYF);
        System.out.println(id1);
        ULID valueOf = ULID.valueOf(id1.toString());
        System.out.println(valueOf);
        assert id1.equals(valueOf);
        valueOf = ULID.valueOf(id1.toBase64String());
        assert id1.equals(valueOf);

        Set<ULID> set = new HashSet<>();
        int len = 100;  //1530ms
        invoke("ulid", i -> {
            ULID x = ULID.randomULID();
            System.out.println(x);
            set.add(x);
            assert ULID.valueOf(x.toString()).equals(x);
        }, len);
        assert set.size() == len;

        for (int i = 0; i < 20; i++) {
            long ts = System.currentTimeMillis();
            assert ULID.newULID(Bytes.getBytes(i), ts).equals(ULID.newULID(Bytes.getBytes(i), ts));
        }

        for (int i = 0; i < 20; i++) {
            long ts = System.currentTimeMillis();
            assert ts == ULID.newULID(Bytes.getBytes(i), ts).getTimestamp();
        }
    }

随机

CRC64

When using murmurHash3 128-bits, the x86 and x64 versions do not produce the same values. 故采用CRC64.

CRC64碰撞率低(详见),自测2亿数据量没有碰撞,就算有碰撞那概率比写bug的概率还低~

@Test
public void codec() {
    for (int i = 0; i < 10; i++) {
        long ts = System.nanoTime();
        assert App.orderedUUID(ts, i).equals(App.orderedUUID(ts, i));
    }

    EntityDatabase db = EntityDatabase.DEFAULT;
    db.createMapping(CollisionEntity.class);
    db.dropMapping(CollisionEntity.class);
    db.createMapping(CollisionEntity.class);
    int c = 200000000;
    AtomicInteger collision = new AtomicInteger();
    invoke("codec", i -> {
        long id = CrcModel.CRC64_ECMA_182.getCRC((UUID.randomUUID().toString() + i).getBytes(StandardCharsets.UTF_8)).getCrc();
        CollisionEntity po = db.findById(CollisionEntity.class, id);
        if (po != null) {
            log.warn("collision: {}", collision.incrementAndGet());
            return;
        }
        po = new CollisionEntity();
        po.setId(id);
        db.save(po, true);
    }, c);
    assert db.count(new EntityQueryLambda<>(CollisionEntity.class)) == c;
}