Skip to content
gqlxj1987's Blog
Go back

ID发生器

Edit page

原repo

.
├── LICENSE
├── README.md
├── assembly.xml
├── brief.txt
├── deploy-maven.sh
├── make-release.sh
├── pom.xml
├── todo
│   ├── todo.txt
│   └──\210\206�\203�\217�\217\221�\217��\231�设计�\210�\203��\210\206�\211_�\216\211�\215\216.doc
├── vesta-client
│   ├── pom.xml
│   └── src
├── vesta-doc
│   ├── API�\226\207档.md
│   ├── REST�\217\221�\203模�\217使�\224��\220\221导.md
│   ├──\213�\215.pptx
│   ├──\236��\236\204设计.md
│   ├──\200��\203��\216\213�\213�\212��\221\212.md
│   ├──\214�\205��\217\221�\203模�\217使�\224��\220\221导.md
│   └── 中�\203�\234\215�\212��\231��\217\221�\203模�\217使�\224��\220\221导.md
├── vesta-intf
│   ├── pom.xml
│   └── src
├── vesta-rest
│   ├── assembly.xml
│   ├── pom.xml
│   └── src
├── vesta-rest-netty
│   ├── assembly.xml
│   ├── pom.xml
│   └── src
├── vesta-sample
│   ├── pom.xml
│   ├── vesta-sample-client
│   └── vesta-sample-embed
├── vesta-server
│   ├── assembly.xml
│   ├── pom.xml
│   └── src
├── vesta-service
│   ├── db
│   ├── pom.xml
│   └── src
└── vesta-theme
    └──\210\221�\232\204微信QR.jpeg

相关的项目结构如上所示。

入口模块为vesta-rest部分,还是vesta-rest-netty部分?

public void run() throws Exception {
        // Configure the server.
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.option(ChannelOption.SO_BACKLOG, 1024);
        b.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .childHandler(new VestaRestNettyServerInitializer());

        Channel ch = b.bind(new InetSocketAddress("0.0.0.0",port)).sync().channel();

        if (log.isDebugEnabled())
            log.debug("VestaRestNettyServer is started.");

        ch.closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

使用NioEventLoopGroup

核心的代码都在vesta-service中?

产生ID部分的代码

public long genId() {
    Id id = new Id();

    id.setMachine(machineId);
    id.setGenMethod(genMethod);
    id.setType(idType.value());
    id.setVersion(version);

    populateId(id);

    long ret = idConverter.convert(id, this.idMeta);

    // Use trace because it cause low performance
    if (log.isTraceEnabled())
        log.trace(String.format("Id: %s => %d", id, ret));

    return ret;
}

protected void populateId(Id id) {
    idPopulator.populateId(timer, id, idMeta);
}

根据类型,分为几种产生ID的方式

public void initPopulator() {
    if (idPopulator != null){
        log.info("The " + idPopulator.getClass().getCanonicalName() + " is used.");
    } else if (CommonUtils.isPropKeyOn(SYNC_LOCK_IMPL_KEY)) {
        log.info("The SyncIdPopulator is used.");
        idPopulator = new SyncIdPopulator();
    } else if (CommonUtils.isPropKeyOn(ATOMIC_IMPL_KEY)) {
        log.info("The AtomicIdPopulator is used.");
        idPopulator = new AtomicIdPopulator();
    } else {
        log.info("The default LockIdPopulator is used.");
        idPopulator = new LockIdPopulator();
    }
}

基本的Id分布为

protected long doConvert(Id id, IdMeta idMeta) {
    long ret = 0;

    ret |= id.getMachine();

    ret |= id.getSeq() << idMeta.getSeqBitsStartPos();

    ret |= id.getTime() << idMeta.getTimeBitsStartPos();

    ret |= id.getGenMethod() << idMeta.getGenMethodBitsStartPos();

    ret |= id.getType() << idMeta.getTypeBitsStartPos();

    ret |= id.getVersion() << idMeta.getVersionBitsStartPos();

    return ret;
}

其他可变部分的产生逻辑

public void populateId(Timer timer, Id id, IdMeta idMeta) {
    long timestamp = timer.genTime();
    timer.validateTimestamp(lastTimestamp, timestamp);

    if (timestamp == lastTimestamp) {
        sequence++;
        sequence &= idMeta.getSeqBitsMask();
        if (sequence == 0) {
            timestamp = timer.tillNextTimeUnit(lastTimestamp);
        }
    } else {
        lastTimestamp = timestamp;
        sequence = 0;
    }

    id.setSeq(sequence);
    id.setTime(timestamp);
}

采用sequence以及timestamp部分来产生

但atomicId有所不同

public void populateId(Timer timer, Id id, IdMeta idMeta) {
    Variant varOld, varNew;
    long timestamp, sequence;

    while (true) {

        // Save the old variant
        varOld = variant.get();

        // populate the current variant
        timestamp = timer.genTime();
        timer.validateTimestamp(varOld.lastTimestamp, timestamp);

        sequence = varOld.sequence;

        if (timestamp == varOld.lastTimestamp) {
            sequence++;
            sequence &= idMeta.getSeqBitsMask();
            if (sequence == 0) {
                timestamp = timer.tillNextTimeUnit(varOld.lastTimestamp);
            }
        } else {
            sequence = 0;
        }

        // Assign the current variant by the atomic tools
        varNew = new Variant();
        varNew.sequence = sequence;
        varNew.lastTimestamp = timestamp;

        if (variant.compareAndSet(varOld, varNew)) {
            id.setSeq(sequence);
            id.setTime(timestamp);

            break;
        }

    }
}

通过variant的方式?


Edit page
Share this post on:

Previous Post
Pointers in C
Next Post
独立