java – 9位全天唯一身份证
作者:互联网
有一个令人费解的要求.
基本上我需要使用这些标准创建唯一ID
> 9位数字,当天唯一(如果第二天再次显示该号码,则表示没问题)
>实时生成;仅限java(表示没有从数据库生成序列号 – 实际上根本没有数据库访问)
>生成的数字用于填充requestID,每天将生成大约1.000.000 id.
>不应使用UUID或UID(超过9位数)
这是我的考虑:
>使用序列号听起来不错,但是在JVM重启的情况下,
requestId可能会重新生成.
>使用时间HHmmssSSS(小时分钟秒毫秒)有2个问题:
a. System Hour might be changed by server admin.
b. Can cause issue
if 2 requests being asked on same milliseconds.
任何的想法?
解决方法:
处理1,000,000个ID的九位数给了我们三位数(我们需要其他六位用于ID的0-999999).
我假设你有一个多服务器设置.为每个服务器分配一个三位数的服务器ID,然后您可以在每个服务器中分配唯一的ID值,而不必担心它们之间的重叠.它可以只是内存中不断增加的值,除了在JVM重启之后,我们需要将最近分配的值回显到磁盘(好吧,到你想要存储它的任何地方 – 本地磁盘,内存缓存等等).
为了确保您不会在每个请求上达到文件/任何I / O的开销,您可以在块中分配ID,将块的端点回送到存储.
所以它最终成为:
>为每个服务器提供一个ID
>在服务器上存储存储当天最后分配的值(例如文件)
>让ID分配器在块中工作(一次10个ID,100,无论如何)
>分配块:
>读取文件,写回块数增加的数字
>使用块中的ID
> ID将是,例如12000000027,用于服务器#12分配的第28个ID
>当天变化时(例如午夜),扔掉当前的块并为新的一天分配一个新块
在伪代码中:
class IDAllocator {
Storage storage;
int nextId;
int idCount;
int blockSize;
long lastIdTime;
/**
* Creates an IDAllocator with the given server ID, backing storage,
* and block size.
*
* @param serverId the ID of the server (e.g., 12)
* @param s the backing storage to use
* @param size the block size to use
* @throws SomeException if something goes wrong
*/
IDAllocator(int serverId, Storage s, int size)
throws SomeException {
// Remember our info
this.serverId = serverId * 1000000; // Add a million to make life easy
this.storage = s;
this.nextId = 0;
this.idCount = 0;
this.blockSize = bs;
this.lastIdTime = this.getDayMilliseconds();
// Get the first block. If you like and depending on
// what container this code is running in, you could
// spin this out to a separate thread.
this.getBlock();
}
public synchronized int getNextId()
throws SomeException {
int id;
// If we're out of IDs, or if the day has changed, get a new block
if (idCount == 0 || this.lastIdTime < this.getDayMilliseconds()) {
this.getBlock();
}
// Alloc from the block
id = this.nextId;
--this.idCount;
++this.nextId;
// If you wanted (and depending on what container this
// code is running in), you could proactively retrieve
// the next block here if you were getting low...
// Return the ID
return id + this.serverId;
}
protected long getDayMilliseconds() {
return System.currentTimeMillis() % 86400000;
}
protected void getBlock()
throws SomeException {
int id;
synchronized (this) {
synchronized (this.storage.syncRoot()) {
id = this.storage.readIntFromStorage();
this.storage.writeIntToStroage(id + blocksize);
}
this.nextId = id;
this.idCount = blocksize;
}
}
}
…但是再次,那是伪代码,你可能想要在那里抛出一些主动的东西,这样你就不会在需要时阻止I / O等待ID.
假设您已经拥有某种应用程序范围的单例,并且IDAllocator实例只是该单个实例中的数据成员,则编写上述内容.如果没有,你可以通过赋予它经典的getInstance方法并让它从环境中读取它的配置而不是将它作为构造函数的参数接收,来轻松地使上面的单例成为单例.
标签:java,uniqueidentifier 来源: https://codeday.me/bug/20190725/1538062.html