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