顾名思义,ekko是一个分布式唯一ID生成器,参考了snowFlake思想,但是并不局限于其设计。
英雄联盟的时间刺客ekko
- 易用,最大限度保证系统的易用性,支持Get与MultiGet;
- 高并发,单机每秒100w个唯一ID生成;
- 高可用,理论上没有强依赖任何其他服务;最多可拓展至达4096个物理机;且有生成ID的兜底方案;
- 多维度,支持机房级别、产品线级别区分;
- 不受时钟漂移影响,通过多种方式规避时钟漂移;
- 轻量级,支持多种方式分配WorkerID进行部署,总有一种方式适合你;
唯一ID是uint64类型,并保证ID在趋势上全局递增,其中:
39 bits: 从发布至今经历的毫秒数,系统可运行17年;
3 bits: 机房标识,可支持8个机房;
12 bits: 物理机workerID + 产品线,两者共占12bits,具体划分是可配置的。
- 产品线可以配置0-4bits, 0表示不区分产品线
- 剩余bits用于表示workerID,故可支持最多256~4096台物理机部署
10 bits:毫秒内并发计数,一毫秒内可支持1024个ID,即QPS = 1024*1000 约为 100W
|------------------------------------------------------------------------------|
| Ekko ID generator design |
|------------------------------------------------------------------------------|
| 64bits |
| : 39bits for timestamp |
| : 3bits for idc |
| : 8~12bits for workerID |
| : 0~4bits for products |
| : 10bits for currency |
|------------------------------------------------------------------------------|
| |
| @if 8bits for workerID |
| [.......................................][...][........][....][..........] |
| [ timestamp ][idc][workerID][prod][ currency ] |
| |
| @if 12bits for workerID, no product |
| [.......................................][...][........][....][..........] |
| [ timestamp ][idc][ workerID ][ currency ] |
| |
|------------------------------------------------------------------------------|
支持多种方式为物理机分配workerID:
- 手动分配;
- 基于mysql主键方式自动分配;
- 基于redis incrby方式自动分片;
- 基于etcd自动分配;
有两种手段共同判定时间漂移
- 本地共享内存:记录上次成功生成UID的时间戳+并发,下次生成UID的时间戳+并发必须比共享内存中的值大,否则不服务;
- 周期上报(default 3s):周期性将本地时间上报到mysql/redis/etcd
防止时间漂移主要依赖第一种手段;放在共享内存可以使得服务重启后数据也有效;
而第二种手段更多用于服务启动时检查,是否此时时间大于上次上报时间,以及是否与其他机器保持了合理的时间戳diff;
- 各模式的测试