stephenc / eaio-uuid

Fork of eaio-uuid
http://stephenc.github.com/eaio-uuid/
Other
30 stars 26 forks source link

Singleton state and only forward lapse support #5

Open JensRantil opened 10 years ago

JensRantil commented 10 years ago

First off, eaio-uuid could possibly be the best Java UUID library out there. That said, I found a couple of somewhat related issues with it for my usecase:

Background: I have bunch of event streams that I need to migrate from one database to another. Each stream consists of events with auto increment IDs:

Since the new storage solution is more a distributed one I intend to migrate the auto increment IDs to UUIDs. The end goal will be:

To be able to generate these UUIDs I had a look at UUIDGen#createTime(...) which at first looked like a perfect fit. However;

Problem: The UUIDGen#createTime(...) implementation only works for correctly for ascending consecutive input of currentTimeMillis. As soon as a descending currentTimeMillis is put in, the next time generated will be increased by 100 nanoseconds. That is a bug.

In my case this means that I need to sort all my events globally by timestamp to correctly generate UUIDs of type 1. Since my data is too big for a single instance to handle, this is impossible. Restarting the JVM for every stream :-) is neither an option.

While UUIDGen#createTime(...) is thread-safe per se (it uses AtomicLong for synchronization), a related problem is that of multiple threads calling UUIDGen#createTime(...). Since they generally will have a different notion of time (especially in my case where time is not Thread.currentTimeMillis()) the implementation is inherently broken. This boils down to singleton state;

If it wasn't for the fact that lastTime and UUIDGen#createTime(...) were static, this would not be a problem. In that case, I'd be able to instantiate one UUIDGen per migration thread, sorting my stream individually and then generating UUID using strictly monotonical input to UUIDGen#createTime(...).

Proposed solution:

The above solution has the benefit of being a backward compatible implementation while still enabling reusing the UUIDGen.

Workaround:

Related: