De laag die de spelerdata op een Metin2-server daadwerkelijk beheert, is niet de game-core, zoals velen denken, maar het metin2 db cache-proces. Wanneer je een personage verplaatst, een item oppakt of een quest voltooit, gaat geen van die acties rechtstreeks naar MySQL. Ze passeren eerst een cachelaag in het geheugen. In dit artikel loop ik stap voor stap door hoe het db-proces spelerdata bewaart, wanneer het naar schijf schrijft en waarom deze architectuur zo breed gebruikt wordt.
De multi-procesarchitectuur van Metin2
Een klassieke Metin2-server is geen enkel programma. Hij bestaat uit minstens drie aparte processen, elk met een eigen taak:
- auth — Verzorgt het inloggen en de accountverificatie. Het controleert gebruikersnaam en wachtwoord en geeft een sessiesleutel uit.
- db — De enige toegangspoort voor al het MySQL-verkeer. Het laadt spelerdata in het geheugen, cachet die en schrijft ze periodiek terug naar de database.
- game / core — Het spel zelf. Beweging, gevechten, quests, NPC's en kaartlogica draaien hier. Grotere servers draaien meerdere
core-processen (kanalen).
Het belangrijkste punt: de game-cores praten nooit rechtstreeks met MySQL. Elk lees- en schrijfverzoek wordt via een eigen TCP-protocol naar het db-proces gestuurd. Het db-proces beantwoordt die verzoeken, bevraagt MySQL waar nodig en antwoordt meestal vanuit de kopie die het al in het geheugen heeft.
Waarom bestaat de db cache?
Deze extra laag lijkt op het eerste gezicht misschien onnodige complexiteit. Het doel is echter heel concreet: MySQL beschermen tegen voortdurende query's. Denk aan positie-, levens-, ervarings- en inventarisdata die honderden spelers tientallen keren per seconde wijzigen. Elke wijziging meteen naar de database schrijven zou een belasting zijn die de schijf en InnoDB simpelweg niet aankunnen.
De db cache lost dit als volgt op:
- Wanneer een speler inlogt, worden al zijn gegevens (personage, inventaris, quests, affects, kluis) één keer uit MySQL gelezen en in het geheugen bewaard.
- Alle wijzigingen tijdens het spel gebeuren eerst op deze geheugenkopie — ze raken de schijf niet.
- Schrijfacties naar de database worden gebundeld en op vaste intervallen uitgevoerd, plus bij het uitloggen van de speler.
Het resultaat: het aantal schrijfacties dat MySQL bereikt daalt duizendvoudig, terwijl in-game handelingen op geheugensnelheid reageren.
Hoe wordt spelerdata in het geheugen geladen?
Wanneer een speler een personage selecteert, verzamelt het db-proces alle gegevens van dat personage uit de betreffende tabellen. In Metin2 staat spelerdata niet in één tabel; ze is logisch opgesplitst:
player— het basispersonage (level, ervaring, locatie, stats)item— inventaris, kluis en uitgeruste itemsquest— queststatus en vlaggenaffect— actieve buff/debuff-effectensafeboxenmall— opslag en mall-kluis
Deze rijen worden in het geheugen samengevoegd tot een cache-object dat aan het personage gekoppeld is. Zolang de speler online blijft, leeft dit object; voor elke datavraag raadpleegt de core dit object in plaats van MySQL.
Wanneer wordt data naar schijf geschreven?
De opslaglogica is het meest kritieke deel van deze architectuur, want de meeste spelersverliezen (item-dupes, rollbacks, verdwenen items) ontstaan hier. Data wordt in drie situaties naar MySQL geschreven:
- Periodieke opslag: op vaste intervallen scant het db-proces de "vuile" (gewijzigde) records in het geheugen en schrijft ze als
UPDATE-statements naar MySQL. Dit interval hangt af van de configuratie; het is doorgaans een vertragingsvenster van enkele seconden. - Opslag bij uitloggen: wanneer een speler het spel verlaat of de verbinding wegvalt, worden alle gegevens van dat personage onmiddellijk naar schijf geschreven en uit de cache verwijderd.
- Directe opslag bij kritieke gebeurtenissen: voor gevoelige handelingen zoals het aanmaken van valuta of kluistransacties kan data zonder wachten worden weggeschreven.
Precies daarom gaan bij een onverwachte crash (kill -9, hardwarestoring, OOM) alle wijzigingen na de laatste periodieke opslag verloren — vandaar de "rollback" die spelers ervaren. Het snelheidsvoordeel van de architectuur is tegelijk haar grootste risicopunt.
De communicatie tussen core en db
Het gesprek tussen de game-core en db verloopt via een eigen, pakketgebaseerd protocol. Een core stuurt een pakket als "laad de data van deze speler" of "werk dit item bij", het db-proces zet het in de wachtrij, verwerkt het en stuurt het antwoord terug. Deze structuur waarborgt consistentie vanuit één gezaghebbende bron (db) wanneer meerdere core-processen dezelfde spelerspool delen.
Aan de configuratiekant wordt de verbinding meestal opgezet met regels als deze:
PLAYER_SQL: localhost player root wachtwoord
COMMON_SQL: localhost common root wachtwoord
# adres van het db-proces aan de core-kant
db_addr: 127.0.0.1
db_port: 15000
Hier zie je twee aparte databases: player (spelerspecifieke, voortdurend wijzigende data) en common (alleen-lezen definitietabellen zoals item_proto en mob_proto). De common-data verandert zelden en wordt dus zwaar gecachet; de player-data is wat de db cache daadwerkelijk beheert.
Tips voor goed db cache-beheer
- Houd het opslaginterval in balans: een te lang interval vergroot het rollback-risico, een te kort interval vermoeit MySQL. Stem het af op je serverbelasting.
- Monitor het db-proces: als db crasht, kan er geen data worden opgeslagen, zelfs als de game-cores blijven draaien. Bewaak altijd de gezondheid van het proces.
- Gebruik InnoDB: geef de voorkeur aan InnoDB boven MyISAM voor de player-tabellen; dat maakt verschil voor consistentie na een crash en voor gelijktijdige schrijfacties.
- Maak back-ups: een regelmatige
mysqldump-back-up is de enige veilige manier om het onvermijdelijke dataverlies binnen het periodieke opslagvenster te compenseren.
Veelgestelde vragen
Gaat spelerdata verloren als de db cache crasht?
Alle wijzigingen die zijn opgebouwd na de laatste periodieke opslag gaan verloren. Als het db-proces netjes afsluit (graceful shutdown), spoelt het de geheugendata naar schijf; bij een plotselinge crash (kill -9) is alleen de data tot aan het laatste opslagpunt veilig.
Waarom verbindt de core niet rechtstreeks met MySQL?
Voor prestaties en consistentie. Eén db-proces bundelt de schrijfbelasting om MySQL te beschermen en fungeert als de enige gezaghebbende databron over meerdere cores, waardoor dataconflicten worden voorkomen.
Wat is het verschil tussen de player- en common-database?
player bevat de voortdurend wijzigende data van de speler (personage, items, quests) en wordt door de db cache beheerd. common bevat zelden wijzigende definitietabellen zoals item_proto en mob_proto en wordt vooral gelezen.
Heb je last van dataverlies, rollbacks of prestatieproblemen op je Metin2-server? Laten we samen je db cache-configuratie en database-architectuur doornemen. Neem contact met me op.