分布式数据库当然也有主键的需求, 但是为什么不直接使用 uuid 作为主键呢? 作为曾经被这个问题困惑过的人, 试着回答一下
1. UUID 生成速率低下
Java 的 UUID 依赖于 SecureRandom.nextBytes 方法, 而 SecureRandom 又依赖于操作系统提供的随机数源,
在 Linux 系统下, 它的默认依赖是 / dev/random, 而这个源是阻塞的.
最可怕的是, 这个 nextBytes 方法还是一个 synchronized 方法, 也就是说, 如果多线程调用 UUID, 生成速率不升反降.
测试结果: 在一台 64 线程的服务器上, 调用 UUID.randomUUID 方法, 生成一千万个 uuid 平均耗时在 130s,tps 不到 8w
2. UUID 主键在 innodb 中会引发性能问题
a. innodb 中的主键索引也是聚集索引, 如果插入的数据是顺序的, 那么 b + 树的叶子基本都是满的, 缓存也可以很好的发挥作用.
如果插入的数据是完全无序的, 那么叶子节点会频繁分裂, 缓存也基本无效了. 这会减少 tps
b. uuid 占用的空间较大
3. UUID 完全没有意义, 如果有一个主键是全局自增的, 那么数据排列顺序就是数据的插入顺序
解决方案:
1. 分布式全局序列生成 (使用 zk 的 DistributedAtomicLong, 一次自增一个步长, 用户用完了步长内的序列, 再找 zk 要)
2. Twitter 的 snowflake 算法
当然自增序列也不是完美的, 因为在极大并发的情况下, 按自增主键插入会发生争用, 主键的上界会出现热点. 但总的来说, 还是可以接受的
来源: http://www.bubuko.com/infodetail-2575314.html