twitter snowflake 全局唯一ID算法
研发页游时,经常需要合服,每次合服,最浪费时间的就是重复ID的合并,后来,渐渐的有人用了各个大区集中到ID分配节点上获取一定量的ID,来分配。对于ID分配节点来说,有一定的单点风险。对于使用这些预约的ID,每次关服,开服都需要重新存储,加载剩余的可用ID个数,位置等等,还挺麻烦。
最近做不分区的游戏,发现了Twitter的分布式唯一ID生成算法snowflake,发现不光在不分区的分布式游戏节点上用合适,也可以用在分区分服的传统页游、手游上。
1,符号位不用,JAVA类语言不好处理,跟其他平台对接时会带来麻烦
2,范围为39bit,当前时间戳-开服时间戳(比如20150916,写死在代码里,不可以配置)的差值,1<<39 -1 = 17.4年。可用17年的ID,我觉得38bit ,可以实现8.7年 的存储,足够一个游戏的生命周期了。
3,10bit,服务器ID,最大值1023,可以支持开到1000多个服。(游戏太火,1000多不够?这么火的游戏,正好上面时间戳差值可以节省1个bit,够开2047个服了。还不够?那下面两个想着省点呗)
4,4bit,每个服的节点(或线程)ID,最大值15。一般,需要开这么线程才能处理完的业务量时,都会再开新服了,15个用不完的。还不够的话,下面的自增序列肯定用不完,可以拿个过来。
5,10bit,自增序列最大值为 1023,每毫秒内可产生1023个不重复ID供使用,每秒100W个不重复ID。角色ID自增,以及道具、建筑ID自增,建议每个业务都用自己的一个ID生成器,不要共用同一个。每个游戏进程按照QPS为1W来算,一个请求注册1个用户的话,实际用到的每秒1W即可。若用于道具ID生成,每个查询会生成10个来算,每秒可生成10W即可。也就是说 自增序列占7bit即可,其余3个可分配到其他存储位置上。
这么分配ID的话,以后合服只需要直接合并导入数据,不用担心ID重复的问题了。
Golang语言版的gosnowflake : https://github.com/Terry-Mao/gosnowflake/blob/master/id.go
PHP版的IDWork: https://github.com/zhouyuan24/IDWork/blob/master/idwork.php
JAVA版的 idcenter:https://github.com/adyliu/idcenter/blob/master/src/main/java/com/sohu/idcenter/IdWorker.java