分而治之 -- 浅谈分库分表及实践之路 | 京东云技术团队
前言
之前总在聊微服务, 微服务本身也是分布式系统,其实微服务的核心思想是分而治之,把一个复杂的单体系统,按照业务的交付,分成不同的自服务,以降低资深复杂度,同时可以提升系统的扩展性。
今天想聊一下分库分表,因为对于快速增长的业务来说,这个是无法回避的一环。之前我在做商城相关的 SAAS 系统,商品池是一个存储瓶颈,商品池数量会基于租户增长和运营变得指数级增长,短短几个月就能涨到几千万的数据,而运营半年后就可能过亿。而对于订单这种数据,也会跟着业务的成长,也会变得愈发巨大。
存储层来说,提升大数据量下的存储和查询性能,就涉及到了另一个层面的问题,但思想还是一样的,分而治之。
我们面临什么样的问题
关系型数据库在大于一定数据量的情况下检索性能会急剧下降。在面对海量数据情况时,所有数据都存于一张表,显然会轻易超过数据库表可承受的。
此外单纯的分表虽然可以解决数据量过大导致检索变慢的问题,但无法解决过多并发请求访问同一个库,导致数据库响应变慢的问题。所以需要分库来解决单数据库实例性能瓶颈问题。
数据库架构方案
在讲具体解决方案之前,我们需要先了解一下数据库的三种架构涉及方案。
1. Shared Everything
一般指的是单个主机的环境,完全透明共享的 CPU/内存/硬盘,并行处理能力是最差的,一般不考虑大规模的并发需求,架构比较简单,一般的应用需求基本都能满足。
2. Shared Disk
各处理单元使用自己的私有 CPU 和 Memory,共享磁盘系统。典型的代表是 Oracle RAC、DB2 PureScale。例如 Oracle RAC,他用的是共享存储,做到了数据共享,可通过增加节点来提高并行处理的能力,扩展能力较好,使用 Storage Area Network (SAN),光纤通道连接到多个服务器的磁盘阵列,降低网络消耗,提高数据读取的效率,常用于并发量较高的 OLTP 应用。其类似于 SMP(对称多处理)模式,但是当存储器接口达到饱和的时候,增加节点并不能获得更高的性能,同时更多的节点,则增加了运维的成本。
3. Shared Nothing
各处理单元都有自己私有的 CPU/内存/硬盘等,Nothing,顾名思义,不存在共享资源,类似于 MPP(大规模并行处理)模式,各处理单元之间通过协议通信,并行处理和扩展能力更好。典型代表 DB2 DPF、带分库分表的 MySQL Cluster,各节点相互独立,各自处理自己的数据,处理后的结果可能向上层汇总或在节点间流转。
我们常说的 Sharding 其实就是 Shared Nothing,他是将某个表从物理存储上被水平分割,并分配给多台服务器(或多个实例),每台服务器可以独立工作,具备共同的 schema,例如 MySQL Proxy 和 Google 的各种架构,只需增加服务器数就可以增加处理能力和容量。
至于 MPP,指的是大规模并行分析数据库(Analytical Massively Parallel Processing (MPP) Databases),他是针对分析工作负载进行了优化的数据库,一般需要聚合和处理大型数据集。MPP 数据库往往是列式的,因此 MPP 数据库通常将每一列存储为一个对象,而不是将表中的每一行存储为一个对象。这种体系结构使复杂的分析查询可以更快,更有效地处理。例如 TeraData、Greenplum,GaussDB100、TBase。
基于以上的这几种架构方案,我们可以给出大数据量存储的解决方案:
以上几种解决方案各有利弊,分区模式最大的问题是准 share everything 架构,无法水平扩展 cpu 和内存,所以基本可以排除;nosql 本身其实是个非常好的备选方案,但是 nosql(包括大部分开源 newsql)硬件消耗非常大,运维成本较高。而常用的一种方案就是基于 Mysql 的分库分表方案。
分库分表架构方案
对于分库分表,首先看一下市面上有哪些产品。
对于分库分表的产品模式,又分为两种,中间件模式和客户端模式。
1. 中间件模式其优缺点
中间件模式独立进程,所以可以支持异构语言,对当前程序没有侵入性,对业务方来说是透明的 mysql 服务,但是缺点也非常明显,硬件消耗大、运维成本高(尤其是在本地化实施情况下),同时因为对关系型数据库增加了代理,会造成问题难调试。
2. 客户端模式优缺点
客户端模式的主要缺点是对代码有侵入,所以基本只能支持单语言,同时因为每个客户端都要对 schema 建立连接,所以如果数据库实例不多,需要对连接数仔细控制,但是客户端模式的优点也非常明显,首先从架构上它是去中心化的,这样就避免了中间件模式的 proxy 故障问题,同时因为没有中间层性能高、灵活可控,而且因为没有 proxy 层,不需要考虑 proxy 的高可用和集群,运维成本也比较低。
sharding-jdbc 接入实战
sharding-jdbc 其实是这些产品中最为大家熟知的,也是因为它定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC。而且在社区活跃度,代码质量等方面,也是很不错的。接下来,我讲详细讲一下接入细节。
1. 组件集成
2. bean 配置
配置 sharding jdbc 数据源并且加入到动态数据源中,用于数据源路由。
修改原配置中心对应服务的 mysql 数据源配置,对不分库分表的数据源配置为动态数据源默认路由
3. sharing JDBC 配置
以上是一些基本配置,还有一些业务场景配置,大家可以参考开源社区文档: https://shardingsphere.apache.org/document/4.1.0/cn/overview/
总结
对于具体业务场景,我们首先是基于 DDD 的思想划分业务单元,最开始先做好垂直分库。接着是针对一些特定的业务增长量巨大的表,进行水平的分库处理,比如商品子域中的商品池表,订单子域中的订单表等等。
而在分表维度,业务初期,就要最好垂直分表的设计。比如商品池设计中,只需要存储关系信息,而商品详情的信息单独存储在一个底表之中。
作者:京东物流 赵勇萍
来源:京东云开发者社区
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/e89bd398a87524a258a697b2c】。文章转载请联系作者。
评论