Pomelo 数据同步模块 pomelo-sync


在游戏应用中,数据更新是非常频繁的。用户游戏数据像位置、装备等,会随着时间的变化而变化,为避免频繁的数据同步影响运行效率,我们一般会将数据保存在内存中,并通过定时器或其它方式持久化数据。pomelo-sync是Pomelo 提供的一个简单的数据同步模块,它可以将内存中的数据同步到mysqlredis文件等存储引擎中。

  1. pomelo-sync模块介绍
  2. pomelo-sync的使用
  3. pomelo-sync模块API
  4. 注意事项
  5. pomelo-sync-plugin

1. pomelo-sync模块介绍

pomelo-sync(Data sync)是一个简单的数据同步模块,它可以支持不同情况下的定时器调用或实例引用。pomelo-sync数据同步还支持内存操作,像redisMongoDB等NoSQL数据库,开发者就可以认为是一个没有事务的内存式数据库。

pomelo-sync支持的同步特性有timer syncsetgetmsetmgethsethgetincrdecrflushmergershowdowninfo等。


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)。默认的同步方式是文件同步,如果要使用MySQLredis,则需要通过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-redispomelo-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 - 在execflush方法中使用的uid
  • cb - 同步作业完成时的回调函数(这个模块不支持,需要用户自己实现)