ID生成器

背景:

网络游戏经常需要合服,所以角色ID最好不要重复,这样会降低合服的难度。另外,如果能做到物品id、角色id、npcid这些都不重复,那么更好。于是有人说,那你用UUID吧。但是,如果能根据这个id就能知道它到底是宠物还是角色还是物品,那么更好。

注意:A、B合服后,要用A或者B的serverid。另一个废弃,新开服也不能用废弃的ID。

(自以为这个比xdb的那套方法好。因为没有多余的表来存这个ID)

/**
* ID生成器。 <br />
* TODO: 把type用Integer.reverse这样的方式颠倒之后再存进去。那么当扩展typebits的时候,现在的数据依然可用。
* 
* @author cm
* 
*/
public class IDGenerator {
    private volatile AtomicLong[] nextValue;
    static final int typebits = 3;
    static final int serverbits = 12;
    static final int valuebits = Long.SIZE - 1 - typebits - serverbits;

    private static volatile IDGenerator instance;
    private volatile int serverid = 0;

    public void setServerid(int serverid) {
        this.serverid = serverid;
    }

    public static IDGenerator getInstance() {
        if (instance == null) {
            synchronized (IDGenerator.class) {
                if (instance == null)
                    instance = new IDGenerator();
            }
        }
        return instance;
    }

    public static interface IType {
        /** 类型,如0代表角色,1代表宠物,2代表物品。 */
        int getId();

        /** 当前的最大值。只要底层的存储引擎不是Hash而是采用Btree这样的,那么这个值很容易拿到 */
        long getMaxValue();
    }

    private IDGenerator() {
        final int maxlen = (1 << typebits);
        nextValue = new AtomicLong[maxlen];
    }

    private static long getNextidFromCurrentValue(long value) {
        return ((value & (((1 << valuebits) - 1) << serverbits)) >> serverbits + 1);
    }

    /** server每次启动的时候调一下这个方法 */
    public void register(IType type) {
        nextValue[type.getId()]=new AtomicLong(getNextidFromCurrentValue(type.getMaxValue()));
    }

    public long getNextValue(int type) {
        final long v1 = type << (serverbits + valuebits);
        final long v2 = (nextValue[type].incrementAndGet()) << serverbits;
        return v1 | v2 | this.serverid;
    }
}

其实在register的时候还可以做一点小处理,如果type.getMaxValue<=0,那么从1<<20这个范围内随机生一个数作为初始值。以防止竞争对手根据ID而获知用户数。

我的同事非要把UUID变成String之后做数据库表的主键,而不用long。我很无奈。那么那个TODO就永远TODO下去吧,永远也用不上的代码。

(刚写的,还没测。发现BUG请告诉我)

此博客中的热门博文

在windows下使用llvm+clang

少写代码,多读别人写的代码

tensorflow distributed runtime初窥