In the following scenario:
在以下场景中:
1 Database 4 Web servers
1数据库4 Web服务器
How do the Web servers generate unique ID's for the database so that they are unique? Yes it's possible to use Auto-increment, but this is too easily crawled/guessed/etc. So auto-increment is currently not an option.
Web服务器如何为数据库生成唯一ID以使它们是唯一的?是的,可以使用自动增量,但这很容易被抓取/猜测/等。因此,自动增量目前不是一种选择。
5 个解决方案
#1
15
Use a UUID (http://www.ietf.org/rfc/rfc4122.txt). Collisions are unlikely, and could be dealt with when they occur by regenerating a new UUID, or they could be prevented by concatenating a unique id for each server (like the mac address): -
使用UUID(http://www.ietf.org/rfc/rfc4122.txt)。冲突不太可能,并且可以通过重新生成新的UUID来处理它们,或者可以通过连接每个服务器的唯一ID(如mac地址)来阻止它们: -
StringBuilder sb = new StringBuilder(UUID.randomUUID());
InetAddress address = InetAddress.getLocalHost();
String uid = sb.append(NetworkInterface.getByInetAddress(address).getHardwareAddress());
#2
3
You can use a UUID:
您可以使用UUID:
import java.util.UUID;
UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());
#3
1
If you are really worried about collisions, you can pre-generate your keys and store them in a database table with a unique index. Then have a periodic job that populates the table during downtime, and removes/archives used keys once in a while.
如果您真的担心冲突,可以预先生成密钥并将它们存储在具有唯一索引的数据库表中。然后有一个定期作业,在停机期间填充表,并偶尔删除/存档使用过的键。
#4
1
What DB system are you using? Does the app know which server is making the request? Are you letting the DB decide the key, or setting it in code?
你使用什么数据库系统?应用程序是否知道哪个服务器正在发出请求?您是让DB决定密钥还是在代码中设置密钥?
It could be as simple as using an auto-increment with a prefix or 2nd field indicating the server that requested the key.
它可以像使用带前缀的自动增量或指示请求密钥的服务器的第二个字段一样简单。
#5
1
I'm not sure why an auto-increment or sequence is unacceptable. You want an internal ID to not be "guessable"? What, it's like this is an account number and you don't want someone to be able to guess a valid account number?
我不确定为什么自动增量或序列是不可接受的。您希望内部ID不是“可猜测的”吗?什么,这是一个帐号,你不希望有人能够猜出一个有效的帐号?
Well, okay, besides UUIDs already mentioned, two obvious possibilities come to mind.
嗯,好吧,除了UUID已经提到过,还有两个明显的可能性。
-
Use a sequence, then generate a random number, and create the account number from a combination of the two using an algorithm such that two different sequences numbers cannot give the same final number. For example, a simple algorithm would be: Take the next sequence number, multiply by 12345678, generate a random number from 0 to 12345678-1, and add the two together.
使用序列,然后生成随机数,并使用算法从两者的组合创建帐号,使得两个不同的序列号不能给出相同的最终数。例如,一个简单的算法是:取下一个序列号,乘以12345678,生成一个从0到12345678-1的随机数,并将两者加在一起。
-
Have a table on the database with one record, which holds the last assigned number. Each time you need a new number, lock this record, use the previous value to generate the next value, and update the record. As long as the numbers always increase, you're guaranteed to not have a duplicate.
在数据库上有一个包含一条记录的表,该记录包含最后分配的编号。每次需要新号码时,请锁定此记录,使用上一个值生成下一个值,然后更新记录。只要数字总是增加,就可以保证不会有重复数字。
If you have some scheme that uses an identifier of the server as part of the identifier, I'd encourage you to not have that identifier simply be a number stored in a configuration file somewhere. I'm working on a system now where someone had the bright idea to give each server a "server id" that is built in to record id's, and the server id is a small integer that is manually assigned. It's not too hard in production where there are only 3 servers. But in development and testing, where new servers are coming up and down all the time and test configuration files are constantly being tossed around, it's a pain to administer. I'd avoid using a server id period, but if you're going to use one, make it automatically assigned by some central server, or derive it from the IP, or something safe.
如果您有一些方案使用服务器的标识符作为标识符的一部分,我建议您不要将该标识符简单地存储在某个配置文件中的数字。我正在开发一个系统,现在有人有一个明智的想法,即为每个服务器提供一个内置于记录id的“服务器ID”,而服务器id是一个手动分配的小整数。在只有3台服务器的生产中,这并不算太难。但是在开发和测试中,新服务器一直处于起伏状态并且测试配置文件不断被抛出,这是一个很难管理的问题。我会避免使用服务器ID周期,但是如果你打算使用一个,请让它由某个*服务器自动分配,或者从IP派生,或安全的东西。
#1
15
Use a UUID (http://www.ietf.org/rfc/rfc4122.txt). Collisions are unlikely, and could be dealt with when they occur by regenerating a new UUID, or they could be prevented by concatenating a unique id for each server (like the mac address): -
使用UUID(http://www.ietf.org/rfc/rfc4122.txt)。冲突不太可能,并且可以通过重新生成新的UUID来处理它们,或者可以通过连接每个服务器的唯一ID(如mac地址)来阻止它们: -
StringBuilder sb = new StringBuilder(UUID.randomUUID());
InetAddress address = InetAddress.getLocalHost();
String uid = sb.append(NetworkInterface.getByInetAddress(address).getHardwareAddress());
#2
3
You can use a UUID:
您可以使用UUID:
import java.util.UUID;
UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());
#3
1
If you are really worried about collisions, you can pre-generate your keys and store them in a database table with a unique index. Then have a periodic job that populates the table during downtime, and removes/archives used keys once in a while.
如果您真的担心冲突,可以预先生成密钥并将它们存储在具有唯一索引的数据库表中。然后有一个定期作业,在停机期间填充表,并偶尔删除/存档使用过的键。
#4
1
What DB system are you using? Does the app know which server is making the request? Are you letting the DB decide the key, or setting it in code?
你使用什么数据库系统?应用程序是否知道哪个服务器正在发出请求?您是让DB决定密钥还是在代码中设置密钥?
It could be as simple as using an auto-increment with a prefix or 2nd field indicating the server that requested the key.
它可以像使用带前缀的自动增量或指示请求密钥的服务器的第二个字段一样简单。
#5
1
I'm not sure why an auto-increment or sequence is unacceptable. You want an internal ID to not be "guessable"? What, it's like this is an account number and you don't want someone to be able to guess a valid account number?
我不确定为什么自动增量或序列是不可接受的。您希望内部ID不是“可猜测的”吗?什么,这是一个帐号,你不希望有人能够猜出一个有效的帐号?
Well, okay, besides UUIDs already mentioned, two obvious possibilities come to mind.
嗯,好吧,除了UUID已经提到过,还有两个明显的可能性。
-
Use a sequence, then generate a random number, and create the account number from a combination of the two using an algorithm such that two different sequences numbers cannot give the same final number. For example, a simple algorithm would be: Take the next sequence number, multiply by 12345678, generate a random number from 0 to 12345678-1, and add the two together.
使用序列,然后生成随机数,并使用算法从两者的组合创建帐号,使得两个不同的序列号不能给出相同的最终数。例如,一个简单的算法是:取下一个序列号,乘以12345678,生成一个从0到12345678-1的随机数,并将两者加在一起。
-
Have a table on the database with one record, which holds the last assigned number. Each time you need a new number, lock this record, use the previous value to generate the next value, and update the record. As long as the numbers always increase, you're guaranteed to not have a duplicate.
在数据库上有一个包含一条记录的表,该记录包含最后分配的编号。每次需要新号码时,请锁定此记录,使用上一个值生成下一个值,然后更新记录。只要数字总是增加,就可以保证不会有重复数字。
If you have some scheme that uses an identifier of the server as part of the identifier, I'd encourage you to not have that identifier simply be a number stored in a configuration file somewhere. I'm working on a system now where someone had the bright idea to give each server a "server id" that is built in to record id's, and the server id is a small integer that is manually assigned. It's not too hard in production where there are only 3 servers. But in development and testing, where new servers are coming up and down all the time and test configuration files are constantly being tossed around, it's a pain to administer. I'd avoid using a server id period, but if you're going to use one, make it automatically assigned by some central server, or derive it from the IP, or something safe.
如果您有一些方案使用服务器的标识符作为标识符的一部分,我建议您不要将该标识符简单地存储在某个配置文件中的数字。我正在开发一个系统,现在有人有一个明智的想法,即为每个服务器提供一个内置于记录id的“服务器ID”,而服务器id是一个手动分配的小整数。在只有3台服务器的生产中,这并不算太难。但是在开发和测试中,新服务器一直处于起伏状态并且测试配置文件不断被抛出,这是一个很难管理的问题。我会避免使用服务器ID周期,但是如果你打算使用一个,请让它由某个*服务器自动分配,或者从IP派生,或安全的东西。