浅谈MySQL Sharding分片技术

 

一个生产系统总会经历一个业务量由小变大的过程,可扩展性成为了考量系统高可用性的一个重要衡量指标。试想一下,一个记事本应用程序,在存储的很少字节时,能够快速的打开和访问,但是如果硬要让记事本存储百万、千万字节,那么这个记事本估计就歇菜了!同样,系统刚开始的时候,用户数量不多,所有的数据都放在了同一个数据库中,此时因为用户少压力小,一个数据库完全可以应付的了。但是随着用户数量不断增加,数据库压力也与日俱增,如果没有妥善的扩容机制,那么再强劲的硬件和商业数据库也会歇菜。


“Shard”字面意思为碎片,Sharding可以译为分片。MySQL5 以后提供了Sharding的能力,其目的就是为突破单节点数据服务器I/O能力限制,解决数据库Scale Out水平扩展的问题。通过Sharding可以将数据按照物理位置贴合用户分布,得到更加快速的响应;操作庞然大物总是让人头疼,Sharding将数据分块,更小的数据集操作汇总能够得到更大的体验;分片使得数据分摊在各个数据节点,对其操作实现负载均衡,众多屌丝的汇聚战胜了一个高富帅! 


Sharding按方向可以分为两类。

垂直分区:以表为单位,把不同的表分散到不同的数据库或主机上。特点是规则简单,实施方便,适合业务之间耦合度低的系统。

水平分区:以行为单位,将同一个表中的数据按照某种条件拆分到不同的数据库或主机上。特点是相对复杂,适合单表巨大的系统。


 Sharding按模式可以分为两大模式。

静态分片模式,即分区键是静态分配的,一般使用范围或哈希函数,例如深圳团队放到一个分片,北京团队放到另外一个分片;或者编号为0096开头的员工放到一个分片,而0199开头的员工放到另外一个分片。这种模式虽然实现简单,但明显的缺陷便是存在数据不均匀的情况。

动态分片模式,即分区函数将从字典中查找分区键,然后定位具体哪个分片存储了数据。这种模式比静态模式更加灵活,但是需要一个集中存储来存放字典,每次查找数据都需要执行2次查询,并且集中存储本身还可能存在单点故障。 


 Sharding按分区类型分为: 

 

1) RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。 

 

2) LIST 分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。 

 

3) HASH 分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。 

 

4) KEY 分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。


在经过周密的设计和反复的测试后发现,所做的一切的努力都是值得的,MySQL的Sharding技术让一群低廉的PC服务器构成了一个可以媲美昂贵的小型机+商业数据库的性能,以低成本的方式构建了强大的数据中心。难怪淘宝这个巨人在很早的时候就一直推行“走你IOE”! 


因此,学习MySQL Sharding百益而无一害!最早的先驱者估计可以是Google捐赠给开源社区的Hibernate shards了,这是一个Hibernate应用横向分割的分布式数据库解决方案的框架。它可以让一个Hibernate应用比较简单地加入横向分割的数据库分布式功能。另外,还有HiveDB。其底层也是基于Hibernate shards实现,目前版本相对稳定,其亮点是具有类似mysql proxy之类多服务器容错功能,单独服务器发生故障不影响系统正常运行,通过类似ha-jdbc思想实现。最后,不得不提的就是淘宝贡献的TDDL,使用过淘宝的同学应该都深有体会,其可靠性、可用性、稳定性、可扩展性均领跑业界很多同类产品。TDDL最大的两个亮点是动态数据源管理和分库分表。