zoukankan      html  css  js  c++  java
  • 游戏服务器缓存策略

    1:什么是缓存

        在数据库与服务器逻辑之间加入的数据层


    2:作用

        减少数据库操作

        服务器使用mysql作为数据库,mysql每秒钟并发数量有限,所以我们要减少mysql的操作。


    3:erlang的缓存

        erlang 在内存中可用 进程字典/ gen state / ets 储存变量,理论上三种方式都可以作为缓存


    4:缓存实现方案

        方案 1

            原理

            读数据时从缓存内读取,如果缓存不存在则从数据库中筛选,并放入缓存内

            数据变更时直接操作数据库,并清除缓存

            实现方式

            启动一个gen_server进程将所有 ets建立起来,ets会分为 ets_player,ets_bag 等将数据分开储存到ets表中,一般以玩家id作为ets的key,读取某个数据会优先访问ets表中数据,再从数据库筛选

            这是我们最初的方案,缺点十分明显,只能减少部分读取操作,在频繁更改数据的情况下,缓存几乎没有作用,缓存在不停的被清理,当需要读取数据时又需要重新从数据库中拉取。


        方案2

            原理

            读取策略与方案1一致

            数据变更时变更缓存内数据,不操作数据库,当玩家下线时再将缓存数据同步到数据库中


            实现方式

            同样会启动一个gen_server进程将所有 ets建立起来,不同的是ets中的每一行多了一个是否修改的标识位,玩家读取数据依然优先访问ets表中数据

            当玩家修改数据,例如升级后,修改ets_player中对应的数据,并将ets中修改标识设为已修改

            玩家下线后,顺序检查各个ets中的数据,将标识为已修改的数据同步到数据库中


            方案2与方案1相比,最大的变更在于数据更改时不清理缓存,而是修改缓存,这就避免了频繁的从数据库中筛选数据。

            将数据库同步操作积累到玩家下线而不是立即写库,可以减少许多sql语句,例如玩家在上线期间由 1级升到5级,下线写库只会执行一条sql,而即时写库则需要4条,对2,3,4,5分别执行update

            最初我们以为这套方案已经可以满足游戏线上运行需求,直到我们做了一个压力测试(膝盖中了一箭?),例如你有10多个系统,玩家,竞技场,背包,抽奖,等等等等那么在玩家下线时会出现数据库操作高峰。在压力测试时峰值十分明显,尤其是开服初期导量十分多的情况。


        方案3

            原理

            由于玩家下线时间可能会出现峰值,所以我们想到了使用定时写库这种方式,将写库时间设定为我们认为合适的间隔


            实现方式

            每一张数据表都启动一个对应的gen_server来管理数据,进程内部会创建一个ets表,玩家读取/修改数据时都会访问对应的gen_server

            当玩家修改信息后,gen_server内部会记录修改的信息。

            gen_server内部启动一个定时器,每隔一段时间将修改的数据同步到数据库中


            与方案2相比,方案3将写库时间控制在自己手里,在游戏开新服导量期间,可能设定数小时同步一次数据,可以很大程度减少sql压力

            但这套方案也有缺陷,由于玩家查询/修改数据都需要访问同一个gen_server,部分gen_server 如玩家信息,就会出现瓶颈,出现超时现象

        方案4

            原理

            为了解决方案3中gen_server访问的瓶颈问题,我们在gen_server外层又添加了一层缓存


            实现方式

            在方案3的基础上,又将方案1,2中的cache_process添加回来,玩家读取数据会先访问cache_proces中的数据,如果其中没有再访问对应的gen_server进程


            最终 读取数据流程       玩家获取数据 -> cache_process中查找 -> gen_server 中查找 -> 数据库中查找

                                                    玩家更改数据 -> 更改cache_process

                                                                             -> 更改 gen_server 中数据 -> 一定时间后 gen_server将数据写回数据库

  • 相关阅读:
    Oracle中的exist和in
    oracle恢复误删数据
    【axios】API 说明
    Content-type对照表
    【gdal】创建GeoTiff栅格数据
    NPM使用
    【nodejs】request 和 response 对象
    【nodejs】express框架+mysql后台数据查询
    webapp网络定位
    JS对象创建的几种方法
  • 原文地址:https://www.cnblogs.com/l1pe1/p/8412859.html
Copyright © 2011-2022 走看看