Multi-Datacenter Sharding Guide¶
This guide covers deploying Barrel DocDB in a multi-datacenter or multi-region environment using Virtual Databases (VDBs) with zone-aware placement.
Architecture Overview¶
┌──────────────────────────────────────────────────────┐
│ Load Balancer │
└─────────────────────────┬────────────────────────────┘
│
┌─────────────────────────────────────┼─────────────────────────────────────┐
│ │ │
US-EAST Zone EU-WEST Zone ASIA Zone
│ │ │
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ Node 1 │ │ Node 3 │ │ Node 5 │
│ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │
│ │ users_s0 │◄├─────────────────────┤►│ users_s0 │◄├─────────────────────┤►│ users_s1 │ │
│ │ users_s1 │ │ Replication │ │ users_s1 │ │ Replication │ │ users_s2 │ │
│ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │
└───────────────┘ └───────────────┘ └───────────────┘
Zone Configuration¶
Node Configuration¶
Each Barrel node is assigned to a zone via its configuration:
%% sys.config for us-east node
[
{barrel_docdb, [
{zone, <<"us-east">>},
{node_id, <<"node1">>}
]}
].
%% sys.config for eu-west node
[
{barrel_docdb, [
{zone, <<"eu-west">>},
{node_id, <<"node3">>}
]}
].
Environment Variables¶
Alternatively, configure via environment variables:
Docker Configuration¶
# docker-compose.yml
services:
barrel-us-1:
image: barrel/docdb:latest
environment:
BARREL_ZONE: "us-east"
BARREL_NODE_ID: "us-1"
ports:
- "8081:8080"
barrel-eu-1:
image: barrel/docdb:latest
environment:
BARREL_ZONE: "eu-west"
BARREL_NODE_ID: "eu-1"
ports:
- "8082:8080"
Zone Discovery¶
Nodes discover each other and their zones through the discovery system.
Check Node Zone¶
Response:
List Nodes by Zone¶
%% Get current node's zone
Zone = barrel_discovery:get_zone().
%% Get all nodes in a zone
{ok, Nodes} = barrel_discovery:nodes_in_zone(<<"us-east">>).
%% Get all known zones
{ok, Zones} = barrel_discovery:list_zones().
Zone-Aware VDB Creation¶
Basic Multi-Zone Setup¶
Create a VDB with replicas distributed across zones:
curl -X POST "http://localhost:8080/vdb" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{
"name": "users",
"shard_count": 4,
"placement": {
"replica_factor": 2,
"zones": ["us-east", "eu-west"]
}
}'
This creates: - 4 shards distributed across both zones - Each shard replicated to 2 nodes (one per zone when possible)
Placement Constraints¶
Fine-tune shard placement with constraints:
curl -X POST "http://localhost:8080/vdb" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{
"name": "orders",
"shard_count": 8,
"placement": {
"replica_factor": 3,
"zones": ["us-east", "eu-west", "asia"],
"constraints": [
{"type": "min_per_zone", "value": 1},
{"type": "prefer_zones", "value": ["us-east", "eu-west"]}
]
}
}'
Placement Options¶
| Option | Type | Description |
|---|---|---|
replica_factor |
integer | Total replicas per shard |
zones |
array | Preferred zones for placement |
constraints.min_per_zone |
integer | Minimum replicas per zone |
constraints.max_per_zone |
integer | Maximum replicas per zone |
constraints.prefer_zones |
array | Ordered zone preference |
Cross-Node Replication¶
When a VDB is created with replica_factor > 1, Barrel automatically sets up replication between nodes.
How It Works¶
- Primary election: Each shard has a primary node
- Replica assignment: Replicas placed in different zones when possible
- Continuous sync: Changes replicate asynchronously
- Conflict resolution: MVCC revision trees handle conflicts
Replication Topology¶
Primary (us-east)
│
┌─────────┼─────────┐
▼ ▼ ▼
Replica Replica Replica
(eu-west) (asia) (us-east-2)
Check Replication Status¶
Response:
{
"vdb_name": "users",
"replica_factor": 2,
"shard_count": 4,
"shards": [
{
"shard_id": 0,
"primary": "http://us-east-1:8080",
"replicas": ["http://eu-west-1:8080"],
"replication_tasks": [
{
"source": "users_s0",
"target": "http://eu-west-1:8080/db/users_s0",
"status": "active",
"docs_written": 1500
}
]
}
]
}
VDB Config Synchronization¶
VDB configurations are automatically synchronized across all nodes through a dedicated meta database.
Automatic Sync¶
When a VDB is created on any node:
- Config stored in local
_barrel_vdb_metadatabase - Broadcast sent to all discovered peers
- Peers pull and store the config locally
- Physical shard databases created if needed
On-Demand Config Pull¶
When accessing a VDB that doesn't exist locally, the node attempts to pull its config from peers:
%% Automatically happens when you access a VDB
{ok, Info} = barrel_vdb:info(<<"users">>).
%% If VDB not found locally, tries to fetch from peers
Manual Sync¶
Force sync of all VDB configs:
Multi-Region Deployment¶
Example: 3-Region Setup¶
Deploy a globally distributed VDB across US, EU, and Asia regions.
1. Configure Nodes¶
US Region (2 nodes):
# Node us-east-1
docker run -d --name barrel-us-1 \
-e BARREL_ZONE=us-east \
-e BARREL_NODE_ID=us-east-1 \
-e BARREL_PEERS="http://eu-west-1:8080,http://asia-1:8080" \
-p 8081:8080 barrel/docdb
# Node us-east-2
docker run -d --name barrel-us-2 \
-e BARREL_ZONE=us-east \
-e BARREL_NODE_ID=us-east-2 \
-e BARREL_PEERS="http://us-east-1:8080" \
-p 8082:8080 barrel/docdb
EU Region (2 nodes):
# Node eu-west-1
docker run -d --name barrel-eu-1 \
-e BARREL_ZONE=eu-west \
-e BARREL_NODE_ID=eu-west-1 \
-e BARREL_PEERS="http://us-east-1:8080,http://asia-1:8080" \
-p 8083:8080 barrel/docdb
# Node eu-west-2
docker run -d --name barrel-eu-2 \
-e BARREL_ZONE=eu-west \
-e BARREL_NODE_ID=eu-west-2 \
-e BARREL_PEERS="http://eu-west-1:8080" \
-p 8084:8080 barrel/docdb
Asia Region (1 node):
# Node asia-1
docker run -d --name barrel-asia-1 \
-e BARREL_ZONE=asia \
-e BARREL_NODE_ID=asia-1 \
-e BARREL_PEERS="http://us-east-1:8080,http://eu-west-1:8080" \
-p 8085:8080 barrel/docdb
2. Create VDB with Multi-Region Replication¶
curl -X POST "http://us-east-1:8080/vdb" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{
"name": "global_users",
"shard_count": 8,
"placement": {
"replica_factor": 3,
"zones": ["us-east", "eu-west", "asia"],
"constraints": [
{"type": "min_per_zone", "value": 1}
]
}
}'
3. Verify Replication¶
# Check status from any node
curl "http://asia-1:8080/vdb/global_users/_replication" \
-H "Authorization: Bearer $API_KEY"
4. Write and Read from Any Region¶
# Write to US region
curl -X PUT "http://us-east-1:8080/vdb/global_users/user1" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{"name": "Alice", "region": "us"}'
# Read from Asia region (after replication)
curl "http://asia-1:8080/vdb/global_users/user1" \
-H "Authorization: Bearer $API_KEY"
Shard Rebalancing¶
As data grows or nodes change, you may need to rebalance shards.
Split a Large Shard¶
When a shard grows too large, split it:
%% Check shard sizes
{ok, Info} = barrel_vdb:info(<<"users">>).
Shards = maps:get(shards, Info),
%% Find shards with high doc_count or disk_size
%% Split the large shard
{ok, NewShardId} = barrel_shard_rebalance:split_shard(<<"users">>, 0).
Merge Underutilized Shards¶
When shards are too small, merge adjacent ones:
%% Check if shards can be merged (must be adjacent)
{ok, true} = barrel_shard_rebalance:can_merge(<<"users">>, 2, 3).
%% Merge them
ok = barrel_shard_rebalance:merge_shards(<<"users">>, 2, 3).
Monitor Progress¶
ProgressFun = fun(#{phase := Phase, migrated := M, total := T}) ->
io:format("Phase: ~p, Progress: ~p/~p~n", [Phase, M, T])
end,
%% Split with progress monitoring
{ok, _} = barrel_shard_rebalance:split_shard(<<"users">>, 0, #{
progress_callback => ProgressFun
}).
Failure Handling¶
Node Failure¶
When a node fails:
- Read availability: Reads can be served from any replica
- Write handling: Writes route to available primary/replicas
- Automatic recovery: When node recovers, replication catches up
Zone Failure¶
When an entire zone fails:
- Read availability: Other zones serve reads
- Write availability: Writes continue if quorum available
- Recovery: Full resync when zone recovers
Network Partition¶
During network partitions:
- Split-brain prevention: MVCC handles conflicts
- Eventual consistency: Conflicts resolved on merge
- Manual resolution: Use revision tree for complex conflicts
Monitoring¶
Key Metrics¶
Monitor these metrics for multi-region deployments:
| Metric | Description | Alert Threshold |
|---|---|---|
vdb_replication_lag_seconds |
Replication delay | > 30s |
vdb_shard_doc_count |
Documents per shard | Variance > 50% |
vdb_cross_zone_latency_ms |
Inter-zone latency | > 200ms |
vdb_replication_errors_total |
Replication failures | > 0 |
Health Checks¶
# Per-node health
curl "http://node1:8080/health"
# VDB-specific health
curl "http://node1:8080/vdb/users/_replication" | jq '.shards[].replication_tasks[].status'
Prometheus Metrics¶
Best Practices¶
Zone Placement¶
- Odd number of zones: Use 3 or 5 zones for quorum
- Geographic distribution: Place zones in different regions
- Network quality: Ensure low latency between zones (<100ms)
Replica Factor Selection¶
| Scenario | Replica Factor | Zones |
|---|---|---|
| Development | 1 | 1 |
| Production (single region) | 2 | 1 |
| Production (multi-region) | 3 | 3 |
| High availability | 5 | 3+ |
Shard Count Guidelines¶
| Document Count | Recommended Shards |
|---|---|
| < 100K | 2-4 |
| 100K - 1M | 4-8 |
| 1M - 10M | 8-16 |
| 10M+ | 16-32 |
Network Configuration¶
- Use private networks between zones when possible
- Configure timeouts appropriately for cross-region latency
- Enable compression for cross-region replication
- Use TLS for all inter-node communication
Troubleshooting¶
Replication Not Working¶
-
Check node discovery:
-
Verify authentication:
-
Check replication logs:
Config Not Syncing¶
-
Check VDB exists on source:
-
Force sync:
-
Check network connectivity between nodes
Uneven Shard Distribution¶
- Check document IDs for patterns
- Review hash function configuration
- Consider manual shard split/merge