Execute a TTL Key-Value Store with Transactions
OpendoorBackend Engineer · Technical ScreenLast updated
This problem tests the implementation of an in-memory key-value store supporting TTL expiration, atomic transactions with rollback capabilities, and logical time-based validation.
Problem Statement
Design a simple in-memory key-value store that supports basic operations, TTL-based expiration, and a single active transaction. You must maintain a logical clock (time) that increments with each operation.
Requirements
SET(key, value, ttl): Sets a key to a value that expires atcurrent_time + ttl.GET(key): Returns the value if the key exists and has not expired; otherwise returnsNULL.DELETE(key): Removes the key.BEGIN(): Starts a transaction. Only one transaction can be active at a time.COMMIT(): Persists all changes made sinceBEGIN().ROLLBACK(): Discards all changes made sinceBEGIN().TICK(): Increments the logical clock by 1.
Transactions are isolated: changes made during a transaction are not visible to GET unless the current scope is within the transaction. If a SET or DELETE is called outside a transaction, it takes effect immediately.
Interface
class KVStore:
def __init__(self):
self.time = 0
def tick(self): ...
def set(self, key, value, ttl): ...
def get(self, key): ...
def delete(self, key): ...
def begin(self): ...
def commit(self): ...
def rollback(self): ...
Constraints
- All keys and values are strings.
- Time is a non-negative integer.
ttlis a positive integer indicating duration from the currenttime.
Example
kv = KVStore()
kv.set("a", "1", 10)
kv.tick()
kv.get("a") # returns "1"
kv.begin()
kv.set("a", "2", 5)
kv.get("a") # returns "2"
kv.rollback()
kv.get("a") # returns "1" (original value persists)
Hints
Hint 1
Use a dictionary to store the current state and a separate 'staging' dictionary to track changes made during a transaction.
Hint 2
Store expiration times as `absolute_time = current_time + ttl` to simplify expiration checks.
Hint 3
During a transaction, a 'read' should check the staging area first; if the key isn't there, fall back to the main storage.
Follow-up questions
- How would you optimize the GET operation if the store contained millions of keys with different TTLs?
- What changes would be required to support nested transactions (e.g., SAVEPOINTs)?
- How would you handle persistence to disk to ensure the store survives a process restart?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.