游戏后台生成唯一ID

  MMO游戏后台通常需要由大量服务器来共同承载海量玩家,虽然玩家可能分布在不同的游戏大区,但是他们可能会通过跨服等等方式进行各种交互。游戏中的角色,装备,物品等需要生成一个全局唯一ID标识,便于辨别不同玩家,不同装备,也方便定位外网问题。

  常见的分布式全局唯一ID生成方式包括使用数据库自增,使用Redis的原子操作INCR和INCRBY,使用UUID,SnowFlake算法等等。前面两种方式均需要产生一次异步调用,在MMO中,海量玩家会集中在一个场景中进行PK,做任务,打怪等,场景内业务逻辑复杂,为了降低编码复杂度,减少BUG几率,通常会选择使用本地算法来生成全局唯一ID。

  UUID方式生成的ID比较长,通常需用字符串表示,作为内存数据主键或者数据库主键它的查找效率比不上直接使用整数类型生成的ID做主键。同时它对业务来说是一串无规则的字符串,不能根据相关业务规则进行调整。

  SnowFlake算法是开源的分布式生成算法,它是一个本地生成算法,它可以生成一个位的整数,具体生成的位结构如下图:

  SnowFlake算法12位序列号支持一个节点同一毫秒内产生4096个ID,一秒内可以产生400多万个UID,其41位的时间戳可以使用69年。

  下面讲述一种MMO中的分布式ID生成方式,它会生成一个64位的整数ID,核心思想与SnowFlake类似。同时会根据游戏的特性对64位ID中的位段进行相应的调整。在游戏部署上,我们会根据进程所在不同大区,不同功能,不同机器给线上部署的进程分配一个唯一的进程业务ID,这个进程业务ID的格式如下:WorldID.ZoneID.FuncID.InstID。

根据游戏进程部署的特点,产生了下面这种64位ID的通用结构:

具体字段含义如下:
大区号: 游戏中的分区

虚拟机器号: 一个小区内的机器虚拟编号

功能号: 不同类型的进程的功能编号,比如排行榜进程和组队进程功能号不一样

实例ID: 同一类型的进程的不同实例编号

校验序号: 这个序号在每次进程重启时就自增1,数据会写入本地文件中

序列号: 同一时间内生成ID会自增序列号

自适应时间: 进程启动时初始化为当前时间的时间戳(秒级别的)

  大区号,虚拟机器号,功能号,实例ID的位数通常根据不同类型的游戏特点进行调整。比如分区分服的游戏,大区很多,那么大区号位数会比较长,而一个区内机器数比较少,那么虚拟机器号分配的位数比较少。而对于全区全服的游戏,甚至可以把大区号与虚拟机器号合并成一个段。

  下面以校验序号为2位,序列号位12位,自适应时间为29位来说明一下这个UID的生成方式。

  大区号,虚拟机器号,功能号和实例ID部署时就已经固定好了。校验序号在进程每次启动时自增1并写入本地文件中,自适应时间在每次进程启动时,初始化为当前时间的时间戳(秒级别的)。

  在单个UID生成过程中,序列号,自适应时间变化规则伪代码如下:

uint64_t CreateUID(){... // 省略部分代码## 标题dwLoopSeq++;if(dwLoopSeq == 0) {dwAdapativeTime++;}... // 省略部分代码
}

问题一:由于序列号只有12位,一秒内一个进程最多产生4096个UID,如何解决一段时间内UID生成突增的情况?
  如果在一些突发情况下,一秒内产生的UID超过4096个,那么自适应时间会自增1,相当于提前消费下一秒可产生的UID,通过这种提前消费的方式可以满足某些时间点UID突增的情况。
  另外,如果一些时间点产生的UID比较少,那么自适应时间慢于当前时间,也会累计一些逝去的时间用于未来某个时间点UID突增的情况。

问题二:如果自适应时间已经超前当前时间,进程又重启了,自适应时间又倒退到当前时间,会不会导致UID重复?
  在每次进程重启时,校验号都会自增1,因此两次启动中,校验序号是不一样的。另外这种方式生成的UID通常用于角色ID,物品ID等,单秒内生成量是可以预估的,从而事先调整UID的各个段的位数来满足业务需求。
  在实际运行中,通常也会对自适应时间超前进行监控,当遇到这种情况时,避免进程的频繁重启,随着时间的流逝,自适应时间会慢慢靠近当前时间。

