使用场景:

为玩家创建的多人游戏对战房间生成唯一的六位房间ID,用户可邀请好友输入该ID来加入房间。

终极解决方案:

使用Redis的Set作为房间ID生成器,在初始化时向Set中插入100000~999999,在需要时使用SPOP随机弹出一个房间ID进行使用,在房间销毁时归还到Set中。

但是,如果系统中没有使用Redis怎么办?

基础实现:

使用Map维护正在使用中的房间ID,当玩家需要生成一个房间ID时通过随机算法当场生成,并与该Map做比对,检查是否已在使用,如已在使用则重新生成直到生成不重复的房间ID为止。在房间销毁时,移除Map中的房间ID。

随着使用中的房间数量的增加,随机算法碰撞率也会上升,可能导致客户端较长的等待才能拿到未使用的房间ID,此时可用反过来,在服务器中维护一个长度为100的简单队列,使用后台线程定该队列中塞入经过重复检测的房间ID,java和C#等可以使用BlockedQueue,go可以使用channel来实现。在反转后,客户端获取房间ID只是从队列中取出一个现成的,可以实现无等待获取。但如果仍然使用常规的随机算法,在生成数量较多后随机碰撞的问题仍未解决,将占用服务器大量资源。

队列ID生成器

使用长度为N的int数组和三个int值实现房间ID队列,可使用O(N)复杂度生成队列,并使用O(1)复杂度获取和归还ID。

package mainimport ("fmt""math/rand""sync""time"
)func init() {rand.Seed(time.Now().Unix())
}var (mx             = &sync.Mutex{}queue          = make([]int, 0, 900000)headPointer    = 0recyclePointer = 0usingCount     = 0
)func main() {initQueue()id, success := get()if !success {fmt.Println("当前已没有可供使用的房间ID")}recycle(id)
}func initQueue() {// 生成所有可用的数for i := 0; i < 900000; i++ {queue = append(queue, i+100000)}for i := 0; i < 900000; i++ {// 遍历所有位置,将其与后面的任意一个数交换位置randomIndex := i + rand.Intn(900000-i)queue[i], queue[randomIndex] = queue[randomIndex], queue[i]}
}func get() (roomId int, isSuccess bool) {// 多线程加锁mx.Lock()defer mx.Unlock()// 当所有ID都在使用中时,拒绝提供新IDif usingCount == 900000 {return 0, false}isSuccess = true// 取头指针对应的房间IDroomId = queue[headPointer]// 头指针后移一位headPointer++// 转了一圈后,返回队列头headPointer %= 900000// 使用中数量加一usingCount++return
}func recycle(recycleRoomID int) {// 多线程加锁mx.Lock()defer mx.Unlock()// 回收IDqueue[recyclePointer] = recycleRoomID// 回收指针向后移动一位recyclePointer++// 转了一圈后返回队列头recyclePointer %= 900000// 使用中数量减一usingCount--
}

其他闲话

  • 使用Queue、LinkedList等数据结构在理解和实现上更简单,但需要注意的是,这将为值类型的int包装上一层外部对象结构,导致内存效率和取用速度降低一个数量级。(当然,就这点数据量,还到不了讨论这种性能的地步)

六位不重复房间ID生成器,不使用Redis和额外数据结构相关推荐

  1. java redis id生成器_基于redis的分布式ID生成器

    项目地址 基于redis的分布式ID生成器. 准备 首先,要知道redis的EVAL,EVALSHA命令: 原理 利用redis的lua脚本执行功能,在每个节点上通过lua脚本生成唯一ID. 生成的I ...

  2. 分布式数据库id生成器的技术选型

    分布式数据库id生成器的技术选型 一. 数据库自增主键 二.UUID 三.数据库或者Redis生成ID 五.雪花算法 六.LEAF 七.案例 注:本文部分内容为转载,加入自己的理解及资料 作者:晚歌y ...

  3. SnowFlake唯一ID生成器

    写在前面 架构是权衡的结果,架构也是一层层的组件拼接起来的,如果没有好用的组件,架构势必会做阉割,架构的理想态是建立在一堆友好.易用.标准化的组件之上的.在我过去的经验中,有两类组件经常会出现在我的架 ...

  4. im即时通讯源码_IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)

    1.引言 在中大型IM系统中,聊天消息的唯一ID生成策略是个很重要的技术点.不夸张的说,聊天消息ID贯穿了整个聊天生命周期的几乎每一个算法.逻辑和过程,ID生成策略的好坏有可能直接决定系统在某些技术点 ...

  5. c#分布式ID生成器

    c#分布式ID生成器 简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63 ...

  6. 分布式ID生成器(来源:架构师之路,2017-06-25 58沈剑 架构师之路)

    一.需求缘起 几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如: 消息标识:message-id 订单标识:order-id 帖子标识:tiezi-id 这个记录标识往往就是数据库中的主键,数 ...

  7. 分布式唯一ID生成器

    在应用程序中,经常需要全局唯一的ID作为数据库主键.如何生成全局唯一ID? 首先,需要确定全局唯一ID是整型还是字符串?如果是字符串,那么现有的UUID就完全满足需求,不需要额外的工作.缺点是字符串作 ...

  8. 雪花算法之唯一ID生成器理解

    雪花算法基本情况 雪花算法是一个分布式的唯一ID生成器. 它应该具有高并发,以及高性能优点. 基于时间戳,ID具有有序性,同时分布式下机器间时间差异过大(类似同一台机器时间回拨,一定会重复),会导致重 ...

  9. 融云发送图片消息_IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现...

    1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...

最新文章

  1. 编写一个函数进行左移或右移的位运算
  2. [转]七大.NET开源框架
  3. c 嵌入html5 win7,Html5新标签解释及用法
  4. python编程题-python编程练习题
  5. sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)
  6. Perturbed Masking:和参数无关的预训练模型分析方法
  7. linux 编译git 客户端源码然后安装
  8. Oracle密码过期问题 ORA-28001:the password has expired
  9. Semantic Element
  10. linux自学(四)之开始centos学习,网络配置
  11. java多线程编程相关技术
  12. [补档]noip2019集训测试赛(十)
  13. Unity采用Forge Networking Remastered数据的远程传输 Basic RPC Example
  14. 杨咩咩的编程求学之路之开篇
  15. xmlDocument是什么?(转)
  16. 车载TBOX,4G北斗/GPS双模定位
  17. 秒数转换为天小时分钟秒的格式
  18. python给矩阵赋值_python – 基本Numpy数组值赋值
  19. web连接mysql教程视频_jsp servlet mysql实现的Java web在线商城项目源码附带视频指导运行教程...
  20. BFS——1253 胜利大逃亡

热门文章

  1. 手机在信号好的地方一直无服务器,解决手机信号不好的几种方法
  2. linux重新初始化网络命令,如何在Ubuntu 18.04 Bionic Beaver Linux上重新启动网络
  3. NVIDIA Tesla GPU系列P4、T4、P40以及V100显卡性能的对比
  4. 参加国企面试需要注意的点有哪些?
  5. 已设置过微信号怎么改?新版微信已经支持这个功能!
  6. Anaconda 修改默认虚拟环境安装位置
  7. poco for android,POCO桌面(com.mi.android.globallauncher) - 2.6.8.25 - 应用 - 酷安
  8. wavplay控件应用之SigmaStudio
  9. AE学习02:时间轴
  10. oracle中的存储过程是什么,oracle存储过程是什么?