在高可用集群高并发场景下分布式全局唯一ID生成方案
前言 分布式全局ID的应用场景:
1、数据库的分表的主键ID生成方案
2、有些分布式部署、微服务等场景中,需要生成全局性的唯一ID
一、分布式ID生成规则硬性要求:
1、全局唯一:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。
2、趋势递增:MySQL中InnoDB引擎使用的是聚集索引。多数RDBMS使用Btree的数据结构来存储索引数据,在主键的选择上尽量选择有序的主键保证写入性能。
3、单调递增:保证下一个ID号一定大于上一个。
4、保证安全:ID号需要无规则性,不能让别人根据ID号猜出我们的信息和业务数据量,增加恶意用户扒取数据的难度。
5、含时间戳。
二、分布式ID生成可用性要求:
1、高可用:发布一个获取分布式ID的请求,服务器就要保证99.999%的情况下给创建一个全局唯一的分布式ID。
2、低延迟:发布一个获取分布式ID的请求,要快,急速。
3、高QPS:假如并发一口气10万个创建分布式ID请求同时杀过来,服务器要顶得住并且成功创建10万个分布式ID。
三、生成主键方案有哪些:
1、UUID。
2、数据库自增主键。
3、基于Redis生成全局ID策略。
4、雪花算法,Twitter的分布式自增ID算snowflake。
5、百度UidGenerator算法(基于雪花算法实现自定义时间戳)。
6、美团Leaf算法(依赖于数据库,ZK)。
四、各主键生成方案的优缺点:
1、UUID的优缺点:
优点:性能非常高,JDK自带本地生成,无网络消耗。
缺点:(1)只保证了唯一性,趋势递增。(2)无序,无法预测他的生成规则,不能生成递增有序的数字。(3)mysql官方推荐主键越短越好,UUID包含32个16位进制的字母数字,每一个都很长。(4)B+树索引的分裂。主键是包含索引的,mysql的索引是通过B+树来实现的,每一次新的UUID数据插入,为了查询优化,因为UUID是无序的,都会对索引底层的B+树进行修改。插入无序,不但会导致一些中间节点产生分裂,也会白白创造很多不饱和的节点,大大降低了数据库插入的性能。
2、数据库自增主键的优缺点:
优点:简单方便易用。
缺点:(1)要设置增长步长,系统水平扩展比较困难。(2)每次获取ID都得读写一次数据库,数据库压力大,非常影响性能,不符合分布式ID里低延迟和高QPS的规则。
3、基于Redis生成全局ID策略优缺点:
优点:满足分布式ID生成要求,并且已有最佳实践案例。
缺点:(1)要设置增长步长,同时key一定要设置有效期。(2)为了一个分布式ID,要搞一个Redis集群,维护成本大,当然若本身系统中有在使用Redis集群,生成ID只是顺带着还是比较方便的。
4、雪花算法,Twitter的分布式自增ID算snowflake优缺点:
优点:(1)经测试snowflake每秒能生成26万个自增可排序的ID。(2)snowflake生成的ID结果是一个64bit大小的整数,为一个Long型 (转换成字符串后长度最多19)。(3)分布式系统内不会产生ID碰撞(datacenter和workerId作区分)并且效率高。
缺点:严重依赖服务器时间,所以当发生服务器时钟回拨的问题是会导致可能产生重复的id。