分布式全局序列ID方案之Redis优化方案

1 Redis的Flicker方案 利用redis的lua脚本功能,在每个节点上通过lua脚本生成唯一ID,生成的ID为64位,具体如下: 使用41 bit来存放时间,精确到毫秒,可以使用到2039年 使用12 bit来存放逻辑分片ID,最大分片ID是4095 使用10 bit来存放自增长ID,则每个节点,每毫秒最多可生成1024个ID 比如GTM时间 2018年6月24日11点23分 ,它的距1970年的毫秒数是 1529810591000,假定分片ID是60,自增长序列是20,则生成的ID是: 6416490681073670164 = 1529810591000 << 22 | 60 << 10 | 20 redis提供了TIME命令,取得redis服务器的秒值和微秒值 毫秒值获取命令:EVAL "local current = redis.call('TIME') ;return a[1]*1000 + a[2]/1000" 0 生成最终ID : current << (12 + 10)) | (shardingId << 10) | seq 2 ID原子性自增方案 2.1 Redis HINCRBY 命令 Redis 的 INCR 命令支持 “INCR AND GET” 原子操作。利用这个特性,我们可以在 Redis 中存序列号,让分布式环境中多个取号服务在 Redis 中通过 INCR 命令来实现取号;同时 Redis 是单进程单线程架构,不会因为多个取号方的 INCR 命令导致取号重复。因此,基于 Redis 的 INCR 命令实现序列号的生成基本能满足全局唯一与单调递增的特性,并且性能还不错。

分布式全局序列ID方案之Flicker优化方案

1 Flicker的解决方案 MySQL中id自增的特性,可以借此来生成全局的序列号,Flicker在解决全局ID生成方案里就采用了MySQL自增长ID的机制(auto_increment + replace into + MyISAM)。一个生成64位ID方案具体就是这样的: 先创建单独的数据库,然后创建一个表: CREATE TABLE borrow_order ( id bigint(20) unsigned NOT NULL auto_increment, stub char(1) NOT NULL default '', PRIMARY KEY (id), UNIQUE KEY stub (stub) ) ENGINE=MyISAM 当我们插入记录后,执行SELECT * from borrow_order ,查询结果就是这样的: +-------------------+------+ | id | stub | +-------------------+------+ | 1 | 192.168.100.102 | +-------------------+------+ 在我们的应用端需要做下面这两个操作,在一个事务会话里提交: REPLACE INTO borrow_order (stub) VALUES ('192.168.100.102'); SELECT LAST_INSERT_ID(); 上述操作,通过 replace into 操作,首先尝试插入数据到表中,如果发现表中已经有此行数据则先删除此行数据,然后插入新的数据。 如果没有此行数据的话,直接插入新数据。注意:插入的行字段需要有主键索引或者唯一索引,否则会出错

分布式全局序列ID方案之Snowflake算法

1 背景 在分布式项目中,在业务数据中需要生成一个全局唯一的序列号,比如:消息标识,订单标识,用户标识等等。同时对于id生成的要求如下: * 全局唯一 * 趋势有序 * 主键索引 方便排序 * 高可用 * 高并发 2 基础方案 2.1 数据库主键自增 利用mysql的auto_increment特性 >优点: (1)能够保证唯一性 (2)能够保证递增性 (3)步长固定 缺点: (1)无法高可用:普通的一主多从+读写分离架构,自增ID写入请求,主库挂了就GG (2)无法高并发:写入是单点,数据库主库的写性能决定ID的生成性能上限,并且难以扩展 2.2 UUID uuid算法是比较常用的算法,根据UUID的特性,可以产生一个唯一的字符串 优点: (1)本地生成ID,无需远程服务调用,低延时 (2)扩展性好,基本可以-认为没有性能上限 缺点: (1)无法保证趋势递增 (2)uuid字符串过长,作为主键建立索引查询效率低,常见优化方案为“转化为两个uint64整数存储”或者“折半存储”(折半后不能保证唯一性) (3)如使用实现版本的=不一样,在高并发情况下可能会出现UUID重复情况 2.3 时间戳 优点: (1)本地生成ID,无需远程调用,低延时 (2)ID趋势递增 (3)ID是整数,建立索引后查询效率高 缺点: (1)如果并发量超过1000,会生成重复的ID 3 Twitter Snowflake 3.1 简介 snowflake是twitter开源的分布式ID生成算法,其核心思想是:一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号。这个算法单机每秒内理论上最多可以生成1000*(2^12),也就是400W的ID,完全能满足业务的需求 3.2 图示详解 (1)1位:标识部分,在java中由于long的最高位是符号位,正数是0,负数是1,一般生成的ID为正数,所以为0 (2)41位:时间戳部分,这个是毫秒级的时间,_一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间)_,这样可以使产生的ID从更小值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年