六位不重复房间ID生成器,不使用Redis和额外数据结构
使用场景:
为玩家创建的多人游戏对战房间生成唯一的六位房间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和额外数据结构相关推荐
- java redis id生成器_基于redis的分布式ID生成器
项目地址 基于redis的分布式ID生成器. 准备 首先,要知道redis的EVAL,EVALSHA命令: 原理 利用redis的lua脚本执行功能,在每个节点上通过lua脚本生成唯一ID. 生成的I ...
- 分布式数据库id生成器的技术选型
分布式数据库id生成器的技术选型 一. 数据库自增主键 二.UUID 三.数据库或者Redis生成ID 五.雪花算法 六.LEAF 七.案例 注:本文部分内容为转载,加入自己的理解及资料 作者:晚歌y ...
- SnowFlake唯一ID生成器
写在前面 架构是权衡的结果,架构也是一层层的组件拼接起来的,如果没有好用的组件,架构势必会做阉割,架构的理想态是建立在一堆友好.易用.标准化的组件之上的.在我过去的经验中,有两类组件经常会出现在我的架 ...
- im即时通讯源码_IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)
1.引言 在中大型IM系统中,聊天消息的唯一ID生成策略是个很重要的技术点.不夸张的说,聊天消息ID贯穿了整个聊天生命周期的几乎每一个算法.逻辑和过程,ID生成策略的好坏有可能直接决定系统在某些技术点 ...
- c#分布式ID生成器
c#分布式ID生成器 简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63 ...
- 分布式ID生成器(来源:架构师之路,2017-06-25 58沈剑 架构师之路)
一.需求缘起 几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如: 消息标识:message-id 订单标识:order-id 帖子标识:tiezi-id 这个记录标识往往就是数据库中的主键,数 ...
- 分布式唯一ID生成器
在应用程序中,经常需要全局唯一的ID作为数据库主键.如何生成全局唯一ID? 首先,需要确定全局唯一ID是整型还是字符串?如果是字符串,那么现有的UUID就完全满足需求,不需要额外的工作.缺点是字符串作 ...
- 雪花算法之唯一ID生成器理解
雪花算法基本情况 雪花算法是一个分布式的唯一ID生成器. 它应该具有高并发,以及高性能优点. 基于时间戳,ID具有有序性,同时分布式下机器间时间差异过大(类似同一台机器时间回拨,一定会重复),会导致重 ...
- 融云发送图片消息_IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现...
1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...
最新文章
- 编写一个函数进行左移或右移的位运算
- [转]七大.NET开源框架
- c 嵌入html5 win7,Html5新标签解释及用法
- python编程题-python编程练习题
- sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)
- Perturbed Masking:和参数无关的预训练模型分析方法
- linux 编译git 客户端源码然后安装
- Oracle密码过期问题 ORA-28001:the password has expired
- Semantic Element
- linux自学(四)之开始centos学习,网络配置
- java多线程编程相关技术
- [补档]noip2019集训测试赛(十)
- Unity采用Forge Networking Remastered数据的远程传输 Basic RPC Example
- 杨咩咩的编程求学之路之开篇
- xmlDocument是什么?(转)
- 车载TBOX,4G北斗/GPS双模定位
- 秒数转换为天小时分钟秒的格式
- python给矩阵赋值_python – 基本Numpy数组值赋值
- web连接mysql教程视频_jsp servlet mysql实现的Java web在线商城项目源码附带视频指导运行教程...
- BFS——1253 胜利大逃亡
热门文章
- 手机在信号好的地方一直无服务器,解决手机信号不好的几种方法
- linux重新初始化网络命令,如何在Ubuntu 18.04 Bionic Beaver Linux上重新启动网络
- NVIDIA Tesla GPU系列P4、T4、P40以及V100显卡性能的对比
- 参加国企面试需要注意的点有哪些?
- 已设置过微信号怎么改?新版微信已经支持这个功能!
- Anaconda 修改默认虚拟环境安装位置
- poco for android,POCO桌面(com.mi.android.globallauncher) - 2.6.8.25 - 应用 - 酷安
- wavplay控件应用之SigmaStudio
- AE学习02:时间轴
- oracle中的存储过程是什么,oracle存储过程是什么?