#Data management pain

1 messages · Page 1 of 1 (latest)

graceful slate
#

@queen goblet Can i delete data from the cache on an asynchronous thread?

grave cobalt
#

Yeah

#

Id advice using a ConcurrentHashMap

graceful slate
#

thats what im using

#

thanks

graceful slate
queen goblet
#

No

#

They need to be too

graceful slate
#

AutoFlush: Updates the database with the cache
https://mystb.in/EncouragedGenreQuoted.swift

Database: Class for interacting with database
https://mystb.in/GarlicOffenseThursday.php

DataListener: Listeners that loads and unloads players and families
https://mystb.in/AwesomeSubstituteKyle.swift

Family: A class that represents a family. A family is a group of players and has a leader. Should be loaded when at least one member of the family is online
https://mystb.in/ChainRailroadExcellent.java

PlayerData: A class that represents a player.
https://mystb.in/KissAddDaisy.java

Both Family and PlayerData have a static object called NULL_FAMILY and NULL_PLAYER_DATA. I use these because you can't use null values in a concurrent hash map. So basically these are used to tell Autoflush to delete the playerdata or family

#

I have two problems:

  1. When something needs to access an unloaded player or family, the system caches the player/family until it is automatically unloaded on the next flush. I'd rather have some system that instantly unloads the player or family data after modification, but I have no clue how to implement such a system in a clean manner.

  2. I need to preform two tasks that don't really make sense using this system. For one, I need to be able to pick a random family out of all existing families. I can't just pick a family from the database because it may be missing some families that are in the cache but not in the database. Second, I need to make a command that allows users to paginate through all families. No idea how to even start on that one

grave cobalt
#

I'd rather have some system that instantly unloads the player or family data after modification, but I have no clue how to implement such a system in a clean manner.

#

I'd just stick with expiration or a garbage collection pattern

#
  1. I need to preform two tasks that don't really make sense using this system. For one, I need to be able to pick a random family out of all existing families. I can't just pick a family from the database because it may be missing some families that are in the cache but the database. Second, I need to make a command that allows users to paginate through all families. No idea how to even start on that one

Are families separate from users?

#

but anyway

#

you must decide which data source is your primary data source

#

and then make sure that source is up to date when its needed

graceful slate
graceful slate
#

they should be loaded in the cache if at least one member of the family is online

grave cobalt
#

Idk

#

You think my current system is good?

#

hmm

#

how far are you planning to scale the system?

#

lets say amount of users your server should be able to handle concurrently

graceful slate
#

maybe like 50-100

grave cobalt
#

okay

graceful slate
grave cobalt
#

so what is the purpose of the database?

graceful slate
#

its used to store data between server restarts obviosuly

#

I'm mainly loading the resources I will most commonly use from the database into the cache

#

and whatever is in the cache will eventaully get unloaded back into the database

graceful slate
#

Ok forget the first question

#

I still need some help on the second

queen goblet
queen goblet
#

well

#

in that case if you need EVERY family

#

your likely better running a cache layer of your database and its expensive

#

its either that or make calls to get those users each time

queen goblet
graceful slate
#

wont that be kinda expensive though

queen goblet
#

yep

graceful slate
#

do you think flushing the cache and then querying the database is also a good choice?

queen goblet
#

thats the cost of needing to go through every iteration of your data

#

no

#

never flush your cache unless server shut down

#

your cache is a buffer between you and your database

graceful slate
#

i think im using the term flush wrong lmao

#

i mean like

#

update the database with the cache without deleting it

queen goblet
#

give me a minute

graceful slate
#

this is my current implementation, not sure if it's good though

// In Family.java
@Nullable
public static Family loadRandomFamily() {
    CompletableFuture<Void> future = AutoSave.saveCache();
    future.join();

    Family family = LifeSpan.getInstance().getDatabase().getRandomFamily();

    if (family != null) {
        familyMap.put(family.getUuid(), family);
    }
    
    return family;
}

// In Database.java
@Nullable
public Family getRandomFamily() {
    try {
        PreparedStatement statement = conn.prepareStatement("SELECT * FROM Families ORDER BY RANDOM() LIMIT 1;");

        ResultSet result = statement.executeQuery();

        if (result.next()) {
            return formFamily(result);
        }
    }
    catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}
queen goblet
#

If you start your server like this

#

then the line that the blue arrow points at should never happen

#

black = outbound red = inbound

#

read it from left to right top left corner

#

Hopefully this helps visualize seeing your cache as a type of buffer/layer between your program and database

#

ik my graphs suck lol

#

i dont have a good graphin program

graceful slate
#

lemme read this

#

sorry im kinda lost on the second graph lol

#

"the event checks the.. if it already exists see red line"

#

what red line theres 4 connecting to it

#

@queen goblet

queen goblet
#

there

#

arrows

#

maybe that helps?

#

@graceful slate

graceful slate
#

oh damn thanks

queen goblet
#

btw the 2 piece of text on the top center are one piece

#

"send it back to him and async update to database"

graceful slate
#

ye i noticed that

queen goblet
#

sorry it looks like a 5 year old made that graph 💀

#

but its the only way i can rly efficiently explain the buffer/layer cache system

graceful slate
#

hmm so

#

if I'm understanding this correctly

#

you're saying that I should pretty much never read from the database aside from server startup?

#

and after the initial read I'm only ever updating the database?

queen goblet
#

If your wanting a easy way to iterate through all your data, then yes

#

yep

#

you can async update task every like 5 mins

