论坛首页 综合技术论坛

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

浏览 13075 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-03-05   最后修改:2009-03-05

       今天看了“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降低框架复杂度。

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

 

后话:

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

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

你什么时候写篇文章分析一下淘宝的架构哦
0 请登录后投票
   发表时间:2009-03-06  
DBA Notes 大多只是抛几个名词出来讲一下,不会讲这么细致,而且用词也很晦涩,基本看上了等于没看。这篇显然不是出自DBA NOTES。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics