分库设计中的主键选择.docxVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
分库设计中的主键选择 在先前的文章《又拍网架构中的分库设计》中, 我有提到过 MySQL 分库设计中的主键选择问题。在这篇文章里我想对这个问题进行展开讨论, 以此作为对上一篇文章的一个补充。前面提到又拍网采用了全局唯一的字段作为主键。比如拿照片表为例, 虽然不同用户的照片数据存放在不同的 Shard(或者说 MySQL 节点/实例, 请参考《又拍网架构中的分库设计》) 上, 但是每一张照片拥有整个站点唯一的 ID 作为标示。 为什么要全局唯一? 我们在对数据库集群作扩容时,为了保证负载的平衡,需要在不同的 Shard 之间进行数据的移动, 如果主键不唯一,我们就没办法这样随意的移动数据。起初,我们考虑采用组合主 键来解决这个问题。 一般会以 user_id 和一个自增的 photo_id 来作为主键,这的确能 解决移动数据可能带来的主键冲突问题, 但是就像在“又拍网架构中的分库设计”中描述的那样当 Shard 之间的数据发生关系后,我们需要用更多的字段来组成主键以保证唯一性, 因此主键的索引会变的很大,从而影响查询性能, 同时也会影响写入性能。 其次,每个 Shard 由两台MySQL 服务器组成,而这两台服务器采用 master-master 的复制方式, 以保证每个 Shard 一直可写。master-master 复制方式必须保证在两台服务器上各自插入的数据有不同的主键, 不然当复制到另外一台时就会出现主键重复错误。如果我们保证主键全局唯一,就自然的解决了这个问题。 在没有采用数据拆分的设计当中,如果要用 自增字段,可以参考这篇文章里的解决办法。 可能的解决方案 UUID 或许可以采用 UUID 作为主键,但是 UUID 好长的一串,放在 URL 里好难看啊,有木有? 当然这个不是关键所在,更重要的原因还是性能。UUID 的生成没有顺序性,所以在写入时, 需要随机更改索引的不同位置,这就需要更多的 IO 操作,如果索引太大而不能存放在内存中的话就更是如此。 而 UUID 索引时,一个 key 需要 32 个字节(当然如果采用二进制形式存储的话可以压缩到 16 个字节), 因此整个索引也会相对比较大。 MySQL 自增字段 在单个 MySQL 数据库的应用中一般设置一个自增的字段就可以了,而在水平分库的设计当中,这种方法显然不能保证全局唯一。 那么我们可以单独建立一个库用来生成 ID,在 Shard 中的每张表在这个 ID 库中都有一个对应的表,而这个对应的表只有一个字段, 这个字段是自增的。当我们需要插入新的数据,我们首先在 ID 库中的相应表中插入一条记录,以此得到一个新的 ID, 然后将这个 ID 作为插入到Shard 中的数据的主键。这个方法的缺点就是需要额外的插入操作,如果 ID 库变的很大, 性能也会随之降低。所以一定要保证 ID 库的数据集不要太大,一个办法是定期清理前面的记录。 引入其它工具 Redis、Memcached 等都支持原子性的 increment 操作,而且因为它们的优秀性能可以减少写入时的额外开销, 也许我们可以拿它们当作序列生成器。Memcached 的问题在于不持久性,所以我们不会考虑。 而 Redis 也不是实时持久的,当然也可以配置成实时的,但那样怪怪的。当然也有一些持久的工具, 比如 Kyoto Cabinet、Tokyo Cabinet、MongoDB 等等, 传说中性能都不错,但是引入其它工具会增加架构的复杂程度, 也会增加维护成本。我们的团队很小,精力有限,我们奉行够用就好的原则,也就是没有特别的原因, 在可以接受的情况下,尽量用我们熟悉的工具解决问题。所以,我们还是来考虑一下怎么样用 MySQL 来解决这个问题吧。 更好的方案 我们一开始就是采用了上面所描述的 MySQL 自增字段的方法, 后来看到《Ticket Servers: Distributed Unique Primary Keys on the Cheap》 这篇文章里所描述的方法,豁然开朗。我经常这样想:如果没有那些开源产品、没有那些无私分享经验的人, 光凭我们自己的能力能做到什么程度。很感谢那些人,所以我也尽量多的分享一些自己的经验。 我先描述一下 Flickr 那篇文章里所描述的方法,他们使用了 REPLACE INTO 这个MySQL 的扩展功能。 REPLACE INTO 和 INSERT 的功能一样,但是当使用REPLACE INTO 插入新数据行时, 如果新插入的行的主键或唯一键(UNIQUE Key)已有的行重复时,已有的行会先被删除,然后再将新数据行插入。 你可以放心,这是原子操作。 建立类似下面的表: CREATE TABLE `tickets64` ( `id` bigint(20) un

文档评论(0)

hao187 + 关注
官方认证
文档贡献者

该用户很懒,什么也没介绍

认证主体武汉豪锦宏商务信息咨询服务有限公司
IP属地上海
统一社会信用代码/组织机构代码
91420100MA4F3KHG8Q

1亿VIP精品文档

相关文档