游戏中的唯一id生成,防止合服id重复
故事背景,接手了一个烂代码,合服的时候大量id重复。你说改了id合服不就完事了吗,有那么简单吗。比如道具id重复,你把道具表的id改了,但是其他表用了道具id,其他表你也要改。如果其他表用的道具id不是单独一个字段,是一个复杂的数据呢,你怎么改。你无法通过数据库直接改。。我奇怪的是他用了长度19位,float都装不下这么长的数据,居然重复的。。。
贴源码
UINT64 TwitterSnowflake::GenerateUnique()
{
UINT64 id = 0;
UINT32 nowMsec = GetCurrentTimeMsec() / 1000; //修成秒
id = (UINT64)nowMsec << 32;
//中间m_machineIdBits位是机器ID
id |= (UINT64)(m_machineId & (m_maxMachine - 1)) << m_sequenceBits/*15*/;
//最后m_sequenceBits位序列号
CXTAutoLock lock(m_locker);
if (nowMsec < m_lastStamp)
{
id = 0;
//ASSERT(false);
}
else if(m_lastStamp == nowMsec)
{
int m_sequence_old = m_sequence;
m_sequence = ((m_sequence + 1) & (m_maxSequence - 1));
if (m_sequence == 0)
{
printf("%d %d %d %d\n", nowMsec, m_lastStamp, m_sequence, m_sequence_old);
nowMsec = WaitNextSec();
}
}
else
{
m_sequence = 0;
}
id |= m_sequence;
//TODO
/*static std::map<INT64, INT32> record;
static std::map<INT64, INT32> recordTime;
auto it = record.find(id);
if (it != record.end())
{
++it->second;
printf("%d %d %d id = %lld 重复次数 %d %d \n", nowMsec, m_lastStamp, recordTime[id], id, it->second, m_sequence);
}
else
{
record[id] = 1;
recordTime[id] = nowMsec;
}*/
m_lastStamp = nowMsec;
//printf("%d %d %d id = %lld %d \n", nowMsec, m_lastStamp, recordTime[id], id, m_sequence);
return id;
}
生成出来大概是这样的 7293710237208084482,这么TM的大,lua的float都装不下.难受的是不同服生成出来的id,肉眼可见的回重复。
我改成了服务器id拼时间,然后自增。
void TwitterSnowflake::SetMachineId(int id)
{
m_machineId = id;
m_id = m_machineId * 10000000000 + time(NULL);
}
UINT64 TwitterSnowflake::GenerateUnique()
{
return m_id++;
}
比如1011服,生成的id 101111726036456
1011是服务器id,1是进程id,后面是时间。服务器id4位,进程id 1位,时间10位,一共长度15位。