第一部分:
关系型数据库随时间的流逝慢慢的不能满足现在每秒大量的操作、很多打开的连接、大量的数据和非常高的写比率。为避免这种情况的出现,很多大型站点和SaaS的应用开始使用sharding技术和他们的关系型数据结合。
怎样对应用分片?下面列出的四点很简单:
1、分析表schema得出分片该如何设置
2、开启多个MySQL 实例
3、根据shard配置,导入导出数据
4、更新程序代码来支持shard配置
分析数据:
为了得到一个shard 配置,你需要做下面三步:
1、列出表名和表的大小。 大表时最需要进行分片的,因为很多SQL命令经常在表上执行。
2、列出外键(如果有的话)外键帮助我们了解表之间的关系,这样的表需要很明智的划分,否则你的表将失去一致性
3、分析涉及到的SQL语句 一些SQL语句在shard环境下是难以执行的。所以需要整理一份SQL语句来决定哪些表时不需要shard的。我们还能得出哪些表时访问频率很高,哪些不是。
表划分规则:
在实施shard的时候,需明白并不是所有的表都会被分片。因为sharding会限制SQL的书写(不允许在表之间进行join,表的唯一性,自增字段),你必须强制修改应用代码。通常情况下一些表被shard,另一些表被复制到其他shard上。 确定哪些表时需要被分片的;
对表进行shard的算法像下面描述的一样简单:
1、寻找最大的表,很多表结构中都有几张大表,其余并不是。
2、分析sql语句:是否表之间使用了join查询?
a、是,让其中较小的表作为一个全局表
b、如果不是,还要根据sql语句来分析访问频率分析
i、如果这些表访问不频繁,让他们成为全局表
ii、找出访问频繁的表尤其是那些写入比较严重的进行shard,然后跳到第2步确定他们真的可以被shard(无join操作)
一旦你确定了哪些表是将被shard的,那么下一步就是选择sharding keys ,多数情况下回使用表的primary key作为shard key。如果某些表之间存在外键关系,那么使用外键作为shard key 也是可以考虑的。
和数据库分区一样,sharding也有很多算法:hash,list,range等。一般情况下使用 list或者 hast算法来应对多个选择条件的情况。通过不同的DB来保存不同的用户信息。hash往往能够对数据更加平均的进行分配。
下一步呢?
如果你是一个新的环境,那么可以跳过这一步啦。
1、在所有的shard上对数据进行克隆,复制物理文件或者mysqldump都行
2、对于每个shard(shard上的每个表)
a、删除所有的索引
b、删除所有多余的数据(脚本搞定)
这个操作会产生很多的碎片,可以考虑建立一张临时表,只插入相关的记录,最后删除原表,再重命名。
c、添加索引
第二部分: ;">public class ShardingAwareDatasource {public static Connection getConnection(Object shardingKey) {…}public static Connection getAnyConnection() {…}}
需要在特定shard上执行的sql语句需要调用 getConnecttion 方法,该方法逻辑放包含基于shard key的连接号。在全局表上执行的sql使用getAnyConnection 方法。
设计的这些连接方法必须在session级别实现来实现事务隔离。
Query 语句修改规则:
1、转到响应查询
2、对于每个查询确定踏实访问全局表,还是shard中的表
a、如果访问全局表,那么使用getAnyConnecttion方法
b、如果访问某个shard中的表,检测语句中是否包含shard key
i、如果包含,那么使用这个keyd 调用 getConnecttion方法
如果查询还要访问其他的表,那么把它拆分成多个语句
ii、如果不包含key,那那么将其拆分成多个查询来得到shard key
c、确保代码能合并所有分开查询的数据。
当使用ORM的情况下:
由于很多的ORM不支持sharding,那只能重写ORM code,只能通过自己写SQL来寻找操作对象,这不是一个简单的任务!
现在你已经知道如何进行shard操作,那么你知道为什么这么做吗?
这个问题已经在ScaleBase 上讨论了很多。 我们很难看到,为什么会有人不想shard。仅仅因为我们是如此热衷于透明的分片机制.这不意味着我们无法理解的非常基本的问题,“我应该什么时候和为什么碎片?”
这个问题并不是很难,我长话短说,如果你的数据都在一台机器上并且已经超出了你的内存的容量,那么你可以考虑分片。如果你的写入很多导致IO很忙,那你可以考虑分片
为什么呢?这个问题很好解释:
数据库一般情况下更倾向于将常用数据放到内存中,供应商已经开发了很多高校的缓存算法,比如:query cache,buffer pool等等
如果数据量太大的话,那么内存就会变的紧张。甚至索引页没有在内存里面。这个时候越早分片越好。如今很多DB是建立在云上的,添加内存几乎变的不可能。使用sharding之后,每个机器都有自己的数据和足够的内存可用,我们做的仅仅是添加新的shard!
其他方面的话可能是最大并发连接数,如果到了一个限制值,这个时候也是可以进行分片的。每个shard相比都会有较少的连接,更高的命中率!