DataBase Sharding at Netlog 数据库数据切分系统

blogdaren 2015-02-11 抢沙发 1351人次

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/

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

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

33.png

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

44.png      

第三阶段:部分数据独立部署结合读写分离

部分数据根据其业务独立性情况,可以将所有的数据独立存储到数据库服务器,分担数据读写压力,前提是要求数据具有较高的业务独立性

55.png

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

66.png     

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

77.png

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

88.png

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

切分数据的两个关键点:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4.HiveDB是MySql分区框架的java实现。

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

Netblog几个需求:

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

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

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

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

Netblog Sharding的实现

99.png

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

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

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

一个获取用户id为26博客信息的范例:

1.Where is user 26?

User 26 is on shard 5.

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

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

3.On 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-master,master-slave复制等手段。

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

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

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

2.并行计算处理。

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

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

转自: http://www.51testing.com/?uid-23978-action-viewspace-itemid-154705


版权声明:除非注明,本文由( blogdaren )原创,转载请保留文章出处。

本文链接:DataBase Sharding at Netlog 数据库数据切分系统

发表评论:

您的昵称:
电子邮件:
个人主页: