Regarding the uuid gem
If you're using the uuid gem you don't have to worry about uniqueness, as this has been taken care of for you. However, uuid will generate long, 128-bit unique IDs. So, if you want something that's shorter, you might not want to use it.
A simpler way, if your needs are simple
If you want, say, 8-digit unique codes which are also random, you can see an implementation of such a system in my cortex project under the new_unique_code
method.
What this does is generate an 8-digit alpha-numeric code to represent a resource in the app. After generating a given code I try to do a .find_by_code
, and if that returns nil
I know that it's NOT already in use.
In my particular case, 8-digit alpha numeric codes give me a keyspace of some many millions of possible codes (I forget how many). Based on the use case of my app, the chances of a code collision (the percentage of used codes vs. available codes) are small enough to risk possibly needing to generate a new code more than once for a given resource.
The result of this is that needing to generate a new code more than once for a given resource is extremely rare, and as such, takes up almost no additional time.
What about multiple app servers/threads in the app?
One limitation of my solution is that if you have multiple app servers, but a single DB server, it's possible to have two independent app servers generate the same code before either of them creates the new resource record in the centralized DB. This creates a situation where it's possible to have code collisions and all but the first record saved to the DB will be marked invalid (due to a uniqueness constraint on the code column). This particular app only runs (and will probably only ever run) on a single app server instance. This is a known tradeoff that I'm aware of, so I can risk it.
But, if I wanted to solve this problem, I would limit each app server's range of random codes such that they could never accidentally overlap. For example, let's say I'm generating random codes that come out as 8-digit numeric codes between the values 00000000-99999999. If I had, say, three app servers running this app, I would simply limit server #1 to generating codes between 00000000-33333333, server #2 to 33333334-66666666, and server #3 to 66666667-99999999. This way they would be guaranteed never to overlap codes, and you could still generate unique, random keys all day long.
How exactly you would limit a given server to a given range is a bit off topic, but some of the available options are:
- Set a config setting within each app server manually. This is manual (and therefore brittle), but if you have a stable number of app servers that won't be changing, this is probably fine.
- Get the app servers to talk to one another and negotiate what their random number ranges should be.
- Give up, realize that this is a complex problem that has been solved by very smart people, that you don't need to recreate the wheel, and just use UUID.
- Consider using a centralized unique ID generator that runs as a network service, such as Twitter Snowflake