Cross-server
Running one shared auction house across a network, what has to be shared and what happens if Redis goes down.
Point several servers at one database and one Redis and they share a single auction house. A player lists an item on survival, another player buys it on skyblock, and both menus update within about a second.
What has to be shared
All three of these are required. Getting any one wrong gives you two auction houses that look like one.
| Requirement | |
|---|---|
| Database | Every server points DATABASE at the same MySQL or MongoDB. SQLite cannot be shared |
| Redis | Every server points CROSS-SERVER.REDIS at the same Redis instance |
| Server ID | Every server has a different CROSS-SERVER.SERVER-ID |
Everything else can differ per server. Menus, language, sounds, price bounds and slot
limits are all local settings. A network can run a different gui.yml on each server and
they still share listings.
Turning it on
Switch the storage backend
SQLite is a single file and cannot be shared. Set DATABASE.TYPE to MYSQL or
MONGODB and fill in the connection details. See Storage.
Copy that database block to every server
Byte for byte. If one server points at a different database it silently runs its own auction house.
Enable cross-server mode
CROSS-SERVER:
ENABLED: true
SERVER-ID: "survival"
REDIS:
HOST: "localhost"
PORT: 6379
PASSWORD: ""
DATABASE: 0
TIMEOUT: 5000Give each server its own ID
survival, skyblock, creative, whatever you like, as long as they are all different.
The ID appears in /ah about and is attached to every listing, so you can tell where an
item was listed.
Restart every server
DATABASE.TYPE is not re-read by /ah reload, so this needs a full restart rather than a
reload.
Check it
Run /ah about on each server. It reports the platform, the storage backend and whether
cross-server mode is on. Then list something on one server and open /ah on another.
Redis settings
| Key | What it does | Default |
|---|---|---|
CROSS-SERVER.REDIS.HOST | Redis hostname | localhost |
CROSS-SERVER.REDIS.PORT | Redis port | 6379 |
CROSS-SERVER.REDIS.PASSWORD | Leave empty when Redis has no password set | "" |
CROSS-SERVER.REDIS.DATABASE | Redis database index | 0 |
CROSS-SERVER.REDIS.TIMEOUT | Socket timeout in milliseconds | 5000 |
The connection is tested with a ping at startup rather than assumed. If it fails, the plugin logs the error and carries on as a single server rather than pretending to be connected.
The sync switches
CROSS-SERVER.SYNC controls what actually crosses the wire. All four are on by default.
Broadcasts new, sold, cancelled and expired listings to the other servers so open menus update within about a second.
Turn it off and the other servers only notice a change on their next refresh: when a player presses the Refresh button, or when a cache invalidation arrives.
This is the switch that makes the network feel like one auction house. Leave it on unless you have a specific reason.
Lets any server ask the others to rebuild their listing cache from the database.
It is cheap and it repairs drift after a network hiccup. The only thing that publishes an
invalidation is /ah reload, on the grounds that a reload is the moment an admin is most
likely to have changed something behind the plugin's back.
How often, in milliseconds, this server announces it is alive. Defaults to 30000, so
every 30 seconds.
Set it to 0 to disable the heartbeat entirely. Nothing else depends on it, so turning it
off is safe.
Delivers a payout the moment a player is seen online on another server, rather than making them wait for their next login on the server that created it.
With this off, a player who sells something on survival while standing on skyblock gets their money the next time they join survival. With it on, they get it where they are.
What crosses the wire
Redis carries small notifications only, on a single channel. A message names its type, the server it came from and one or two arguments, for example "listing 42 sold". No item data and no player inventories travel over Redis.
The message types are listing created, sold, cancelled and expired, cache invalidation, payout available, sale notification, and heartbeat.
Messages a server published itself are ignored on receipt, since it already applied them locally.
The database is the single source of truth. Redis is a notification bus, nothing more. That is what makes the failure mode below so mild.
If Redis goes down
The network keeps working. Every server still reads and writes the same database, so nothing is lost, nothing is duplicated and no sale can go through twice.
What you lose is the fast update:
| Still works | Degrades |
|---|---|
| Listing, buying, cancelling | Menus on other servers go stale until refreshed |
| Money and items moving correctly | Cross-server sale notifications stop arriving |
| Payouts, on the next login | Payouts wait for a login on the right server |
| Every dupe protection | Heartbeats stop |
Players can press the Refresh button in the auction house menu to force a fresh read from the database at any time, which sidesteps the staleness entirely.
If Redis is down when a server starts, that server logs the failure and runs as a single server against the shared database. Restart it once Redis is back.
Dupe protection across servers
Every state change that moves value is a conditional database update rather than a read followed by a write. Two servers trying to sell the same listing at the same moment both issue the same update, and the database lets exactly one of them through. The loser is told the listing is gone.
The collection box works the same way, so an item can be claimed once and only once, on one server only.
Troubleshooting
Check that every server points at the same database, not just the same database type.
Check DATABASE.MYSQL.HOST, PORT and DATABASE on each one. /ah about reports the
backend actually in use.
Redis is not connected, or SYNC.AUCTION-UPDATES is off. Check the startup log for a
Redis connection failure, and check that every server uses the same Redis host, port and
database index.
Two servers are sharing a SERVER-ID. Give each one its own.
Either CROSS-SERVER.ENABLED is false, or the Redis connection failed at startup and the
plugin fell back to single-server mode. The console will say which.