views:

427

answers:

7

I need to generate unique, incremental, numeric transaction id's for each request I make to a certain XML RPC. These numbers only need to be unique across my domain, but will be generated on multiple machines.

I really don't want to have to keep track of this number in a database and deal with row locking etc on every single transaction. I tried to hack this using a microsecond timestamp, but there were collisions with just a few threads - my application needs to support hundreds of threads.

Any ideas would be appreciated.

Edit: What if each transaction id just has to be larger than the previous request's?

A: 

If you remove 'incremental' from your requirements, you could use a GUID.

I don't see how you can implement incremental across multiple processes without some sort of common data.

David Norman
+3  A: 

If you're going to be using this from hundreds of threads, working on multiple machines, and require an incremental ID, you're going to need some centralized place to store and lock the last generated ID number. This doesn't necessarily have to be in a database, but that would be the most common option. A central server that did nothing but serve IDs could provide the same functionality, but that probably defeats the purpose of distributing this.

If they need to be incremental, any form of timestamp won't be guaranteed unique.

If you don't need them to be incremental, a GUID would work. Potentially doing some type of merge of the timestamp + a hardware ID on each system could give unique identifiers, but the ID number portion would not necessarily be unique.

Could you use a pair of Hardware IDs + incremental timestamps? This would make each specific machine's IDs incremental, but not necessarily be unique across the entire domain.

---- EDIT -----

I don't think using any form of timestamp is going to work for you, for 2 reasons.

First, you'll never be able to guarantee that 2 threads on different machines won't try to schedule at exactly the same time, no matter what resolution of timer you use. At a high enough resolution, it would be unlikely, but not guaranteed.

Second, to make this work, even if you could resolve the collision issue above, you'd have to get every system to have exactly the same clock with microsecond accuracy, which isn't really practical.

Reed Copsey
Good point on the timestamp resolution.
Stewart
+1  A: 

This is a very difficult problem, particularly if you don't want to create a performance bottleneck. You say that the IDs need to be 'incremental' and 'numeric' -- is that a concrete business constraint, or one that exists for some other purpose?

If these aren't necessary you can use UUIDs, which most common platforms have libraries for. They allow you to generate many (millions!) of IDs in very short timespans and be quite comfortable with no collisions. The relevant article on wikipedia claims:

In other words, only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%.

Chris Winters
It is this service's requirement. I made an edit to the question, I may be able to get away with just having larger id's each time (which lends itself to something time-based I reckon).
Stewart
A: 

If you target a Windows platform, did you try Interlocked API ?

devio
A: 

Google for GUID generators for whatever language you are looking for, and then convert that to a number if you really need it to be numeric. It isn't incremental though.

Or have each thread "reserve" a thousand (or million, or billion) transaction IDs and hand them out one at a time, and "reserve" the next bunch when it runs out. Still not really incremental.

CoverosGene
A: 

I'm with the GUID crowd, but if that's not possible, could you consider using db4o or SQL Lite over a heavy-weight database?

Si
GUID is not possible, as it is not incremental. I worry about performance bottlenecks of hundreds of threads each trying to get exclusive UPDATE access to the same field of data.
Stewart
That's why I suggested a light-weight db, personally I'd take db4o(.net) for a test drive. Should be easy to test your performance requirements in an hour or two (assuming you want .net/java).
Si
A: 

If each client can keep track of its own "next id", then you could talk to a sentral server and get a range of id's, perhaps a 1000 at a time. Once a client runs out of id's, it will have to talk to the server again.

This would make your system have a central source of id's, and still avoid having to talk to the database for every id.

Lasse V. Karlsen