https://metaplay.io logo
Caching in metaplay
# questions-and-feedback
d
Hi, I am using metaplay with photon and i would like to cache what rooms players are in inside metaplay. I am currently using ephemeral entities and sharding by photon region. In a more traditional server setup not using akka I would probably have looked to a redis to cache this type of information. Feels like this is not required and I am wondering wether you could give me some guidance about how to implement this type of in-memory cache. I am trying to shard, have a regular c# data structure and rely on the single threading of the entity to ensure data integrity. Is this the right approach? Are there more suitable libraries I should be using? What about Entity type and replication? Should I have a write instance and then replicas? Thanks for any advice Andre
n
Hi, So the idea is to be able to look up some info about a player, without needing to message the actual player entity (to avoid waking up the actor)? Simplest might be to just store the info in the database, in a new table with the player id as the key. But i realize you specified in-memory caching, and this isn't that. I mention it as it may still be viable. ---- Other than that, an implementation using ephemeral entities does seem like the most obvious option. Could you describe how you shard using the photon region? I guess this means that, to query the cache, you need to know the player's region. Is the region known already without querying it from the player entity? I imagine the main purpose of sharding is to allow splitting the cache's resource usage to multiple server nodes. Or is there some interaction between the cache entries per region, dictating the sharding strategy? For a general player cache, the simplest sharding would be based on the player id. Say there's a cache shard on every node, using
ShardingStrategies.CreateStaticService()
for the
ShardingStrategy
(i'm ignoring dynamically-scaling node sets, player entities don't use them anyway). To calculate the EntityId value of the cache where a given player's info is: take the player id value, modulo by
clusterConfig.GetNodeCountForEntityKind(EntityKindGame.PlayerInfoCache)
(from
ClusteringOptions
). This method has an obsoletion warning related to dynamic scaling, but it can be silenced since we know dynamic scaling isn't involved. The rest is what you probably already have: messages for updating and getting a player's info. And probably some pruning to keep memory usage bounded. As you say, threading issues are avoided, as each entity works one message at a time, so the cache can use e.g. a plain
Dictionary<,>
without locking. For a simple cache like this, i wouldn't bother with the complication of separate write/read replicas. I expect the individual operations to be quite cheap.
d
Hey, Thanks for the detailed reply. With regards to Photon for example I have my own matchmaker which has a room registry and the players in each room. So given that a players is not switch photon region easily I can pass the region in the matchmaking request. And I can us a couple of other criteria there as well. I am reasonably happy with this solve atm. I guess my question was maybe a bit more generic like say I want to store an inverse lookup of player Id to room then I would want a dictionary with all the online players. Typically I would have resorted put this into a memcached and managed the size of that cache and eviction policy and selected a corresponding high memory server. In a metaplay/akka architecture I see that this would be an ephemeral entity that would get sharded and spread accross a bunch of nodes. Say I wanted to query the room where all my friends are then I would fan out the query to all the shards. My main concern with this approach which I wanted to validate is whether there are runtime memory considerations I should consider. I presume the kubernetes nodes are identical and one would need to ensure each shard is not using too much memory. How would you reason about that part? Thanks Andre