在游戏应用中,数据更新是非常频繁的。用户游戏数据像位置、装备等,会随着时间的变化而变化,为避免频繁的数据同步影响运行效率,我们一般会将数据保存在内存中,并通过定时器或其它方式持久化数据。pomelo-sync是Pomelo 提供的一个简单的数据同步模块,它可以将内存中的数据同步到mysql、redis或文件等存储引擎中。
1. pomelo-sync模块介绍
pomelo-sync(Data sync)是一个简单的数据同步模块,它可以支持不同情况下的定时器调用或实例引用。pomelo-sync数据同步还支持内存操作,像redis、MongoDB等NoSQL数据库,开发者就可以认为是一个没有事务的内存式数据库。
pomelo-sync支持的同步特性有timer sync、set、get、mset、mget、hset、hget、incr、decr、flush、merger、showdown、info等。
2. pomelo-sync的使用
2.1 安装pomelo-sync
npm install pomelo-sync
2.2 使用
pomelo-sync安装后,可以像下面这样使用:
var Sync = require('pomelo-sync');
var opt = opt || {};
var updateUser = function(dbclient,val) {
console.log('mock save %j',val);
}
var dbclient = {}; // 数据库连接等
var id = 10001;
var optKey = 'updateUser';
var mapping = {optKey:updateUer}; // key 函数映射
opt.mapping = mapping;
opt.client = dbclient;
opt.interval = 2000;
var sync = new Sync(opt) ;
sync.exec(optKey,id,{name:'hello'});
3. pomelo-sync模块API
exec
sync.exec(key, id, val, cb)
添加一个对象,以便同步执行计时器调用
参数
key- 要调用的键-函数映射,必须唯一id- 合并操作的对象主键val- 要同步的对象cb- 计时器执行时调用的回调函数
flush
sync.flush(key, id, val, cb)
立即将内存数据与备用计时器同步,并删除等待队列中的数据
参数
key- 要调用的键-函数映射,必须唯一id- 合并操作的对象主键val- 要同步的对象cb- 计时器执行时调用的回调函数
isDone
sync.isDone()
获取同步状态。当队列空时,返回true;其它情况返回false。
参数
4. 注意事项
系统默认的同步时间为1分钟(1000 * 60)。默认的同步方式是文件同步,如果要使用MySQL或redis,则需要通过options.client来设置。
pomelo-sync模块不支持MySQL对象关系映射(ORM),如果要使用ORM需要自行实现。
5. pomelo-sync-plugin
pomelo-sync被实现为一个Pomelo组件。除此之外,Pomelo还提供了pomelo-sync-plugin,它是基于pomelo-sync实现的一个Pomelo 插件。
可以通过npm安装这款插件:
npm install pomelo-sync-plugin
安装后,可以像下面这样使用:
// app.js
var sync = require('pomelo-sync-plugin');
// ...
// Configure database
app.configure('production|development', 'area|auth|connector|master', function() {
var dbclient = require('./app/dao/mysql/mysql').init(app);
app.set('dbclient', dbclient);
app.use(sync, {sync: {path:__dirname + '/app/dao/mapping', dbclient: dbclient}});
});
// ...
"/app/dao/mapping"路径下的所有js文件都会被加载到pomelo-sync中,这些模块中定义了需要定时执行的持久化操作。
示例如下:
// pomelo-sync-plugin/node_modules/pomelo-sync/lib/dbsync.js
var DataSync = module.exports = function(options) {
// ...
this.mapping = this.loadMapping(options.mappingPath);
// ...
};
x. pomelo-sync-redis
pomelo-sync-redis基于pomelo-sync修改而来,并实现了同样的功能,二者不同点在于:
pomelo-sync使用JavasSript对象来合并数据,pomelo-sync-redis使用Redis Hash来合并数据。pomelo-sync使用一个自实现的队列来存储刷新数据,而pomelo-sync-redis使用Redis Set来存储刷新数据。- 每个
pomelo-sync实例都会执行同步作业,pomelo-sync-redis也可以设置用于执行作业的实例,且这些实例像pomelo-sync一样可以添加作业。 - 每个
pomelo-sync实例不会与其它实例共享数据,而pomelo-sync-redis可以通过Redis与其它实例共享和合并数据。 pomelo-sync-redis可以即时清除mergerMap部分中的数据(通过flushByUid方法)。
pomelo-sync-redis和pomelo-sync一样,是一个Pomelo组件。如果要以插件形式使用它,那么可以使用pomelo-sync-redis-plugin
x. pomelo-sync-redis的使用
使用pomelo-sync-redis前先通过npm命令安装:
npm install pomelo-sync-redis
安装可以像下面这样使用pomelo-sync-redis:
var opt = opt || {};
var updateUser = function(dbclient,val) {
console.info('mock save %j',val);
}
var dbclient = {};//db connection etc;
var id = 10001;
var optKey = 'updateUser';
var mapping = {optKey:updateUer}; //key function mapping
opt.mapping = mapping;
opt.client = dbclient; // store engine client
opt.interval = 2000; // exec sync interval
opt.port = 6379; // redis server port
opt.host = "127.0.0.1" // redis server ip
var redisKeys = {
MERGER_MAP_KEY: "POMELO:SYNC:MERGER:MAP",
USER_SET_KEY: "POMELO:SYNC:%s:SET",
FLUSH_SET_KEY: "POMELO:SYNC:FLUSH:SET"
} // keys will used in redis
opt.keys = keys
opt.isSyncer = true // if ture, this pomelo sync instance will execute sync job at interval, default is false. At least one pomelo-sync-redis is set to syncer !!
var Sync = require('pomelo-sync-redis');
var sync = new Sync(opt) ;
sync.exec(optKey,id,{name:'hello'});
而pomelo-sync-plugin的用法类似如下:
var sync = require('pomelo-sync-plugin');
//app.js
app.use(sync, {sync: {
path: __dirname + '/app/dao/mapping', dbclient: mongoClient,
port: 6379, //default is 6379
host: "127.0.0.1" //default is 127.0.0.1,
interval: 100000,
isSyncer: true, // default is false
keys:{
MERGER_MAP_KEY: "POMELO:SYNC:MERGER:MAP", //key of mergerMap in redis
USER_SET_KEY: "POMELO:SYNC:%s:SET", //key of user set, it is a key format
FLUSH_SET_KEY: "POMELO:SYNC:FLUSH:SET" //key of flushQueue in redis
}
}});
x. pomelo-sync-redis的API
sync.exec(key,uid,id,val,cb)
添加一个需要同步的对象到定时器
参数:
key- 要调用的键-函数映射,必须唯一uid- 一个用于标识数据分组的ID。[可选]id- 合并操作的对象主键val- 要同步的对象cb- 计时器执行时调用的回调函数。[可选]
sync.flush(key,uid,id,val,cb)
不通过定时器立即同步存储器数据,并移除等待队列中的数据
参数:
key- 要调用的键-函数映射,必须唯一uid- 一个用于标识数据分组的ID。[可选]id- 合并操作的对象主键val- 要同步的对象cb- 计时器执行时调用的回调函数。[可选]
sync.isDone()
当队列到数据库的同步状态。如果队列为空则true,否则返回false
sync.flushByUid(uid,cb)
立即将通过exec方法的uid参数添加的内存数据同步到数据库,而不等待定时器,并将数据从等待队列中删除。
uid- 在exec和flush方法中使用的uidcb- 同步作业完成时的回调函数(这个模块不支持,需要用户自己实现)
