`
cenwenchu
  • 浏览: 161221 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

读“DataBase Sharding at Netlog”,看DataBase Scale Out

阅读更多

       今天看了“Database Sharding at Netlog, with MySQL and PHP”一文,和去年我们讨论扩展的思路很类似(不过这种分布式扩展,计算,存储的思路都很类似),但是这片文章的作者是在日益爆炸式增长的用户数据下实践的分享,因此这里将文中的一些思想记录下来分享一下。

       Netlog拥有4000万活跃用户,每个月有超过5000万的独立用户访问网站,每个月有5亿多的PV。数据量应该算是比较大的。作者是Jurriaan Persyn,他从一个开发者角度而非DBA或者SA角度来谈Netlog是如何通过数据切分来提高网站性能,横向扩展数据层的。原文在:http://www.jurriaanpersyn.com/archives/2009/02/12/database-sharding-at-netlog-with-mysql-and-php/

 

       首先,还是先谈到关于数据库在数据日益庞大的情况下一个演变过程。

第一阶段:读写同在一台数据库服务器

 

 

 

 

第二阶段:读写分离(可以解决读写比例均衡或者读居多的情况,但是带入了数据复制同步的问题)

 

 

 

 

      

第三阶段:部分数据独立部署结合读写分离。(部分数据根据其业务独立性情况,可以将所有的数据独立存储到数据库服务器,分担数据读写压力,前提是要求数据具有较高的业务独立性)

 

 

 

 

 

       第四阶段:数据分拆结合读写分离(三阶段的增强)

 

 

 

      

       第五阶段:问题出现,分拆也无法解决数据爆炸性增长,同时读写处于同等比例。

 

 

 

       解决问题两种方式:DB Scale up DB Scale out。前者投入以及后期扩展有限,因此需要进行数据切分。

 

 

 

       上图就是将photo的数据切分到了10台数据库服务器上。

 

       切分数据的两个关键点:

1.  如何根据存储的数据内容判断数据的存储归属,也就是什么是内容的分区主键。

2.  采用什么算法可以根据不同的主键将内容存储到不同的分区中。

 

分区主键的选择还是要根据自身的业务场景来决定,Netblog选择的是用户ID

采用什么方式将分区主键映射到对应的分区可以通过以下四种方式:

1.  根据数据表来切分。(前提就是数据独立性较强,和前面提到的三阶段类似)

2.  基于内容区间范围的分区。(就好比前1000个用户的信息存储在A服务器,1000-2000存储在B服务器)

3.  采用Hash算法结合虚拟节点的方式。(这类在memcached等等分布式场景中最常见,其实也是一个难点),缺点就是在于动态增加存储节点会导致数据部分或者全部失效。

4.  目录式的分区。最简单也是最直接的方式,key和分区的对应关系被保存,通过查找目录可以得到分区信息。适合扩展,就是增加查询损耗。

 

如何将数据分布的尽量均匀,如何平衡各个服务器之间的负载,如何在新增存储机器和删除存储机器的时候不影响原有数据,同时能够将数据均摊,都是算法的关键。在分布式系统中DHTDistribute Hash Table)被很多人研究,并且有很多的论文是关于它的。

 

数据的横向切分给应用带来的问题:

1.  跨区的数据查询变得很困难。(对于复杂的关联性数据查询无法在一个请求中完成)

2.  数据一致性和引用完整性较难保证。(多物理存储的情况下很难保证兼顾效率、可用性、一致性)

3.  数据分区之间的负载均衡问题。(数据本身的不均衡性,访问和读写的不均衡性都会给数据分区的负载均衡带来困难)

4.  网络配置的复杂性。(需要保证服务器之间的大数据量频繁的交互和同步)

5.  数据备份策略将会变得十分复杂。

解决这些问题当前已经有的一些开源项目:

1.  MySql Cluster,解决读写分离问题已经十分成熟。

2.  MySql Partitioning,可以将一个大表拆分为很多小表,提高访问速度,但是限制与这些小表必须在同一台服务器上。

3.  HSCALESpock Proxy都是建立与MySql Proxy基础上的开源项目,MySql Proxy采用LUA脚本来进行数据分区。

4.  HiveDBMySql分区框架的java实现。

5.  另外还有HyperTable,HBase,BigTable等等。

 

Netblog几个需求:

1.              需要灵活的可扩展性。对于存储增加减少需要能够动态的及时实施,因为数据量增长很快,如果策略会导致数据失效或者部署需要重新启动,则就不能满足需求。

2.              不想引入全新的数据层和与原有系统不匹配的抽象层,因为并不是所有数据都需要切分,仅仅在需要的情况下通过API的方式来透明切分数据。

3.              分区的主键需要可配置。

4.              需要封装API,对开发人员透明数据切分的工作。

 

      Netblog Sharding的实现

 

 

 

上图就是NetblogSharding的结构图,主要分成了三部分:ShardSharddbSharddbhostShard就是一个表,里面存放了部分用户数据。Sharddb是一个表的组合就像一个虚拟的DBSharddbhost是具体的存储分区。ShardSharddb可以根据负载的情况被移动到不同的host中去。

       对于Shard的管理,Netblog采用的是目录查询的管理方式。目录信息也存储在MySql中,同时会通过互备,Memcache,集群来确保安全性和高效性。

       Shard Table API采用了多一层的映射模式来适合各种不同属性的查询情况。数据和记录在数据库中存储除了UserID以外还有对应的ItemIDItemID的作用就是定义了具体获取数据的字段信息,例如关联照片表时,ItemID就是PhotoId,关联视频表时,ItemID就是videoID

       一个获取用户id26博客信息的范例:

1Where is user 26?

   User 26 is on shard 5.

2On shard 5; Give me all the $blogIDs ($itemIDs) of user 26.

That user's $blogIDs are: array(10,12,30);

3On shard 5; Give me all details about the items array(10,12,30) of user 26.

Those items are: array(array('title' => "foo", 'message' => "bar"), array('title' => "milk", 'message' => "cow"));

 

对于Shard的管理Netblog采取的措施主要有这些:

1.  服务器之间的负载均衡根据用户数,数据库文件大小,读写次数,cpu load等等作为参数来监控和维护。根据最后的结果来迁移数据和分流数据。

2.  移动数据时会监控用户是否在操作数据,防止不一致性。

3.  对于数据库的可用性,采用集群,master-mastermaster-slave复制等手段。

 

最后通过三种技术来解决三个问题:

 

1.  Memcached解决shard多次查询的效率问题。

根据上面的范例可以看到,一次查询现在被分割成为了三部分:shard查询,item查询,最终结果查询。通过memcached可以缓存三部分内容,由前到后数据的稳定性以及命中率逐渐降低,同时通过结合有效期(内容存储时效)和修改更新机制(add,update,delete触发缓存更新),可以极大地解决效率问题。甚至通过缓存足够信息减少大量的数据库交互。

 

2.  并行计算处理。

由于数据的分拆,有时候需要得到对于多Shard数据处理的结果汇总,因此就会将一个请求分拆为多个请求,分别交由多个服务器处理,最后将结果汇总。(类似于Map-reduce

 

3.  采用Sphinx全文搜索引擎解决多数据分区数据汇总查询,例如察看网站用户的最新更新情况或者最热门日至。这个采用单独系统部署,通过建立全局信息索引,来查询数据情况。

 

以上是技术上的全部内容,作者在最后的几个观点十分值得学习,同时也不仅仅限于数据切分,任何框架设计都可以参考。

 

“Don't do it, if you don't need to!" (37signals.com)

"Shard early and often!" (startuplessonslearned.blogspot.com)

 

看起来矛盾的两句话,却是说出了对于数据切分的一些考虑。

首先在没有必要的情况下就不要考虑数据切分,切分带来的复杂性直接影响可用性,可维护性和一致性。在能够采用Scale up的情况下,可以选择Scale up降低框架复杂度。

另一方面,如果发现了业务增长情况出现必须要扩展的趋势,那么就要尽早着手去实施和规划扩展的工作,并且在切分和扩展过程中要不断地去优化和重构。

 

后话:

       其实任何架构设计首要就是简单直接,不过度设计,不滥竽充数。其实就是要平衡好:可用性、高效性、一致性、可扩展性这四者之间的关系。良性循环、应时应事作出取舍和折中。用的好要比学会用更重要,更关键。

分享到:
评论
18 楼 fujohnwang 2009-05-22  
引用
超大规模的应用, 业务是受数据分区极大的影响的,

我咋感觉这句话跟我一直的想法不太一样那,我咋一直觉得你只有业务跟数据之间的关系摆明了,你才可能更合理的作partition那?照你这句话,我是不是可以理解成反而是数据的分区主导了前者那? wondering...


17 楼 sdh5724 2009-03-08  
willko 写道
很好的文章,谢谢

如果不介意,可以指教个问题吗?
假如把,好友表,按用户id切分了。对于查询我好友信息就很好查了。
但是如果要查我好友的好友就很麻烦了。。如果是同表,那自己连接自己就可以得出了。。

但是分表的话,首先要得出我好友信息,然后在去分表查好友的好友。。
这样数据会好多。。。

不知道有没比较好的查询方法。。



我们通常要做SHARDING的情况, 必然应用会受到限制的。 很多设计师在这个上面撞破了头, 分区后, 还想做各种复杂的join, 多库分别查询并且结果排序,聚合等操作。 这个是不对的, 业务方应该知道, 这个规模下要实现过于复杂的代价是非常庞大的。 如果设计者还是想做这些操作, 那我们只能说, 他对业务的数据的切割没有理解到位, 或者大规模应用的代价还不清楚。

一般来说, 类似SNS的应用, 按用户分割数据, 就要在表的设计上需要一定的灵活度, 比如,每个人的好友列表必须位于本人所在的数据库, 不然查询是非常困难的。 象好友的好友都是通过多次操作数据库得到, 或者在CACHE里已经建立好关系了。 依赖数据库来获得是数据的行为应该受到极大的限制。

另外, SHARDING以后, 可能要求很多数据是冗余的, 这个冗余正是为了避免多库join。 我们不能严格遵守数据库范式来设计表。 比如, SNS应用里的每个好友的状态活动信息, 如果不限制的情况下, 按照普遍的原则, 每个人差不多有200-500的好友, 那么将会产生极大的数据。 所以单一数据库是无法承受的, 即使有了CACHE也是承受不了的。 很容易产生数十亿行数据。 那么我们宁愿向每个好友分发数据, 来避免多库join, 尽管我们极大的冗余了数据, 但是也降低了复杂的多库查询。 业务上, 我们需要限制这些好友信息的数量, 以及过期时间。 以期获得更好的性能。

实际上, 架构师应该把握避免多数据的查询, 以灵活的手段解决 n:m 的数据分区的问题。

也许很多人反对我的观点, 但是事实就是这样, 超大规模的应用, 业务是受数据分区极大的影响的, 不能想干什么就干什么。

最近在看数据库发展方面的, 有的开源组织已经开始研究数据库的实时的map/reduce系统。 也许有一天,数据库透明的为我们解决很多问题。像hadoop类似工具,无法替代数据库的功能。 如果数据库有M/P能力, 最好不过了。 当然也有人说m/p系统是开历史倒车。 尽管他取得了极大的成功。







16 楼 cenwenchu 2009-03-07  
如果是这样的话,应该和文中提到的最后一种手段,也就是对用户的好友建立搜索引擎,建立索引,只能通过几次搜索引擎的检索先得到用户的基本id,然后再根据需要去查询出用户的基本信息。不过我没有实施过,只是空谈^_^,我现在还没有实际的sharding,现在我所关注的是open api,其他方面有涉及,但是不深入,因此只能给个仅作石头的引子。
15 楼 willko 2009-03-07  
很好的文章,谢谢

如果不介意,可以指教个问题吗?
假如把,好友表,按用户id切分了。对于查询我好友信息就很好查了。
但是如果要查我好友的好友就很麻烦了。。如果是同表,那自己连接自己就可以得出了。。

但是分表的话,首先要得出我好友信息,然后在去分表查好友的好友。。
这样数据会好多。。。

不知道有没比较好的查询方法。。
14 楼 cenwenchu 2009-03-07  
楼上的我知道你是谁了,以前的同学么,我也看过你ameoba的部分设计,不过没有很深入,感觉的却很不错的。是的,其实技术就是要在实施过程中才会有体验,就好比erlang很多人都只觉得天生并行计算的好语言,但是它的优点也带来了很多问题,用起来就知道了。不过么,呵呵,象你对横向阔展有那么多研究的同学还是有限的,因此开阔一下眼界也还好了,文中提到的横向扩展很多都是理论性的东西,但是将关系型数据弱化感觉在某些情况还是有效的。如果楼上同学有blog请站内给我一个消息,我也希望好好学习一下这方面的内容,因为我的方向起码在过去还和你不太一样:)
13 楼 sdh5724 2009-03-06  
sdh5724 写道
cenwenchu 写道
sdh5724 写道
一个月5亿PV也值得拿出来做架构分析啊, 一天5亿的办法草是考普的.,

taobao的同学?数据我是直译的,阿软sip一天也就有5000w的服务调用了,今年1.6亿吧,也就这么几台破机器:),这里还是说那种扩展的思路,当然适用于某一些场景,呵呵,这种思路用在一天10亿的设计中也未尝不可。


怎么老有人说我是taobao的, 我声明, 我不是taobao的!


是的, 但是, 这个思路很多人都会。 估计是大部分解决思路的, 问题在难度在于, 管理这么庞大的数据源是个很难解决的问题, 开发上很难做到透明。 虽然这些架构设计很多人滚瓜烂熟了, 但是实践起来, 估计都不是简单的事情, 我很难想象, 一个应用要连接30-50个MYSQL的配置应该如何做。

所以, 我们团队设计了ameoba这个工具, 解决sharding的透明开发, 透明管理的问题。MYSQL大规模部署, DDL是个很大的问题。 无法在线DDL, 哎。

12 楼 sdh5724 2009-03-06  
cenwenchu 写道
sdh5724 写道
一个月5亿PV也值得拿出来做架构分析啊, 一天5亿的办法草是考普的.,

taobao的同学?数据我是直译的,阿软sip一天也就有5000w的服务调用了,今年1.6亿吧,也就这么几台破机器:),这里还是说那种扩展的思路,当然适用于某一些场景,呵呵,这种思路用在一天10亿的设计中也未尝不可。



是的, 但是, 这个思路很多人都会。 估计是大部分解决思路的, 问题在难度在于, 管理这么庞大的数据源是个很难解决的问题, 开发上很难做到透明。 虽然这些架构设计很多人滚瓜烂熟了, 但是实践起来, 估计都不是简单的事情, 我很难想象, 一个应用要连接30-50个MYSQL的配置应该如何做。

所以, 我们团队设计了ameoba这个工具, 解决sharding的透明开发, 透明管理的问题。MYSQL大规模部署, DDL是个很大的问题。 无法在线DDL, 哎。
11 楼 cenwenchu 2009-03-06  
sdh5724 写道
一个月5亿PV也值得拿出来做架构分析啊, 一天5亿的办法草是考普的.,

taobao的同学?数据我是直译的,阿软sip一天也就有5000w的服务调用了,今年1.6亿吧,也就这么几台破机器:),这里还是说那种扩展的思路,当然适用于某一些场景,呵呵,这种思路用在一天10亿的设计中也未尝不可。
10 楼 whaosoft 2009-03-06  
55555555555  我好好看看!~!
9 楼 klesh 2009-03-06  
DBA Notes 大多只是抛几个名词出来讲一下,不会讲这么细致,而且用词也很晦涩,基本看上了等于没看。这篇显然不是出自DBA NOTES。
8 楼 julyboxer 2009-03-06  
sdh5724 写道
一个月5亿PV也值得拿出来做架构分析啊, 一天5亿的办法草是考普的.,

你什么时候写篇文章分析一下淘宝的架构哦
7 楼 sdh5724 2009-03-06  
一个月5亿PV也值得拿出来做架构分析啊, 一天5亿的办法草是考普的.,
6 楼 julyboxer 2009-03-05  
拆分数据,然后通过Map reduce类似框架分析语句。再加缓存。。
不知道有没有新大规模数据管理方式思路呢?
5 楼 joachimz 2009-03-05  
不好意思,我订阅了你blogjava的RSS,错记为Feng的了。
4 楼 nihongye 2009-03-05  
很好的介绍。shard的特点,按用户拆分数据。最大化缓存的使用。Sharddb,Sharddbhost到底干吗用,没点感觉
3 楼 cenwenchu 2009-03-05  
如果说我谈的这篇文章英文版,我想我已经说了原文出处,如果你说整篇中文的话,全都是自己写的,还夹杂了自己的一些观点,请不要随便乱说
2 楼 joachimz 2009-03-05  
在DBA Notes上看过,如果是转贴最好注明。给一个网址就行了。
1 楼 movingboy 2009-03-05  
很不错的思路!

相关推荐

Global site tag (gtag.js) - Google Analytics