设计上:
(1)存档方式
定时器在一定范围的分钟内随机存档一次,为了避免集中式存档
第一次需要全部存档一次,因为需要存档版本字段
分标签实时存档设置了标签的数据,减少每次存档数据
(2)压缩处理
档案消息中的角色二进制数据是经过zlib算法压缩处理的,减少每次存档数据
被压缩数据也以压缩形式的二进制存入数据库mysql,在读档案到场景服务器中才会解档
(3)角色属性数据
关键性角色属性数据没有进行压缩处理,以明文方式写入数据库,可直接查询
1、存档方式
在场景服务器:
定时器在一定范围的分钟内随机存档一次。
第一次需要全部存档一次,因为需要存档版本字段。
分标签实时存档设置了标签的数据。
场景服务器循环
if (_write_record_timer(main_logic_thread::currentTime))
{
//随机时间存档
save(MSG::DB::WRITEBACK_TIMETICK);
first_save = true;
}
else
{
if(!first_save)
{
save(MSG::DB::FIRST_SAVE);//第一次全部内容存档
first_save = true;
}
else
{
operation_save(); //实时标签存档
}
}
2、场景服务器档案处理
(1)存档
序列化一个用户的所有存档数据
struct SerializeRoleData
{
SerializeRoleData()
{
size = 0;
}
RoleData roledata;//角色属性
uint32 size;
char data[0];//其他数据
};
全部内容存档
bool scene_player::save(MSG::DB::WriteBack_Type type)
{
update_roledata(type);
BUFFER_CMD(MSG::DB::stWriteplayerRoleDataRecordCmd,send,UNZIP_BINARY_SIZE);
send->writeback_type = type;
send->charid = id;
SerializeRoleData *sall = (SerializeRoleData*)(&send->data);
constructInPlace(sall);
sall->size = 0;
5 种类型的存档
bcopy(&roledata, &sall->roledata, sizeof(sall->roledata));
other_serialize((char*)(&(send->data.data[0])), send->data.size);
money_serialize((char*)(&(send->data.data[0])), send->data.size);
task_serialize((char*)(&(send->data.data[0])), send->data.size);
item_serialize((char*)(&(send->data.data[0])), send->data.size);
dbClient->sendmsg(send, sizeof(MSG::DB::stWriteplayerRoleDataRecordCmd) + send->data.size);
///清除存档标签
clear_save_tag();
//g_log->debug("角色二进制存档数据:%u", send->data.size);
return true;
}
标签内容存档
void scene_player::operation_save()
{
if(0 != this->save_tag )
{
if((this->save_tag & (1<<SAVE_ROLE_DATA))) ///有roledata更新的情况
{
update_roledata(MSG::DB::WRITEBACK_OPERATION);
BUFFER_CMD(MSG::DB::stWriteplayerRoleDataRecordCmd,send,UNZIP_BINARY_SIZE);
send->writeback_type = MSG::DB::WRITEBACK_OPERATION;
send->charid = id;
send->save_tag = this->save_tag;
SerializeRoleData *sall = (SerializeRoleData*)(&send->data);
constructInPlace(sall);
sall->size = 0;
bcopy(&roledata, &sall->roledata, sizeof(sall->roledata));//角色属性存档
if(this->save_tag & (1<<SAVE_ITEM))//道具存档
{
item_serialize((char*)&sall->data, sall->size);
}
if(this->save_tag & (1<<SAVE_TASK))//任务存档
{
task_serialize((char*)&sall->data, sall->size);
}
if(this->save_tag & (1<<SAVE_MONEY))//金钱存档
{
money_serialize((char*)&sall->data, sall->size);
}
if(this->save_tag & (1<<SAVE_OTHER))//其他存档
{
other_serialize((char*)&sall->data, sall->size);
}
dbClient->sendmsg(send, sizeof(MSG::DB::stWriteplayerRoleDataRecordCmd) + send->data.size);
}
else //没有roledata
{
BUFFER_CMD(MSG::DB::stNewSaveBinaryCmd,send,UNZIP_BINARY_SIZE);
send->charid = id;
send->save_tag = this->save_tag;
if(this->save_tag & (1<<SAVE_ITEM)) 二进制压缩道具数据
{
item_serialize((char*)&send->data, send->size);
}
if(this->save_tag & (1<<SAVE_TASK)) ///二进制压缩任务数据
{
task_serialize((char*)&send->data, send->size);
}
if(this->save_tag & (1<<SAVE_MONEY)) 金钱(不进行zlib压缩)存档
{
money_serialize((char*)&send->data, send->size);
}
if(this->save_tag & (1<<SAVE_OTHER)) 其它二进制存档
{
other_serialize((char*)&send->data, send->size);
}
dbClient->sendmsg(send, sizeof(MSG::DB::stNewSaveBinaryCmd) + send->size);
}
clear_save_tag();///清除存档标签
}
}
道具存档
bool scene_player::item_serialize(char *pdata, uint32 & cursor)
{
char* data = pdata;
char temp[UNZIP_BINARY_SIZE];//存档缓冲区
bzero(temp,sizeof(temp