1、什么是雪花算法?
雪花算法(Snowflake)是一种生成唯一ID的算法。在游戏开发过程中会为玩家生成唯一的id,或者玩家获得一件装备,为这件装备生成唯一的Id,将此角色和装备的Id保存于数据库当中。
-
全局唯一性
- 不能出现有重复的ID标识,这是基本要求。
-
递增性
- 确保生成ID对于用户或业务是递增的。
-
高可用性
- 确保任何时候都能生成正确的ID。
-
高性能性
- 在高并发的环境下依然表现良好。
2、雪花算法是怎么实现的?
这里以ET框架中的 ActorId 举例子,id 总长度为 64位,其中总共分为了四个部分,分别占用:
- 时间:30位 最大可表示时间为34年
- 区服Id: 10bit 最大可以表示1024个区服
- 进程数:8bit 最大可以表示250个进程
- 单元数量:16bit 最大可以表示 16k个单元
以上的各个占位数可以根据项目中的需求自行调整,并非说只能这么表示。
3、如何将代表各个部分的值转化为 64位的Id?
-
位或 “|” 运算符
Debug.Log(12 | 5); //输出 13
可以看出两个二进制没一位之间进行“|”运算 只要有一个为 1,那么结果就为 “1”
-
“<<” 与 “>>”运算符
Debug.Log(5 << 2); //返回值3
“<<”运算符执行左移位运算。在移位运算过程中,符号位始终保持不变。如果右侧空出位置,则自动填充为 0;超出 32 位的值,则自动丢弃。
可以看出5右移2位,则在 5的二进制 右边补充两个00,左边则去掉2位
那么左移就正好相反 那 1000 >> 8 举例,在左边补充8个0,右边去掉8位
Debug.Log(1000 >> 8); //返回值3
介绍完上面需要使用的运算符,我们就可以很简单的实现代码:
public struct UnitIdStruct{public uint Time; // 30bit 34年public ushort Zone; // 10bit 1024个区public byte Process; // 8bit Process % 256 一个区最多256个进程public ushort Value; // 16bit 每秒每个进程最大16K个Unitpublic long ToLong(){ulong result = 0;result |= this.Value;result |= (ulong)this.Zone << 16;result |= (ulong)this.Process << (16 + 8);result |= (ulong)this.Time << (16 + 8 + 10);return (long)result;}public UnitIdStruct(int zone, int process, uint time, ushort value){this.Zone = (ushort)zone;this.Process = (byte)(process % 256);this.Time = time;this.Value = value;}public UnitIdStruct(long id){ulong result = (ulong)id;this.Value = (ushort)(result & ushort.MaxValue);result >>= 16;this.Process = (byte)(result & byte.MaxValue);result >>= 8;this.Zone = (ushort) (result & 0x03ff);result >>= 10;this.Time = (uint)result;}}