今天看了“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和分区的对应关系被保存,通过查找目录可以得到分区信息。适合扩展,就是增加查询损耗。
如何将数据分布的尽量均匀,如何平衡各个服务器之间的负载,如何在新增存储机器和删除存储机器的时候不影响原有数据,同时能够将数据均摊,都是算法的关键。在分布式系统中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的实现
上图就是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全文搜索引擎解决多数据分区数据汇总查询,例如察看网站用户的最新更新情况或者最热门日至。这个采用单独系统部署,通过建立全局信息索引,来查询数据情况。
以上是技术上的全部内容,作者在最后的几个观点十分值得学习,同时也不仅仅限于数据切分,任何框架设计都可以参考。
“Don't do it, if you don't need to!" (37signals.com)
"Shard early and often!" (startuplessonslearned.blogspot.com)
看起来矛盾的两句话,却是说出了对于数据切分的一些考虑。
首先在没有必要的情况下就不要考虑数据切分,切分带来的复杂性直接影响可用性,可维护性和一致性。在能够采用Scale up的情况下,可以选择Scale up降低框架复杂度。
另一方面,如果发现了业务增长情况出现必须要扩展的趋势,那么就要尽早着手去实施和规划扩展的工作,并且在切分和扩展过程中要不断地去优化和重构。
后话:
其实任何架构设计首要就是简单直接,不过度设计,不滥竽充数。其实就是要平衡好:可用性、高效性、一致性、可扩展性这四者之间的关系。良性循环、应时应事作出取舍和折中。用的好要比学会用更重要,更关键。
分享到:
相关推荐
Oracle Sharding Database(分片数据库)是一项数据库水平分割的技术,它能够通过将数据分布在多个数据库服务器中,从而实现大规模并发访问和高效数据管理。Oracle Sharding 是Oracle数据库提供的解决方案,使得应用...
1、创建数据库 首先我们创建相应的数据库 create database sharding_0; create database sharding_1; 这样我们就创建了两个数据库sharding_0和sharding_1; 脚本在项目里面
《简单分库中间件simple-sharding的探索与实践》 在大数据时代,数据库的扩展性和性能成为了企业系统架构的关键挑战之一。"simple-sharding",正如其名,是一款旨在简化数据库分片操作的中间件,它作为一个轻量级的...
" Scale out your database without pain" 在本文中,我们将探讨如何扩展数据库以满足不断增长的数据需求。数据库扩展是一个复杂的问题,需要考虑多个因素,包括性能、可扩展性、数据一致性等。我们将介绍TiDB作为...
**MySQL HA Scale-Out** MySQL高可用性(High Availability, HA)和扩展性(Scale-Out)是数据库系统设计中的关键组成部分,旨在确保数据的持续可用性和系统性能的提升。在这个主题中,我们将深入探讨MySQL在实现HA...
接下来我们将深入探讨标题和描述中涉及的“sharding-proxy实现分表”这一主题。 ### 1. 分库分表介绍 分库分表是数据库水平扩展的一种常见策略,用于解决单表数据量过大导致的性能问题。随着业务的增长,数据量...
Sharding JDBC是一款开源的轻量级Java框架,它提供了一种分库分表的解决方案,用于解决大规模数据集下的数据库的性能问题。Sharding JDBC具有易于使用,无需额外依赖和强依赖数据库的特点。它允许开发人员对JDBC进行...
Oracle Sharding是一种架构,它是Oracle Database 12c Release 2(版本12.2)中的一种特性,专门为在线事务处理(OLTP)应用程序设计。在Sharding架构中,数据被水平地分布在多个独立的Oracle数据库中,这些独立的...
Sharding-JDBC是阿里巴巴开源的一款轻量级的Java框架,用于实现数据库的水平拆分,它是基于JDBC的中间件,可以在不修改业务代码的情况下,透明地实现数据分片和读写分离。 1. 数据库分库分表概念: 分库是指将一个...
MongoDB Sharding 机制分析 MongoDB Sharding 机制是 MongoDB 中的一种机制,用于将数据水平切分到不同的物理节点,以解决单机性能极限的问题。Sharding 可以利用上更多的硬件资源来解决单机性能极限的问题,并减小...
"database-sharding"项目是Google Code上一个已迁移的开源项目,专注于提供数据库分片的解决方案。尽管描述中提到这只是测试,但我们可以深入探讨数据库分片这一主题,以及它在Java环境中的实现。 数据库分片是一种...
ShardingJDBC是阿里巴巴开源的一款轻量级Java框架,它为数据库分片提供了一种解决方案。这个框架的主要目的是解决在大数据场景下,由于单表数据量过大导致的性能瓶颈问题。ShardingJDBC可以在不改变业务代码的情况下...
【标题】"spring-sharding-mybatis" 涉及到的是Spring Boot集成ShardingSphere(原ShardingJDBC)和MyBatis实现数据库分片的解决方案。这是一个在微服务架构中处理大数据量、高并发场景时,提升系统性能的重要技术。...
SpringBoot整合Sharding-JDBC是将Sharding-JDBC这一分布式数据库中间件与SpringBoot框架结合,以实现数据分片、读写分离等高级数据库管理功能。这个完整的代码示例覆盖了Sharding-JDBC的主要技术点,使开发者可以...
标题"sharding-sphere4.1.1"指的是ShardingSphere的4.1.1版本,这是一个流行的开源项目,专注于数据库分片、分布式事务和数据库治理。ShardingSphere由Apache Software Foundation(ASF)管理,提供了一个全面的...
**标题:“sharding-jdbc.rar”** **描述:**该压缩包内容主要涉及使用Sharding-JDBC技术在MySQL环境中实现数据库的分库分表和读写分离。分库分表是一种常见的数据库扩展策略,用于应对大数据量场景下的性能挑战。...
【标题】"sharding-jdbc-demo" 是一个基于Sharding-JDBC、SpringBoot、MyBatis和Druid的示例项目,旨在展示如何在Java环境中整合这些组件来实现数据库分片和微服务架构。 【描述】这个项目的核心是利用Sharding-...
Oracle_Sharding 演示视频 演示如何搭建和测试sharding.