All indexes other than the clustered index are known as secondary indexes. In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index.*** If the primary key is long, the secondary indexes use more space, so it is advantageous to have a short primary key***.
② 对MySQL索引不利:如果作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。
总之,UUID有很多合适的应用场景,但对于美团点评相关的业务系统来说,UUID显然不是最佳选择。
6、美团为什么不直接用Snowflake算法?
6.1SnowFlake算法原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。
这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 ID,12 bit 作为序列号。
SnowFlake的ID构成:
SnowFlake的ID样本:
给大家举个例子吧,如上图所示,比如下面那个 64 bit 的 long 型数字:
1)第一个部分,是 1 个 bit:0,这个是无意义的;
2)第二个部分,是 41 个 bit:表示的是时间戳;
3)第三个部分,是 5 个 bit:表示的是机房 ID,10001;
4)第四个部分,是 5 个 bit:表示的是机器 ID,1 1001;
5)第五个部分,是 12 个 bit:表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 ID 的序号,0000 00000000。
① 1 bit:是不用的,为啥呢?
因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 ID 都是正数,所以第一个 bit 统一都是 0。
对于MySQL性能问题,可用如下方案解决:在分布式系统中可以多部署几台机器,每台机器设置不同的初始值,且步长和机器数相等。比如有两台机器。设置步长step为2,TicketServer1的初始值为1(1,3,5,7,9,11…)、TicketServer2的初始值为2(2,4,6,8,10…)。这是Flickr团队在2010年撰文介绍的一种主键生成策略(详见:《Ticket Servers: Distributed Unique Primary Keys on the Cheap》)。如下所示,为了实现上述方案分别设置两台机器对应的参数,TicketServer1从1开始发号,TicketServer2从2开始发号,两台机器每次发号之后都递增2。
综合对比上述几种方案,每种方案都不完全符合我们的要求。所以美团建立了Leaf工程(Leaf这个名字是来自德国哲学家、数学家莱布尼茨的一句话: >There are no two identical leaves in the world > “世界上没有两片相同的树叶”),分别在上述第二种(Snowflake)和第三种(数据库自增ID)方案上做了相应的优化,实现了Leaf-snowflake和Leaf-segment方案。接下来,我们详细介绍这两种方案的实现思路。
当然这种方案在一些情况会退化成异步模式,甚至在非常极端情况下仍然会造成数据不一致的情况,但是出现的概率非常小。如果你的系统要保证100%的数据强一致,可以选择使用“类Paxos算法”实现的强一致MySQL方案,如MySQL 5.7前段时间刚刚GA的MySQL Group Replication。但是运维成本和精力都会相应的增加,根据实际情况选型即可。