作为页游,基于用户的导入时间,以及服务器的压力问题,不可避免的要求分区。
然后随着时间推移,游戏的玩家也会渐渐的流失,为了游戏的活跃,合服也变得必不
可少了,这个时候,我们数据库里面的各项id如果还是用数据库自己提供的自增id的话,
合服的时候将是一件很蛋疼的事情,至少我们以前的游戏就是这么干的,然后还不得
专门开发一个合服工具去处理这些玩家数据,重新生成玩家id,物品id,物品的拥有者id等。
这将导致合服的过程大大增加,我们一次合服大概要2-3个小时。
为了能在合服的时候尽量减少对数据的修改,我们特意更改了我的id生成策略,不再
使用数据库自增id,而是应用一个__int64表示我们的id(AABBBBCCCCCCCC) AA表示平台,
BBBB表示服务器,CCCCCCCC为自增id.这样在合服的时候,就不再会有数据的冲突问
题了,表数据直接合并就好了。但是我们要怎么维护这样的数据呢?合服之后的自增id会
不会有问题呢?下面就是我们构思的id管理器
首先我们要把我们的不同的id进行分类,比如
enum IDTYPE
{
IDTYPE_NONE = 0,
IDTYPE_USERID = 1,//玩家id
IDTYPE_ITEMID = 2,//玩家物品id
.........
}
然后每一个类型对应下面结构的的信息
struct IDTYPEINFO
{
int nType;
NAMESTR szTblName;
NAMESTR szIdName; // 数据库ID字段的名称
int nMin; // id的原始最小值
};
定义一个ID分配类
class CIDAllocator
{
public:
bool Create(const IDTYPEINFO& info);
OBJID GenNewID(int nPlatAndServer);
private:
typedef std::map<int/*plat & server*/, int/*最大自增ID*/> IDGEN_SET;
IDGEN_SET m_setIDGen;
IDTYPEINFO m_info;
};
注意我们的create函数是基于const IDTYPEINFO& info的,即在我们的游服里面,每一个不同类型
的IDTYPE都会有一个对应的CIDAllocator的对象,而在我们对象里面,有一个hashmap存储的是
m_setIDGen[AABBBB] = AABBBB服务器当前id类型最大自增ID,生成这个map的方式很简单,在
起服的时候"select floor(id/100000000),max(id) from user group by floor(id/100000000)"就能获取
到我们需要的数据了。
而当我们需要生成新的id的时候,调用GenNewID(AABBBB); return ++m_setIDGen[AABBBB] 就
是了。
这样我们某一类的ID管理器就好了,如果我们把游服所有的id信息如下
static IDTYPEINFO aryIDTypeInfo[] = {
{IDTYPE_MAGIC, _TBL_MAGIC, "id", 1},
{IDTYPE_USERTASK, _TBL_USERTASK, "id", 1},
}
预先注册,那么就可以弄一个管理器管理游服所有的id类型了。
idItem = IDAllocatorMgr()->AllocID(IDTYPE_ITEMID , m_pOwner->GetPlatAndServer());