orm在用户数据日志上的应用
前言
游戏服务器免不了需要记录大量玩家数据变化、玩家操作行为、对局战斗数据等等数据的记录以及后台提供数据的查询入口。我遇到过两种做法。
- 方案一
- 手动创建数据表结构。
- 服务器代码拼接sql调用插入。
- 后台再根据表结构定义写查询页面。
- 方案二
- 服务器先写本地json文件。
- 再选用某种日志采集方案采集日志。
- 采集那边也需要定义表结构,然后插入数据库。
- 后台再根据表结构定义写查询页面。
总的来说,这两种方式效率低下,重复劳动多,并且还需要关心怎么清理过期的历史记录数据(比如一个月前的,可能每个日志记录保留的时间不一样)。我在考虑实现日志系统的时候,就想做一个架构直接能写日志、采集日志、定义日志表、插入日志、查询日志面板、过期数据清理、过期日志文件清理。实现以后,业务上我们只需要去定义日志orm结构
,写日志就行,其他工作架构都统一处理了。
实现方案
写日志
利用use_log的写文件功能。use_log
创建时只需要定义好保留天数(maxage),以及刷磁盘间隔时间(flush_inval),其中保留天数可以解决过期日志文件清理的问题,刷磁盘间隔时间可以缓解磁盘性能压力(不立即flush file:write会利用到内存缓存待写入数据)。实现ormadapter_uselog对接上ormtable只需要实现创建单条数据接口(create_one_entry),创建数据时转成json写入文件。这样有了orm
的加持,我们可以方便的定义字段类型以及字段索引。再利用watch_server把orm
的相关信息发布同步。这样其他服务想了解日志信息订阅即可。实现好之后我们就可以这样写日志了。
1 |
|
日志的写入路径和文件名,通常都会写成一样的,还有日志的_guid
,_svr_type
,_svr_id
,_log_name
,_time
字段,这些都是通用的,每个日志都需要写入这些,所以还需要进一步封装,最后在demo中实现了log_helper,有了log_helper之后我们写日志是这样的。
1 |
|
其中item_change_log
就是日志在数据库中的表名。最终实现后,我们在业务中,后续只需要做这两步,定义结构和写入日志。
日志采集
在logserver中利用watch_syn_client的pwatch
就可以订阅同步到其他服务发布的日志orm
信息,利用同步到的信息,我们能知道对应日志的路径和文件名,然后启用间隔轮询的方式调用use_log
的read
方法,一次采集多行数据。logserver建立一个记录采集信息的orm
表,记录采集的相关信息。
定义日志表
通过watch_syn_client
pwatch同步的信息,我们能知道每个日志表的表字段相关结构信息,利用这些信息,可以很方便的建立对接数据库的orm
对象。
插入日志
采集到的数据,通过解析出log_name
得到对应的orm
,再调用对应orm
创建方法就行。
异常处理,为了避免出现网络波动问题,或者数据库挂逼,出现日志写入失败的情况,增加了一个重试池,写入失败的日志数据会加入重试池,重试池每间隔1分钟尝试写入20条数据,当重试池达到1万+数据时,日志采集暂定,小于1万日志采集继续,这样避免采集过多的数据又无法插入。
查询日志面板
后台服务通过订阅同步也能知道orm
日志表结构,建立适配数据库的orm
,这样后台新增日志或者修改日志就无需修改后台代码了。
过期数据清理
通过同步过来的**保留天数(maxage)**信息,再利用orm:idx_delete_entry
,利用_time
索引做过期数据删除处理。
总结
大大简化了加数据日志的流程,整个日志系统兼顾了稳定性和吞吐量。