On the game server, to process player login, You need to query the player's account and password from the database. When a player goes online or offline, you need to read and save the player's role data from the database. Compared with game logic processing, database operations are relatively slow. Even if you use multiple threads and multiple database connections to improve the processing capability of database operations, in highly concurrent and high-load server applications, this will still be a considerable load bottleneck. To imagine such a design scheme, see:
When a large number of players log on to the game server, even if they have their own cache mechanism due to a large number of database access requests, the server will still exhaust all logical thread resources, the server's processing capability will be reduced to DBMS's processing capability.
To avoid blocking logical threads, asynchronous database access can be used, that is, database operation requests are submitted to a dedicated database processing thread pool. Then, the logical thread no longer waits for the database processing results and continues to process others, it is not blocked here.
Abstract: For a game object that requires persistence, you can consider that it has two methods to read and save. Then we abstract a DBO interface:
Struct idbo
{
Virtual bool savetodb (DB *) = 0;
Virtual bool loadfromdb (DB *) = 0;
};
Then change the design scheme to the following:
After changing to the database for asynchronous processing, I want to think about how the current storage mechanism of game data should be improved. To ensure data security, we hope that player data will not be saved only when players go offline, instead, we want to save the data of all online players at intervals. We can consider the following idea: assume we have a gamedb server, where gamedb caches the role data of all online players, each storage time, gamedb submits copies of all online player data (DBO) to the DB thread pool for data storage. The submission process is fast, the logic thread of gamedb can still process game server updates and read cache requests. Why do we need to save copies? The execution of the DB thread may take a long time to save the queue, but the data in the queue is the data at the time when gamedb submits DBO, this ensures the integrity of the player's game data.
Of course, what I mentioned here is just a train of thought. There are still many details not discussed here. For example, if the DB thread pool is saving the data saved at nine o'clock, when the new storage time at ten o'clock is reached, the DB thread pool has not completed the DBO copy queue at nine o'clock. How should it be handled? The problem of DBO object granularity and DBO queue priority.
PS: the architecture in this article is actually a gamedb server. The logic processing in it is the logic processing of gamedb. You can understand this article as follows: how to implement a gamedb server...