游戏后台生成唯一ID相关推荐

  1. 生成唯一字符串算法_面试官问:在分布式场景,生成唯一ID,你有几种方案?...

    来源:http://t.cn/RG0AW0a 说明:本文代码采用C#,重要的是理解解决方案,代码实现都是次要的. 系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结.生成I ...

  2. php给留言分配id_如何使用php生成唯一ID的4种方法

    php生成唯一ID的应用场景非常普遍,如临时缓存文件名称,临时变量,临时安全码等,uniqid()函数基于以微秒计的当前时间,生成一个唯一的 ID.由于生成唯一ID与微秒时间关联,因此ID的唯一性非常 ...

  3. 根据twitter的snowflake算法生成唯一ID

    C#版本 /// <summary>/// 根据twitter的snowflake算法生成唯一ID/// snowflake算法 64 位/// 0---0000000000 000000 ...

  4. php生成不重复时间戳,PHP获取时间戳和微秒数以及生成唯一ID

    microtime函数 描述:返回当前Unix时间戳和微秒数 语法:mixed microtime( [ bool $get_as_float ] ) //直接输出 echo microtime(); ...

  5. php生成游客id_PHP生成唯一ID 公认较为安全的写法 上传随机文件名

    PHP生成随机文件名有多种方式,本次介绍一个在公认比较新.比较安全的随机ID函数.较老的方式一般单一使用rand函数生成随机数字,或者用md5,或者进一步使用uniqid()函数,但不论以上哪种方式, ...

  6. Android View 生成唯一 Id

    Android View 生成唯一 Id 可以使用 Hook LayoutInflater 的方法替换 SystemService 原有的 LayoutInflater,在自定义的 LayoutInf ...

  7. JS生成唯一id方式介绍(UUID和NanoID)

    记录下JS生成唯一id的方法. 1.生成uuid的方法 方法一: function guid() {return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.repl ...

  8. java唯一id_生成唯一ID的四种办法 程序员必备

    我们在实际编程过程中会经常遇到需要用唯一ID的场合,这些唯一ID还会存到数据库中以便于我们将来进行查询. 例如用户编号.订单编号.客户编号等等,几乎凡是需要用来严格划分用户数据归属性的地方就需要用到唯 ...

  9. JavaScript 生成唯一ID的几种方式

    这篇文章主要介绍了JavaScript 生成唯一ID的几种方式,帮助大家更好的理解和使用JavaScript,感兴趣的朋友可以了解下. 编程的世界里,在很多的时候,我们都需要一个唯一的ID来代表一些数 ...

最新文章

  1. ffmpeg 编译Android
  2. 【ACM】杭电OJ 2036(待更)
  3. 又美又飒!这位985大学小姐姐,堪称今年最强博士后!
  4. IBM超越谷歌抵达量子计算里程碑:研制出50量子位计算机
  5. java Runtime.getRuntime().exec 获取反弹shell
  6. 调试node服务器-过程
  7. jquery通过数值改变球大小
  8. 神经网络可视化,真的很像神经元!
  9. python亲密度_859. 亲密字符串(Python)
  10. Java加密与解密的艺术~安全协议~单向认证服务
  11. Python超越R,为何Python攀上数据科学巅峰?
  12. HDR Tone Mapping
  13. 1908元?iPhone SE 3价格大幅下调,网友:这个价格我冲了
  14. Android_撕衣服小案例
  15. 凸优化第四章凸优化问题 4.5几何规划
  16. 【Opencv】 于仕琪 人脸68个特征点分布情况
  17. speex回声消除源码解读
  18. 入浅出JMS(三)--ActiveMQ简单的HelloWorld实例
  19. 深度学习面试100题
  20. 抓取scrapy中文文档(我的第一个爬虫)

热门文章

  1. Android studio无法连接识别检测各种模拟器和手机的问题
  2. 服务器中内存不够的原因
  3. 随笔 | “郑秋冬”随想
  4. 2020年史上最全移动端Web整理从开发基础到实战(三)
  5. 数据科学家处理小数据的7个技巧。
  6. 职场神攻略:5分钟自我介绍法 快准狠!
  7. Sun Solaris系统管理命令简介
  8. 大学生web前端期末大作业实例代码 (1500套,建议收藏) HTML+CSS+JS
  9. STM32 - 使用FSMC控制LCD
  10. 二分算法。yxc教的