“ I would implement a thread-safe sliding window counter using a concurrent
map keyed by grouping attributes (like IP or IP+Agent). Each key maps to a
fixed-size ring buffer of time buckets, allowing O(1) updates and bounded
memory. Thread safety is ensured using per-key locking or atomic
operations.”
✅ Final Takeaway
👉 Use:
● Concurrent mapfor grouping
● Ring buffer (time buckets)for window
● Per-key lockingfor scalability
Design a file system:
Functional requirements:
● A llow users to create, delete, read, and write files and directories at any location, with
recursive deletion of directories removing all contents.
● Support a hierarchical directory structure that allows arbitrary nesting depth, where every
node except the root has exactly one parent, forming a tree structure.
● Enable path-based navigation to resolve nodes by absolute path, with all operations
accepting absolute paths and a PathResolver translating string paths into node
references by traversing the directory tree.
● Implement per-user file permissions for each node, including READ, WRITE, and
EXECUTE, rejecting operations if the current user lacks the required permission, while
owners implicitly have all permissions.
● Allow users to search for files and directories by name pattern, starting from a directory
and searching recursively through all descendants via depth-first traversal.
Non functional requirements:
or the non-functional requirements section of your file system design, you should cover the
F
following topics:
● Thread Safety: Address how the system will ensure safe access when multiple threads
are reading and writing concurrently. Specifically, mention the use of a ReadWriteLock to
allow multiple concurrent readers while ensuring exclusive access for writers.
● Extensibility: Discuss how the design will allow for the addition of new types or behaviors
without modifying existing code. For example, new node types like SymbolicLink can be
added by extending the FileSystemNode class, maintaining flexibility in your system.
● Correctness: Explain how the system will enforce invariants and ensure that no invalid
state can be reached through the public API. This includes rejecting invalid operations to
prevent silent corruption of the system's state.
● These non-functional requirements are crucial for ensuring that your file system is
robust, maintainable, and reliable in a production environment.
Vector Clocks
Where are the vector clocks stored in a distributed key value store?
ector clocks aren’t stored in some separate global service—they liveright next to the data
V
they describe.
🧠 Core idea
vector clock is metadata attached to a key (or aversion of a value)that tracks causality
A
across replicas.
👉 So the real answer is:
ector clocks are stored alongside each value (or each version of a value)
V
inside the distributed key-value store.
📦 Where exactly are they stored?
1. 🔑 With each key–value entry
For a given key:
{
" key": "user:123",
"value": { ... },
"vector_clock": {
"nodeA": 3,
"nodeB": 5,
"nodeC": 2
}
}
S
● tored in the same storage layer (disk / memory)
● Retrieved together with the value
2. 🔁 Per version (in multi-version systems)
In systems that allow conflicts (like Dynamo-style systems):
{
"key": "user:123",
"versions": [
{
"value": "...",
"vector_clock": { "A": 2, "B": 1 }
},
{
"value": "...",
"vector_clock": { "A": 1, "B": 2 }
}
]
}
👉 Each conflicting version has itsown vector clock
🏗️ Where physically (architecture-wise)?
On each replica node
● Each node stores:
○ value
○ vector clock
● No centralized clock storage
👉 This is crucial fordecentralization
🌐 How it works in distributed systems
Used in systems like:
A
● mazon Dynamo
● Riak
● Apache Cassandra (uses a variant / simplified mechanisms)
Flow:
. C
1 lient writes → node updates vector clock
2. Replication happens → vector clocks travel with data
3. On conflict:
○ Compare vector clocks
○ Detect:
■ causality
■ concurrent updates
⚠️ Important nuance (interview gold)
👉 Vector clocks arenot stored globally per nodeor cluster
They are:
● ❌ Not centralized
● ❌ Not shared independently
✅ Always tied to aspecific key/version
●
🧠 Why this design?
1. 📍 Local reasoning
Each key can independently:
● detect conflicts
● resolve causality
2. ⚡ Scalability
N
● o global coordination needed
● Works in partitioned systems
3. 🔄 Conflict resolution
● Enables:
○ last-write-wins alternatives
○ application-level merge
🔁 Alternative mental model
Think of vector clocks as:
👉 “Version history embedded inside the data”
ot:
N
👉 “A system-wide clock service”
✅ Final takeaway
ector clocks are stored asper-key (or per-version)metadata alongside the
V
value on each replica node, enabling decentralizedconflict detection and
resolution.
If you want, I can also walk through:
H
● ow vector clocks detect conflicts step-by-step
● Why they grow in size and how systems mitigate that (very common follow-up)
● Or compare with Lamport timestamps (another interview favorite)
ector clocks are great for causality—but left unchecked, theygrow with every participating
V
node, which isn’t sustainable in real systems. Soproduction systems use a mix ofpruning,
summarization, and alternative clocksto keep thembounded.
🧠 Why vector clocks grow
A vector clock has one entry per node that has ever updated the key:
{ "A": 5, "B": 3, "C": 7, "D": 2, ... }
In large clusters or long-lived keys:
N
● odes join/leave
● Many replicas touch the same key
👉 The vector can becomelarge and expensive to store/compare
🛠️ How systems control growth
1) ✂️ Truncation (limit the number of entries)
Keep only thetop K entries(usually the most recentor most relevant), drop the rest.
How it’s done:
S
● ort entries by recency (or last update time)
● Keep, say,K = 10–20
● Remove older/least-relevant nodes
Trade-off:
● 👍 Keeps metadata small
👎 May lose some causality → can createfalse conflicts
●
Used in systems like Amazon Dynamo and Riak.
2) 🧹 Garbage collection after convergence
Once replicasconvergeand conflicts are resolved:
O
● lder versions (and their clocks) are discarded
● The surviving version carries areduced clock
Idea:
● You don’t need history once it’s no longer relevant
3) 📉 Version collapsing / summarization
If multiple versions become causally ordered, collapse them into one:
{A:1} → {A:2} → {A:3}
👉 Keep only{A:3}
Benefit:
R
● emoves intermediate states
● Shrinks vector size naturally over time
4) 🆔 Logical node identifiers (stable, bounded set)
Instead of tracking every transient process:
U
● se afixed set of replica IDs(e.g., per shard/partition)
● Avoids unbounded growth from ephemeral nodes
5) 🔄 Dotted Version Vectors (DVV)
An improvement over classic vector clocks:
● Track acompact summary+ asingle “dot”(the latestevent)
Why it helps:
A
● voids storing full history per update
● Reduces ambiguity after truncation
Used as an evolution of vector clocks in systems like Riak.
6) ⚖️ Switching to simpler clocks (when acceptable)
Some systems trade precision for simplicity:
🕒 Last-Write-Wins (LWW)
U
● se a timestamp instead of a vector
● Example: Apache Cassandra
Trade-off:
● 👍 Constant size
● 👎 Loses causality → can overwrite concurrent updates
7) 📦 Bounded contexts (per-partition clocks)
M
● aintain clocksper shard/partition, not cluster-wide
● Limits the number of entries per clock
⚠️ The core trade-off
Strategy Accuracy Size Risk
Full vector clock ✅ High ❌ Large
None
Truncated vector ⚠️ Medium ✅ False conflicts
Bounded
LWW timestamp ❌ Low ✅ Tiny
Lost updates
👉 Systems choose based onconsistency vs efficiency
🧠 Interview-ready answer
“ Systems prevent vector clocks from growing indefinitely by truncating entries to a
fixed size, garbage-collecting old versions after convergence, and sometimes using
alternatives like dotted version vectors or last-write-wins timestamps. These
techniques trade off strict causality for bounded metadata size.”
✅ Final takeaway
V
● ector clocks naturally grow with system size
● Real systemsbound them deliberately
● The key trade-off is:
perfect causality vs practical scalability
If you want, I can walk you through:
A
● concrete example of truncation causing a false conflict (very commonly asked)
● Or DVV vs vector clock comparison with diagrams
Rector pattern
Can you show me reactor pattern in action?
bsolutely — let’s walk through the Reactor pattern like a live simulation so you canseewhat
A
the event loop is doing internally.
We’ll simulate:
🧠
A chat server handling multiple clients
with ONE thread
using:
n
● on-blocking sockets
● event loop
● epoll/select style behavior
⚙️ Traditional Blocking Server
Normally:
lient A → Thread A
C
Client B → Thread B
Client C → Thread C
Each thread waits here:
data = [Link]()
Problem:
thread blocked most of the time
●
● huge memory/context-switch cost
🔥 Reactor Approach
Instead:
Event Loop Thread
↓
Wait for ALL socket events
↓
React only when ready
One thread handles MANY clients.
🧩 Let’s Simulate It
Suppose:
3
● clients connected
● all sockets are non-blocking
Step 1️⃣ Register Sockets
Event loop tells OS:
"Notify me when any socket becomes readable"
Internally:
[Link](socketA)
e
[Link](socketB)
[Link](socketC)
Step 2️⃣ Event Loop Sleeps Efficiently
events = [Link]()
hread is now:
T
✅ NOT busy looping
✅ NOT polling manually
✅ sleeping inside kernel efficiently
Step 3️⃣ Client B Sends Message
Suppose:
Client B → "hello"
Kernel notices:
socketB is readable
Kernel wakes event loop.
Step 4️⃣ Event Loop Receives Event
events = [socketB]
Step 5️⃣ Reactor Dispatches Handler
handle_read(socketB)
Handler executes:
data = [Link]()
ince socket already ready:
S
✅ returns immediately
❌ no blocking
Step 6️⃣ Event Loop Continues
After processing:
[Link]()
goes back to sleep.
🧠 Key Insight
The thread blocks:
once centrally
instead of:
blocking per socket
This is the core breakthrough.
🔥 Visual Timeline
Traditional Model
hread A waiting...
T
Thread B waiting...
Thread C waiting...
Huge waste.
Reactor Model
One thread:
sleep until ANY event happens
Massively scalable.
⚡ Real Event Loop Pseudocode
This is essentially Reactor:
while True:
ready_sockets = [Link]()
for socket in ready_sockets:
if socket == server_socket:
accept_new_connection()
else:
handle_client(socket)
That’s it.
🧩 Real Working Example
Here’s a minimal real server:
import socket
import selectors
selector = [Link]()
--------------------------------
#
# Accept new connections
# --------------------------------
def accept(server_socket):
client_socket, addr = server_socket.accept()
print("Connected:", addr)
client_socket.setblocking(False)
[Link](
client_socket,
selectors.EVENT_READ,
read_client
)
--------------------------------
#
# Handle client messages
# --------------------------------
def read_client(client_socket):
data = client_socket.recv(1024)
if data:
print("Received:", [Link]())
client_socket.send(b"ACK\n")
else:
print("Disconnected")
[Link](client_socket)
s
client_socket.close()
--------------------------------
#
# Setup server
# --------------------------------
server = [Link]()
[Link](("localhost", 9999))
[Link]()
[Link](False)
[Link](
server,
selectors.EVENT_READ,
accept
)
print("Reactor server started...")
--------------------------------
#
# THE EVENT LOOP
# --------------------------------
while True:
events = [Link]()
for key, mask in events:
callback = [Link]
callback([Link])
🔥 What Makes This Reactor?
1️⃣ Non-blocking sockets
setblocking(False)
2️⃣ Central event loop
[Link]()
3️⃣ Event dispatching
callback([Link])
⚡ What Happens Internally
Suppose:
1
● 0,000 clients connected
● only 5 active
Traditional:
10,000 threads
Reactor:
thread
1
processes only 5 active sockets
Huge efficiency gain.
⚠️ Important Rule
Handlers must stay FAST.
Bad:
[Link](5)
inside handler.
Why?
Because:
entire event loop freezes
affecting ALL clients.
🔥 So What About CPU-heavy Tasks?
Modern reactors delegate heavy work:
Event Loop
↓
Worker Thread Pool
Very common hybrid architecture.
🧠 Real-world Systems
Nginx
e
● poll
● worker event loops
[Link]
● single-threaded event loop
Netty
● Java reactor framework
🧠 Final Mental Model
Reactor pattern is basically:
"Don’t waste threads waiting."
Instead:
. Register interest in events
1
2. Sleep efficiently
3. React only when OS says work is ready
That’s the entire idea.
Understanding interfaces
[Link]
Pdf in downloads pers mac
Hashmap collision handling
[Link]
Pdf in downloads pers mac