Multi-server
QuestsTracker supports multi-server synchronization via Redis. This page explains how to configure and maintain a multi-server deployment.
If you only have one server, leave redis.enabled: false in your config.yml. The plugin works perfectly without Redis.
Architecture
Server 1 (Survival) Server 2 (Adventure) Server 3 (Event)
| | |
└───────────┬───────────┘───────────────────────┘
|
Redis Server
|
MySQL / MariaDB
All servers share:
- The same MySQL/MariaDB database (via BetonQuest configuration)
- The same Redis server for real-time synchronization
Requirements
| Component | Version | Description |
|---|---|---|
| Redis | 6.0+ | Cache server and Pub/Sub messaging |
| MySQL/MariaDB | 8.0+ / 10.5+ | Shared database (configured in BetonQuest) |
| Network | -- | Connectivity between all servers, Redis, and the database |
Redis configuration
Installing Redis
# Ubuntu/Debian
sudo apt update && sudo apt install redis-server
# CentOS/RHEL
sudo yum install redis
# Docker
docker run -d --name redis -p 6379:6379 redis:latest
Securing Redis
For a production deployment:
# /etc/redis/redis.conf
requirepass your_redis_password
bind 0.0.0.0 # Or the specific server IP
Plugin configuration
On each server, configure config.yml:
redis:
enabled: true
host: "redis-address"
port: 6379
password: "your_redis_password"
All servers must point to the same Redis server and the same BetonQuest database.
How synchronization works
Redis Pub/Sub channels
The plugin uses two communication channels:
| Channel | Description |
|---|---|
quest-updates | Status changes (activation, completion, progression) |
quest-purge | Player data purge for a package |
Synchronization cycle
- A player completes a quest on Server 1
- Server 1 updates the database
- Server 1 publishes a message on the
quest-updateschannel - Server 2 and Server 3 receive the message
- They invalidate their local cache for that player
- The next read uses up-to-date data from the database
Heartbeat system
When a player switches servers:
- The player disconnects from Server 1
- Redis data remains valid for 2 minutes (heartbeat)
- The player connects to Server 2
- Server 2 retrieves data from Redis (L2 cache -- fast)
- No need to reload from the database
If the player does not reconnect within 2 minutes, the Redis data expires and is reloaded from the database on the next connection.
Two-level cache
The plugin uses a two-level cache system for optimal performance:
| Level | Type | Latency | TTL | Description |
|---|---|---|---|---|
| L1 | Caffeine (local) | Sub-millisecond | 1-2 min | In-memory cache on each server |
| L2 | Redis (distributed) | ~1 ms | 2 min | Shared cache between servers |
Read order
L1 (local) → L2 (Redis) → Database
- L1 -- Local in-memory cache (fastest)
- L2 -- Distributed Redis cache (on L1 miss)
- Database -- Source of truth (on L2 miss)
When data is loaded from the database, it is automatically cached in both L1 and L2.
Protection mechanisms
Circuit breaker
If Redis becomes unavailable:
- After 3 consecutive failures, the circuit breaker activates
- Redis operations fail silently (no error spam)
- The plugin operates in database-only mode
- 30-second cooldown before retrying
- When Redis becomes available again, synchronization resumes automatically
Rate limiting
Redis publications are limited to 100ms debounce per player to prevent overloading the Redis server with rapid updates.
Connection pool
- Maximum: 128 connections
- Minimum idle: 16 connections
- Test on borrow/return for reliability
Diagnostics
Checking the Redis connection
/kgquests redis
Displays:
- Connection status (connected/disconnected)
- Number of cached keys (progress, tracking, statuses)
- Total keys
Checking a player's cache
/kgquests redis <player>
Displays:
- Existence and TTL of progress keys
- Existence and TTL of tracking keys
- Number of status keys
- Alert if keys are missing
Performance statistics
/kgquests stats
Displays hit rates per cache (L1 and L2).
Overall health
/kgquests health
Checks all components: database, Redis, cache, scoreboard.
Common issues
Redis unreachable
Symptom: /kgquests redis shows "Disconnected"
Solutions:
- Verify that Redis is running:
redis-cli ping(should respondPONG) - Check the firewall: port 6379 must be open between servers
- Verify the password in
config.yml - Check server logs for connection errors
Data desynchronized between servers
Symptom: Quests do not update when a player switches servers
Solutions:
- Verify that all servers point to the same Redis:
/kgquests redis - Verify that all servers use the same BetonQuest database
- Force a refresh:
/kgquests refresh <player> - Check the circuit breaker in the logs
High latency
Symptom: The menu or scoreboard is slow
Solutions:
- Check Redis latency:
/kgquests benchmark - Check database latency:
/kgquests health - Place Redis on the same network as your Minecraft servers (ideal latency < 1ms)
- Check cache hit rates:
/kgquests stats
Production recommendations
Performance
- Place Redis on the same network as your Minecraft servers (latency < 1ms)
- Use MariaDB rather than MySQL for better performance
- Monitor hit rates with
/kgquests stats(target: >95%)
High availability
- Configure Redis Sentinel or Redis Cluster for redundancy
- Use a MySQL/MariaDB replica for backups
- Monitor connections with
/kgquests health
Backup
- Regularly back up the MySQL/MariaDB database
- Redis does not need to be backed up (data is in the database)
- Export your
config.ymlandquests_config.yml
See also
- Installation -- Initial Redis setup
- Configuration -- Redis configuration keys
- Troubleshooting -- Connection issues