How to handle a database which is constantly updated from a game - mysql

I am working on a game which will store data in a database for multiplayer purposes. A simplified version of the data to be stored is something along the following lines:
Player A goes to a country X on a map and by doing so that country will lose influence over time.
This would be simple enough as the local game could update in the background and then send an update to the database whenever the players stops having an influence there.
The complication comes when:
Player B goes to country X after player A. To check the current influence of country X one of two things need to happen, either A) the influence field in the database updates itself over time, or B) the game constantly updates the database every few seconds when the player A's game updates.
A) sounds like the better option, but I don't actually know if that's possible (is it?) and how much of a strain would that be on the database with a lot of countries?
Sorry if this sounds vague but it seems like a fairly generally applicable scenario for more than just games. If you need any clarification just ask.

Simple, You can do this from database with a Sql Job
Create a SP that calculates influence based on some fields and update it into some column.
Call this SP in a job, schedule it to run every 5 mins or whatever time you want.

Related

Best and most efficient way for ELO-score calculation for users in database

I'm having a hard time wrapping my head around the issue of an ELO-score-like calculation for a large amount of users on our platform.
For example. For every user in a large set of users, a complex formule, based on variable amounts of "things done", will result in a score for each user for a match-making-like principle.
For our situation, it's based on the amount of posts posted, connections accepted, messages sent, amount of sessions in a time period of one month, .. other things done etc.
I had two ideas to go about doing this:
Real-time: On every post, message, .. run the formula for that user
Once a week: Run the script to calculate everything for all users.
The concerns about these two I have:
Real-time: Would be an overkill of queries and calculations for each action a user performs. If let's say, 500 users are active, all of them are performing actions, the database would be having a hard time I think. There would them also run a script to re-calculate the score for inactive users (to lower their score)
Once a week: If we have for example 5.000 users (for our first phase), than that would result into running the calculation formula 5.000 times and could take a long time and will increase in time when more users join.
The calculation-queries for a single variable in a the entire formula of about 12 variables are mostly a simple 'COUNT FROM table', but a few are like counting "all connections of my connections" which takes a few joins.
I started with "logging" every action into a table for this purpose, just the counter values and increase/decrease them with every action and running the formula with these values (a record per week). This works but can't be applied for every variable (like the connections of connections).
Note: Our server-side is based on PHP with MySQL.
We're also running Redis, but I'm not sure if this could improve those bits and pieces.
We have the option to export/push data to other servers/databases if needed.
My main example is the app 'Tinder' which uses a sort-like algorithm for match making (maybe with less complex data variables because they're not using groups and communities that you can join)
I'm wondering if they run that real-time on every swipe, every setting change, .. or if they have like a script that runs continiously for a small batch of users each time.
Where it all comes down to. What would be the most efficient/non-database-table-locking way to do this, with keeping the idea in mind that there will be a moment that we're having 50.000 users for example?
The way I would handle this:
Implement the realtime algorithm.
Measure. Is it actually slow? Try optimizing
Still slow? Move the algorithm to a separate asynchronous process. Have the process run whenever there's an update. Really this is the same thing as 1, but it doesn't slow down PHP requests and if it gets busy, it can take more time to catch up.
Still slow? Now you might be able to optimize by batching several changes.
If you have 5000 users right now, make sure it runs well with 5000 users. You're not going to grow to 50.000 overnight, so adjust and invest in this as your problem changes. You might be surprised where your performance problems are.
Measuring is key though. If you really want to support 50K users right now, simulate and measure.
I suspect you should use the database as the "source of truth" aka "persistent storage".
Then fetch whatever is needed from the dataset when you update the ratings. Even lots of games by 5000 players should not take more than a few seconds to fetch and compute on.
Bottom line: Implement "realtime"; come back with table schema and SELECTs if you find that the table fetching is a significant fraction of the total time. Do the "math" in a programming language, not SQL.

Database for analyzing relationships between MMO players based on millions of Player->Player events?

I play the game "Planetside 2", which provides a game-data REST API and a real-time websocket event-streaming service. I want to analyze relationships between groups of players based on their in-game actions. I have very little prior experience with databases, and don't know whether a relational, graph, or document-based database is most appropriate.
Players are organized like this:
Faction A Faction B
|____Outfit Outfit____|
| |____Player Player____| |
| |____Player Player____| |
| |
|____Outfit Outfit____|
|____Player Player____|
|____Player Player____|
There are 3 factions, but you get the idea. I want to examine the relationships between players and other players and outfits.
The vast majority of in-game events are of the form:
(Player1)-->(Action)-->(Player2)
Each event arrives in a JSON document with a form like this:
{
"payload":{
"amount":"",
"character_id":"",
"event_name":"GainExperience",
"experience_id":"",
"loadout_id":"",
"other_id":"",
"timestamp":"",
"world_id":"",
"zone_id":""
}
}
All the event payloads are flat, as above, but there is no guarantee the developers will not add or remove fields from the events. GainExperience is a particularly tricky type of event because there are nearly 400 different events that reward experience. The other_id field identifies the recipient of the event, if any. For example, if someone revives another player, the revived player's character_id would be placed in other_id.
Most teamwork-based events are GainExperiance events.
The sorts of queries I want to do:
Most of the sorts of things I am interested would involve finding all occurrences of a particular event between members of different groups, then calculating and displaying statistics about those events. Maybe "intersections" is the right set-theory term for it?
What makes me uncertain about which type of database to use is this:
The sheer quantity of players, outfits, and events.
There are in-game "alerts", contests that last 2 hours. During a prime-time alert, there can be as many as:
1000+ simultaneous players in the Alert zone.
2000 total participants.
400-500 outfits represented by at least one member.
1-1.5M events delivered by the event stream, depending on which events are subscribed.
The most active outfits may have as many as 100 participants in an alert.
That makes for some really scary numbers of possible player-player, player-outfit, and outfit-outfit relationships during a single alert. If I wanted to track more than individual 2-hour alerts, I can easily see these numbers causing my database to explode if I am not careful.
These are the databases I have looked at so far:
MySQL: This is what other developers who use the PS2 API use, and the server-side database is also some sort of SQL database, which is reflected in the way the API collections are structured.
My main concern is how to handle GainedExperiance events, because that single event type actually encompasses nearly 400 different events. I don't know if it would be best to leave it in a single large table, or attempt to split it into a bunch of tables by experiance_id. I also doubt that SQL is the best way to express the queries I am interested in.
CouchDB: The way it does map-reduce looks really interesting, but AFAIK it becomes really costly to change or add new views once you have a few million records in there. Saving the events as they stream in would be nice and trivial though.
MongoDB: Treating each event as a tiny document would certainly be convenient, but considering that each is so small and flat I don't think I would really be making use of MongoDB's strengths, and wonder if another DB is better suited to this.
Neo4j: A graph is great for representing relationships, but AFAIK they are designed more for a small number of edges between a large number of nodes, not a large number of edges between a (comparatively) small number of nodes. This would be millions of edges between thousands of nodes, which is a bit different than your typical "find friends of friends of friends" sort of examples you read about.
TL;DR:
I want to look at the ways groups of players interact in an online game, particularly team-work. There is a significant quantity of data available, most of it in the form of actions between two players. I am using my own PC for the time being, and have basically no real experience working with databases. I am intending to use Nodejs.
Which database would be the best tool for this job?
Well, I would go for classical RDBMS like PostgreSQL or MySQL. The amount you mention (1.5M events) is a piece of cake. I would probably try to store player-player, player-outfit and outfit-outfit events each into separate table.
you might look at "wamp" or "xamp" = windows or linux computer, with apache, mysql, and php. there is a good amount of php apps out there open source and simply how to guides vs node.js that might help ya.
if this was just a quick study to see info (school project) thing. anything might work.but somthing that actually stores all the data into database table/s, and in a single file is what ya looking at. storing multi info in different files = ouch.

Getting average or keeping temp data in db - performance concern

I am building a little app for users to create collections. I want to have a rating system in there. And now, since I want to cover all my fields, let's pretend that I have a lot of visitors. Performance comes into play, especially with rates.
Let's suppose that I have rates table, and there I have id, game_id, user_id and rate. Data comes simple, for every user there is one entry. Let's suppose again, that 1000 users will rate one game. And I want to print out average rate on that game subpage (and somewhere else, like on the games list). For now, I have two scenarios to go with:
Getting AVG each time the game is displayed.
Creating another column in games, called temprate and store there rate for the game. It would be updated evey time someone votes.
Those two scenarios have obvious flaws. First one is more stressful to my host, since it definietly will consume more power of the machine. Secound is more work while rating (getting all the game data, submitting rate, getting new AVG).
Please advice me, which scenario should I go with? Or maybe you have some other ideas?
I work with PDO and no framework.
So I've finally manage to solve this issue. I used file caching based on dumping arrays into files. I just go with something like if (cache) { $var = cache } else { $var = db }. I am using JG Cache, for now, but propably I'll write myself something similar soon, but for now - it's a great solution.
I'd have gone with a variation of your "number 2" solution (update a separate rating column), maybe in a separate table just for this.
If the number of writes becomes a problem, then that'd be well after select avg(foo) from ... does, and there are lots of ways to mitigate it by just updating the average rating periodically or just processing new votes every so often.
Likely then eventually you can't just do an avg() anyway because you have to consider each vote for fraud, calculating a sort score and who knows what else.,

mysql: average time for the connected visitors - optimization

The system I work is a little more complex to explain here but I can reduce it to something more simple.
Let's say I have a simple chat server and I count the seconds every client stays connected and save it in a table(I'm using mysql).
So every time a client connects I save the time he stays connected in seconds (int)
If he disconnects and connects again I save this info in another row because this is how I want. The number of times a client connects to the server in a day is between 50k-500k or even more(I know, I know but this is related to my complex system but irrelevant to my question here).
My problem is that I want to show to every client some stats about his visits similar to google analytics(by days), to be more specific I'm interested in showing the average time he spent on a certain day.
I'm looking at an optimized way to do this. So far I've thought about the following solutions:
use select avg(time) from table where date=.... but speed problems might occur
save the avg time in a separate table for every day and user. This solutions is ok, but raises another question: how do I save the average time? here are the situations I was thinking:
a) use mysql trigger to update the stats every time a client is connecting (using INSERT AFTER ...) this solution is not bad, however like I said the client can connect 500k times/day which means 500k times mysql needs to calculate the average time
b) make a separate application similar to a cron job or a timer task that updates the stats every X hours ,this way I know the mysql server will be used only once a few hours depending on the number of clients I have.
So far I'm thinking of implementing the 2.b solution, but I said to ask you first before proceeding. If you have better ideas please share.
Thanks
You can use solution a but don't recalculate the average over and over again. You can do it by storing the current average and the amount of items that where used to calculate the average. Your formula would be like:
(current_average*number_of_old_items+new_value)/(number_of_old_items+1)
In my opinion, this:
speed problems might occur
is not enough reason to avoid what is certainly the simplest and least error-prone solution, especially when it is so easy to change if and when speed problems do occur.
That being said — in the event of speed problems, I agree with your assessment: better to use a scheduled job that computes the average than to add a trigger that will impose a penalty on every insert.

