Overview
The Timestamp Service exposes an API that allows for clients to request fresh timestamps, which are required by the AtlasDB transaction protocol. These timestamps are logical timestamps (that is, they have no relationship to actual wall-clock time), and are returned as signed 64-bit integers.
Guarantees
We guarantee that a request for a fresh timestamp will return a strictly greater timestamp than any other timestamp already returned by an earlier request. In particular, this does not mean that the timestamps clients see will necessarily be monotonically increasing. The following sequence of events is allowed:
Node A is the Leader
Node A receives request for timestamp
Node A enters bad GC cycle / JVM goes to sleep etc.
Node B becomes the Leader
Node B receives request for timestamp
Node B hands out timestamp X+1 and its client receives it
Node A becomes functional again
Node A hands out timestamp X and its client receives it
However, we guarantee the following sequence of events will not happen:
Node A is the Leader
Node A receives request for timestamp
Node A hands out timestamp X+1 and its client receives it
Node B becomes the Leader
Node B receives request for timestamp
Node B hands out timestamp X and its client receives it
Furthermore, there are also no guarantees that the timestamps issued will be consecutive.
We guarantee the above ordering across system restarts as well.
Contiguous Blocks
Users are allowed to make requests for contiguous blocks of timestamps using the getFreshTimestamps
endpoint.
This may be useful if one knows it is the only client and/or wishes to have bespoke complex concurrency semantics.
The endpoint will return a contiguous block of timestamps; this is indicated by a lower and upper bound (inclusive on both ends). We guarantee that the range returned will consist of at least 1 timestamp, and will have at most as many timestamps as the number requested. However, we do not guarantee that the size of the timestamp range will be equal to the number of timestamps requested for; the onus to check this is on the client.
Caching
To guarantee that timestamps still increase across system restarts, we need to persist some kind of a record of what timestamps we’ve issued to stable storage. However, doing this on each timestamp request is unperformant, as we would need a database operation, and in clustered mode we would also need to achieve distributed consensus.
Thus, instead of updating this record on every timestamp, the Timestamp Service will “reserve” a large number of timestamps (currently 1,000,000) and update the bound to be the end of that range. When clients talk to the Timestamp Service, it will issue timestamps from the range it knows it has, requesting more if necessary. We thus only have one “persist” action every million timestamps. This can lead to there being gaps in timestamps when servers are restarted and/or there is a leadership change in clustered mode, but that’s allowed by our guarantees.