#

just run through all the cache asynchronusly and store it

graceful slate
#

hmm

#

ok but heres the thing

#

I'm not iterating through everything very often

queen goblet
#

what would you rather have

graceful slate
#

so I guess its more of a choice then?

queen goblet
#

Higher RAM usages (Maybe like 20MB at most? If your using pojo classes as the cache objects then cache is low asf) but instant gets, when someone opens a inventory to view familys everything is instantly there

Or use more CPU cycles every time someone opens a inventory, and they all wont instantly be there, they will load like a 1988 webpage

#

and not to mention have get calls to datbase players can control is dangerous

#

they can essentialsl ddos the mysql/entire server by spamming something that calls get to the database

graceful slate
#

i see

queen goblet
#

if its in ram its a mere instant return

#

you said 50-200 families right

graceful slate
#

yeah

queen goblet
#

yeah your cache size will probably barely be a few mb depending on the size of the objects your storing

#

if even a few mb

graceful slate
#

and the entire database will be wiped every 3 days or so

queen goblet
#

yeah you can still use cache layering

#

that wont matter to much

#

just if you wipe a database

#

wipe the cache too ofc

#

and stop any save tasks running

graceful slate
#

ok so at this point I'm only using the database to keep data past server restarts

#

other than that, most of the work is in the cache?

queen goblet
#

yep

#

yes

graceful slate
#

alright

queen goblet
#

A lot of discord bots actually cache all the servers theyre in

#

big bots like tickety have like 50gb of cache

graceful slate
#

i thought this was a bad idea at first but now i dont think it'll be too expensive

graceful slate
queen goblet
#

yeah you kinda have to with discord api sadly

graceful slate
#

anyways

#

thanks so much i appreciate it 🙏

#

one more thing actually

#

about the paginating

#

how would I effectively paginate through the cache

queen goblet
#

just a for loop is fine

#

and every x iterations make a new page

#

a page is a list of data objects

graceful slate
#

but I'm not grabbing all the pages at once

queen goblet
#

then about that idk

#

that ones more a logic question

graceful slate
#

for example /family list 3 will grab the third page

#

yeah its fine i can figure that out

queen goblet
#

"How do i organize a data set by pages"

Would likely be a decent search

Or when conclure/smile is on they might knoe

graceful slate
#

I'm gonna have to sort the cache values by something and then find the page ig

queen goblet
#

actually

#

if redempt is still in help-dev channel ask if his lib handles organizing HashMaps

#

might be able to rip a method from hit github

graceful slate
#

hes not rn but maybe later

#

thanks so much

#

although I do want to keep this thread open and hopefully wait for 7smile7's answer

#

because he was the one who suggested me this original data management structure and i want to see what he says out of curiosity

queen goblet
#

his is likely more or less of the same

#

he just explains it more programatically

graceful slate
#

because how do huge applications do it then?

queen goblet
#

clustering

graceful slate
#

do huge applications store all the data in ram too?

graceful slate
queen goblet
#

it really depends honestly

#

in minecraft you cant rly do it because well

#

its a game

#

but a huge banking system?

#

Yeah just get from datbase

graceful slate
#

yeah speed doesnt matter there i guess

queen goblet
#

who cares about the user waiting 2 seconds

#

but in a game, 2 seconds is a big difference hence why cache is a big deal

graceful slate
#

I see

queen goblet
#

thats why so many games have such high ram usages

graceful slate
#

makes sense

queen goblet
#

cause theyre caching files and assets

#

you would do this same structure if your working with files btw

graceful slate
#

alright

#

I honestly might make a library that automatically does this stuff in the future

queen goblet
#

I will say though, your only issue is gonna be data integrity, so those save tasks are 100% necessary and make sure the itnervals prolly no less than 5 mins

#

that way if something happens to your data only 5 mins of progress is lost

#

eg server crash

graceful slate
#

yeah thats not too important for my situation

queen goblet
#

solar ray makes your memory corrupt

#

not rly an issue now a days

#

but, bit flips happen

queen goblet
graceful slate
#

do bigger games store data to the database after every modification though?

queen goblet
#

i mean you could if you wanted to

graceful slate
#

for example I play destiny 2 a lot and if I got a super rare drop but then my power went out a minute later and that super rare drop was gone I'd be pissed

queen goblet
#

just dont do it on main thread

graceful slate
#

surely the companies have a way to prevent that?

queen goblet
graceful slate
#

oh true

queen goblet
#

so if your power goes out it wont matter

graceful slate
#

but if their servers went out it would cause pain

#

got it

queen goblet
#

yeah, you can definatly set a update() to your database after you update something in cache

Just as MC make sure its async or your gonna freeze the whole server haah

graceful slate
#

okay

#

thanks so much man 🙏

#

i learned a lot from this

queen goblet
#

ofc

#

also make sure your calls to your cache are on main thread, they likely already are but thought ide mention

#

i would definatly look into Completable Futures or callback functions tho

graceful slate
#

i mean shouldn't it work on an alternate thread anyways

#

I'm using Concurrent hash map

queen goblet
#

the actual data objects inside though arent thread safe

graceful slate
#

oh

queen goblet
#

just the map is

#

so referances to the map are safe

graceful slate
#

i have barely any experience in multithreading in java so yeah

queen goblet
#

but the actual values they represent are not

#

Ask conclure about multithreading

#

i dont wanna explain and fuck that part up for you

graceful slate
#

alright

queen goblet
#

i typically get one thing wrong when explaining it