Monday, February 20, 2017

Java Sequence Generator which simulates Oracle DB Sequence Generator

There is a requirement in my recent project, to generate 11 digit long sequence number without any database. Interesting, we are so used to rely on database to generate sequence number. In Java programming world, there isn’t a convenient library to generate sequence number!?

Solution 1: UUID.randomUUID().
UUID is alpha numeric and UUID size is way bigger than 11 digits.

Solution 2: System.currentTimeMillis().
[1] System.currentTimeMillis() generates 13 digits.
[2] If we substring the left most 11 characters, we lose the accuracy.
[3] The sequence is not continuous.
[4] In the very fast machine and fast retrieval, it is possible to obtain repeated value.

Solution 3: System.currentTimeMillis() as init value and +1 subsequently.
In the high volume retrieval, +1 may outrun the speed of time, e.g. 20000 transactions per second. When program restart, the newly System.currentTimeMillis() init value might have been used previously.

Solution 4: Plain and basic +1 counter and save the value in local file. This ensures the uniqueness of sequence number and sequence number will resume when restart the program.
Issue: Too much file write will slow down the program.

Solution 5: Plain and basic +1 counter with cache, similar to Oracle sequence cache. When cache is used up, renew it and save the new cache value in local file.
Issue: When the program or server crashes, local file is not updated and we don’t know where the last sequence number.

Solution 6: Enhanced version 5. When program is restarted, sequence counter will start from previous cache.
Issue: This behavior is the same as Oracle sequence generator. Un-used sequence number is lost when program is restarted.

Solution 7: Enhanced version 6. With the help of Java ShutdownHock, we’ll save current and new cache value in the file. Local file will be updated when
1)Program is properly shutdown, ShutdownHock will store [Current count, current count].
2)When new cache is created, store [Current count, new cache]

So, when program is restarted, it will read the file and compare,
1)If Current count == current count, resume sequence number = Current count.
2)If Current count < new cache, it means program crashed previously. Sequence number will start from new cache + 1.

So far Solution 7 is quite good. It is clean and light-weight.

Interesting observation is,
1) Many people would think until Solution 4, 5, 6 and got stuck.
2) When 1 person is working alone, it is not easy to get out of blind spot.
3) The best solution indeed is not known or given. The best solution is purified from questioning and brain-storming with a team of good colleagues.