DB design question - multiplayer game

I am new to DB design. I am trying to write a board game (4 players max) and was trying to come up with a way to communicate moves among each other.
I am using a DB for this as per suggestions on stackoverflow.
My problem is this - When player A makes a move that move has to be read by B,C and D. So the fact that A made the move needs to be communicated to B,C and D. I am doing it the following way. Please tell me if there is a better way to do it. To me it seems all wrong and incredibly flaky.
I have a table with the following fields -
gameId, userMove, flagA, flagB, flagC, flagD
So when A makes the move I write among other things - (flagA=0, flagB=1, flagC=1, flagD=1)
When B,C or D read A's move they decrement their corresponding flag.
A will not update the table unless all flags are 0.
Same thing happens when others make their moves.
Comments? There has to be a better way for this. The things I am seeing wrong here -
I am looping on a select until all flags are 0 for A
I am looping on a select until the flag for the corresponding user is set to read the move.
That is a lot of server load and client timeouts I need to worry about.
I hope I have been able to explain my problem clearly. Please ask questions if needed.
Any help is appreciated.
EDIT: The game is web based (runs in a browser) and I am using php for the server side development and so I cannot use an in-memory cache though I would have loved to do that if possible.
Thanks,
- Pav
If the players of your game will be interacting with one game server during a single game session, it looks like you can keep all that state in memory.
Databases are great for durable storage of data with guarantees for atomicity, consistency and integrity. However, you don't seem to need any of these features for the temporal state that you are describing.
If flagA,B,C and D are all bits you might consider putting them all into one column and treating that column as a bit mask.
This will allow one column to control all flags. It can make your selects and updates much cleaner.
Read up on using bitmasks here:
http://www.gordano.com/kb.htm?q=966
http://en.wikipedia.org/wiki/Mask_%28computing%29
Have you considered usng a file to store the info?