Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Singleton state and only forward lapse support #5

Open
JensRantil opened this issue Oct 19, 2014 · 0 comments
Open

Singleton state and only forward lapse support #5

JensRantil opened this issue Oct 19, 2014 · 0 comments

Comments

@JensRantil
Copy link

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:

  • 1: timestamp_1, data_1
  • 2: timestamp_2, data_2
  • ...
  • n: timestamp_n, data_n

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:

  • UUID1(timestamp_1): data_1
  • UUID1(timestamp_2): data_2
  • ...
  • UUID1(timestamp_n): data_n

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:

  • Make a non-static implementation of UUIDGen, call it ReusableUUIDGen or something, that supports reuse with non-singleton state.
  • Make the current UUIDGen simply hold a singleton ReusableUUIDGen instance and proxy calls to it.
  • Patch UUIDGen#createTime(...) the if statement in the while loop to properly support decreasing input to the method.
  • Document the fact that UUIDGen#createTime(...) only works for consecutive larger input.

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

Workaround:

  • For the descending issue, the caller could make a UUIDGen#createTime(0) call before calling the static method with a descending value.
  • For the issue of global state, all input currently need to be strictly monotonically increasing.

Related:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant