Synchronizing a single entity (the World Boss) across multiple server shards is one of the hardest problems in distributed systems. It is a classic "Global State Contention" problem.
If 10,000 players on Shard A and 10,000 on Shard B both hit the boss at the same millisecond, you cannot simply use a standard Lock() because the latency of locking a global resource 20,000 times per second would freeze the game.
To solve this, the DSL implements a pattern called Authoritative Delta-Synchronization with Buffered Aggregation.
1. The Concept: From "State" to "Deltas"
Instead of syncing the Absolute State (Boss.HP = 100), the shards sync Deltas (Boss.HP -= 50).
The system uses a Three-Layer Architecture:
- Local Shard (The Buffer): Collects damage locally.
- Global Authority (The Truth): The only place where the "real" HP lives.
- Sync Loop (The Heartbeat): Periodically pushes aggregated totals and pulls the current truth.
2. The DSL Implementation: The "Boss-Sync" Workflow
# =================================================================================
# SCENARIO: Distributed World Boss Synchronization
# STRATEGY: Local Aggregation -> Global Delta Update -> Broadcast Sync
# =================================================================================
# --- GLOBAL STATE (Stored in a High-Speed Distributed Cache like Redis) ---
$global_boss_state = {
"hp": 1000000000,
"status": "alive",
"version": 0 # Sequence number to prevent out-of-order updates
}
# --- MODULE: SHARD-LEVEL LOGIC (Runs on every Server Shard) ---
Module ShardBossController {
# Local Buffer: Collects all damage from players on THIS shard
# This prevents 10,000 network calls; we only make ONE call per tick.
$local_damage_buffer = 0
# 1. The Damage Collector (Event-Driven)
# Triggered every time a player hits the boss on this shard
ON (Player.AttackBoss) {
$local_damage_buffer += {damage_amount}
}
# 2. The Sync Heartbeat (The Tick)
# Every 100ms, the shard pushes its total damage to the Global Authority
Tick [100ms] {
if ($local_damage_buffer > 0) {
# Push a DELTA, not a value
Call GlobalAuthority.ApplyDamage {
delta: $local_damage_buffer,
shard_id: $my_id
}
# Reset local buffer after pushing
$local_damage_buffer = 0
}
# Pull the latest Global State to update the local visual representation
Call GlobalAuthority.GetState -> $local_boss_view
}
}
# --- MODULE: GLOBAL AUTHORITY (The Single Source of Truth) ---
Module GlobalAuthority {
# Use an Atomic operation (like Redis INCRBY) to avoid locking the whole server
ApplyDamage /execute {
# ATOMIC OPERATION: Subtract delta from global HP
# This is a "lock-less" write at the hardware level
GlobalState.HP -= {delta}
GlobalState.Version += 1
# Check for Death
if (GlobalState.HP <= 0) {
$global_boss_state.status = "defeated"
Saga.TriggerVictorySequence()
}
}
GetState /return {
return $global_boss_state
}
}
3. How this avoids the "Bottleneck"
A. Avoiding the "Lock Storm" (Aggregation)
If we didn't have the local_damage_buffer, 20,000 players hitting the boss would create 20,000 requests per second to the Global Authority.
By using a 100ms Tick, we reduce the traffic to exactly one request per shard per 100ms.
- If you have 50 shards, that's only 500 requests per second—a load any modern cache (Redis/Memcached) can handle with sub-millisecond latency.
B. The "Absolute vs. Delta" Problem
If Shard A says "Boss HP is now 90" and Shard B says "Boss HP is now 85", they conflict.
By saying "Shard A dealt 10 damage" and "Shard B dealt 15 damage", the Global Authority simply performs a subtraction: 100 - 10 - 15 = 75. Deltas are commutative, meaning the order in which they arrive doesn't change the final result.
C. Solving the "Visual Lag" (Optimistic UI)
Players hate seeing the boss's health bar "jump" every 100ms. To solve this, the DSL supports Local Prediction:
- The Local Shard immediately subtracts the damage from the visual health bar on the player's screen.
- When the
GlobalAuthority.GetStatereturns the "Truth" 100ms later, the client smoothly interpolates (blends) the visual bar to the true value.
4. Stress-Testing the Edge Cases
What if a Shard crashes while holding a buffer of 1 million damage?
- Because the
ApplyDamagecall is part of the DSL's event log (Event Sourcing), the system can see that Shard A failed to "check in" for its heartbeat. - The Saga can then decide: "Discard that damage" (harsh) or "Apply the last known buffer from the log" (fair).
What if the Global Authority becomes slow (Latency Spike)?
- The shards simply continue to accumulate damage in their
local_damage_buffer. - The game doesn't stop; the "Truth" just updates less frequently. Once the authority recovers, a massive "catch-up" delta is pushed, and the boss's health drops instantly to the correct value.
Summary of the Distributed Sync Strategy
| Component | Responsibility | Scaling Method |
|---|---|---|
| Local Shard | Collection & Prediction | Buffering (Reducing request volume) |
| Global Authority | Final Truth | Atomic Operations (Avoiding mutex locks) |
| Sync Loop | Consistency | Heartbeat/Tick (Fixed-interval updates) |
| Client View | User Experience | Interpolation (Hiding the network lag) |