故事背景,接手了一个烂代码,合服的时候大量id重复。你说改了id合服不就完事了吗,有那么简单吗。比如道具id重复,你把道具表的id改了,但是其他表用了道具id,其他表你也要改。如果其他表用的道具id不是单独一个字段,是一个复杂的数据呢,你怎么改。你无法通过数据库直接改。。我奇怪的是他用了长度19位,float都装不下这么长的数据,居然重复的。。。
贴源码
UINT64 TwitterSnowflake::GenerateUnique()
{UINT64 id = 0;UINT32 nowMsec = GetCurrentTimeMsec() / 1000; //修成秒id = (UINT64)nowMsec << 32;//中间m_machineIdBits位是机器IDid |= (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位。