分片技术的背景:横向扩展的方式可以很好的解决读负载的操作,但是无法解决写负载增加的问题;
【将数据库分解的方式】
功能分隔:将某些表分别放在不同的机器上;
水平分隔:将某些表分隔成不同的行分别存储在不同的机器上;
【数据分片】
扩展写操作最直接的方法就是服务器之间不再有复制机制,这样它们就是完全分离的。通过这种结构,就可以将数据分成两个完全独立的自己,然后将客户端定向到它试图改变的数据所在的分区,从而实现扩展写操作。这样,此次更新处理并不需要其他分片消耗资源。 这种分隔数据的方式称为分片(sharding,又称为水平分隔),每个分区称为一个分片(shard);
【分片的好处】
(1)将数据放在距离用户较近的地方;
(2)减少工作集(working set)的大小。
检索表的算法在表较小的时候会更有效,即使同一个机器上有多个分片,这样也能够提高性能。但是,在单个机器上存储多个分片有技术限制和额外开销,所以需要在分片的数目和分片的大小之间权衡;
确定表的最佳大小需要监控MySQL服务器和In能偶DB。搞清楚扫描一行平均需要多少次I/O操作,确定是否需要让分片更小一点;
(3)分发工作;
将工作并行化;
注意:并不是数据库中所有的表都需要进行分片。可以将某些大表进行拆分。然后在每个分片上对小表做全量副本(这些通常就是全局表)
【分片的局限性】
需要选择一个分片索引,保证查询结果在分片或者不分片数据库上是一样的;
有些情况下,用分片索引来解决问题是不可行甚至是不可能的,因为这要求重写查询(或者完全丢弃这个查询),有两个问题需要解决:跨分片连接(cross-shard joins)和AUTO_INCREMENT列
跨分片连接:》
最重要的一个局限点就是跨分片连接。由于表是分片的,所以连接属于不同分片的两张表的结果,与在一个不分片的数据库中的查询结果不可能一样;
使用跨分片连接最常见的情况是做报表:这通常需要收集整个数据库的信息。有两种方式:
(1)使用map-reduce的方式进行查询,将查询发送到所有的分片,然后将查询结果收集到单个结果集中;
(2)将所有的分片复制到某个单独的报表服务器,然后在报表服务器上运行查询;
使用AUTO_INCREMENT:》
在分片环境中,使用AUTO_INCREMENT创建列的唯一标识是行不通的。
因为分片不会同步它们的AUTO_INCREMENT标识符。也就是说,如果向一个分片插入一行,另一个分片可能也在使用相同的标识符。
如果真的需要一个唯一的标识符,大致有以下两种方法:
(1)生成一个唯一的UUID
缺点是UUID占用16个字节,同一个UUID出现在不同分片中(可能性很小);
(2)使用复合标识符(composite identifier)。
ShardID(分片标识符)+LocalID(本地生成的标识符比如AUTO_INCREMENT)
【分片方案的要素】
对数据库如何进行分片最终是由用户想要执行什么样的查询决定的;
1、确定如何为应用分区(partition)。哪些表应该分隔?哪些表在所有分片上都应该有?应该在什么列上进行分片?
2、确定需要什么分片元数据(即关于分片的信息)以及如何管理元数据。包括如何将分片分配到MySQL服务器,如何将分片关键字映射到分片,以及“分片数据库”需要存储哪些数据;
3、确定如何分发查询。包括如何获取分片关键字将查询和事务定向到正确的分片;
4、创建分片管理的模式。包括如何监控分片负载,如何迁移分片,如何通过分隔和合并分片使系统重新负载均衡;
【高级分片架构】
查询来自于应用程序,然后由broker接收。broker决定查询将被发送到哪里,可能需要分局一个记录分片信息的分片数据库来决定。然后,查询将被发送到一个或者多个应用数据库的分片上执行。broker收集这些执行结果,有可能会对结果集进行处理,然后把这些信息发送回应用程序;
【数据分区】
将每一个数据项写入到某个特定的服务器,能够有效的对写操作进行扩展。但是这对于扩展性来说还是不够:高效的数据检索同样重要,为此,需要将相关数据放在一起。因此,高效分片的最大挑战是创建一个高效的分片索引(sharding index),使得经常一起访问的数据落在同一个分片上。你会发现,分片索引是定义在多个表的多个列上或者是每个表的多个列上。分片索引将决定哪些表需要分片,以及如何进行分片;
补充:
自动计算可能的分片索引:使用MySQL的information_schema模式,能够计算出相关列上所有可能的分片索引;
USE information_schema;
SELECT
GROUP_CONCAT(CONCAT_WS(‘.’table_schema,table_name,column_name)
)AS indexes
FROM
key_column_usage JOIN table_constraints
USING(table_schema,table_name,constraint_name)
WHERE
constraint_type=’FORENGN KEY’
GROUP BY
referenced_table_schema,
referenced_table_name,
referenced_column_name
ORDER BY
table_schema,table_name,column_name;
【分配分片】
《每个服务器上一个分片》
《每个服务器上多个分片(虚拟分片)》
【映射分片关键字】
【分片方案】
《静态分片方案》
《动态分片方案》
【分片映射函数】
《区间映射》
《哈希映射和一致性映射》
【处理查询和事务调度】
【处理事务】
【分配查询】
【分片管理】
《将分片迁移到其他的节点》
【分隔分片】