分布式数据库中间件Apache ShardingSphere京东落地实战

潘娟 2019-04-01 11:52:23
本文根据dbaplus社群第183期线上分享整理而成。

面对互联网大数据如火如荼发展、云服务需求的急剧增加,对企业极其重要的数据要如何面对这些新的变革?

 

作为Apache基金会的分布式数据库中间件项目-ShardingSphere将针对数据水平&垂直拆分、分布式事务、数据服务治理、数据安全等需求提供一套适用于互联网应用架构、云服务架构的多解决方案生态圈。

 

本次分享将介绍Apache ShardingSphere核心功能、在京东的具体落地实战、产品生态圈发展等内容。

 

内容提纲:

 

  • Apache ShardingSphere生态圈简介

  • Apache ShardingSphere核心功能&接入端

  • Apache ShardingSphere京东落地实战

  • Apache ShardingSphere迭代&规划

 

一、Apache ShardingSphere

生态圈简介

 

Apache ShardingSphere是一款开源的分布式数据库中间件组成的生态圈。自从2016年开源以来,不断升级开发新功能、重构稳定微内核,并于2018年11月进入Apache基金会孵化器。

 

它由京东集团主导,并由多家公司以及整个ShardingSphere社区共同运营参与贡献。其主要的功能模块为:数据分片(分库分表)、分布式事务、数据库治理三大块内容。

 

目前以在gitHub上收获7000+关注度、70+公司落地的成功案例。

参考链接:

https://github.com/apache/incubator-shardingsphere

 

对新朋友而言,简介部分主要为大家呈现Apache ShardingSphere生态圈概览;对老朋友来说,它的迭代和发展是日新月异的,可以看到它最近的发展状态和前进方向。目前,整个Apache ShardingSphere生态圈架构如下图所示:

 

 

整体核心功能将组成一个闭环,它不仅为大家提供最为基础和核心的数据分片和分布式事务功能,同时针对以ShardingSphere为中心的整个分布式数据库系统,提供数据库治理的功能,例如配置信息动态统一管理、调用链与拓扑图、高可用管理、数据脱敏安全、权限控制等强大的管理功能。

 

此外,我们针对不同的数据库,例如MySQL、Oracle、PostgreSQL、SQL Server提供多模式连接的支持,真正屏蔽底层数据库选型的影响,做到无论使用何种数据库都可在用户无感知情况下进行数据分片、分布式事务、数据库治理的功能操作。

 

管控界面模块旨在为用户提供清晰可见的信息查看、配置更新管理、统计报表等功能。

 

在接入端部分,为了满足不同用户针对不同场景的需求,ShardingSphere提供了多款接入端,包括Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(规划中):

 

  • Sharding-JDBC是一款轻量级的Java框架,在JDBC层提供上述核心功能,使用方式与正常的JDBC方式如出一辙,面向Java开发的用户。

  • Sharding-Proxy是一款实现了MySQL二进制协议的服务器端版本,大家可以把它当成升级版的MySQL数据库使用。独立部署后,即可按照正常MySQL操作方式来使用上述所有的核心功能。

  • Sharding-Sidecar从Service Mesh的理念中应用而生,面向于云原生架构。

 

Apache ShardingSphere是一个生态,它的开源基因注定它的发展开放自由、社区参与贡献。所以在设计它的架构时,会更加注意营造微内核与开发生态。

 

我们提供各个方面的开放接口,以方便所有对此感兴趣的朋友能参与其中,贡献代码,成为Apache基金会项目的提交者。

 

二、Apache ShardingSphere

核心功能&接入端

 

1、核心功能介绍
 

 

数据分片、分布式事务、数据库治理功能已成熟,可提供给用户用于生产;多模式连接和管控界面还在进行中,尚需时日才可与大家见面。

 

成熟的核心功能具体而言主要由以下内容组成:

 

 

可以看到Apache ShardingSphere整个生态圈的功能点多且强大。每个功能点展开来讲,即可组成一个系列课程。限于篇幅所限,本次分享主要为大家介绍数据分片的内容,并结合京东落地实战,讲解数据分片在落地过程中遇到的问题以及对应的解决方法。

 

  • 数据分片在ShardingSphere中主要被划分为读写分离、数据拆分。读写分离主要是指:为数据库搭建灾备副本,并在访问时将这些生产及灾备库分为主库、从库两种角色。其中主库处理所有的修改、变更操作以及少部分读操作;从库分担主库大部分的读请求。

  • 数据拆分在这里主要指数据水平分片,即真正意义上将一个数据库拆分成多个分库,分别存储及访问。具体架构如下图所示:

 

 

在此基础上,很多业务系统出于性能和安全考虑,会选择这两种方式的混合部署架构,即同时使用读写分离和水平分片策略,如下图所示:

 

 

在这种情况下,底层数据的架构网络就会显得异常复杂和繁琐。因为在整个分布式的数据库系统当中会存在:分库1、分库2……,还有对应的从库1、从库2……

 

对业务开发的同学来讲,自身的精力和注意力不仅要放到跟KPI挂钩的业务代码开发上,还需要考虑如何实现和维护这样一套分布式数据库系统。

 

如何避免重复造轮子?如何将工作重心只落在自己的业务开发上?

 

Apache ShardingSphere便为大家充当这样一个实现并维护分布式数据库系统的管理员。作为一款分布式数据库中间件,它将为大家解决这些场景下的数据库管理维护的工作。

 

通过引入这层中间件,让业务开发像使用一个数据库一样去使用整个复杂繁琐的分布式数据库系统,而完全无需关心底层所有的分库以及读写库的使用和维护,如下图所示:

 

 

那么,Apache ShardingSphere是如何做到的呢?

 

首先,它为用户提供了各种内置的分片策略方式,并开放了自定义分片策略接口,用于帮助用户完成特殊场景下的分片需求。

 

数据分片的重中之重是:如何去拆分数据库表?

 

这将关系到今后整个数据库系统的性能、与业务系统的匹配默契程度。ShardingSphere提供了如哈希取模、范围划分、标签分类、时间范围以及复合分片等多种切分策略。

 

举例来说,业务方有可能会按照订单号后几十位做哈希取模来切分库表;也有可能将日志文件信息按照日、月、年的维度进行切分数据,并存储到数据库;还可能按照业务类型进行分库分表等。

 

针对各式各样的业务场景,ShardingSphere提供了以下多种分片策略。虽然这些分配策略基本可以满足80%以上业务方需求,但还是会存在一些变态的业务场景。

 

为此,我们开放了数据分片策略的接口,业务方可以选择按照自己的变态需求实现这些数据分片接口,ShardingSphere就会通过SPI的方式将其加载使用。

 

 

在确定好数据分片策略后,ShardingSphere将使用该分片策略进行以下操作来完成对某条SQL的DDL&DML&DAL&DQL&TCL等操作。

 

但是这个过程对用户来说是透明的,即在用户无感知的情况下,ShardingSphere将用户输入的SQL进行解析,然后依据用户指定的分片策略对这条不含分片信息的SQL进行改写,将其改写成为真正在某个或多个数据表上执行的某条或多条真实的SQL。

 

此外,还需要找到每一条真实的SQL究竟需要在哪个库的哪张分表上执行,最终把改写后的真实SQL下发到对应的分表上进行多线程的执行。而用户会将拿到最终汇总后的数据结果集。

 

 

2、接入端介绍
 

 

Apache ShardingSphere作为一个生态圈,为用户提供了多款接入端以满足用户不同应用场景的需求。分别为:

 

  • Sharding-JDBC,一款轻量级的JAVA框架,面向JAVA开发更为友好;

  • Sharding-Proxy,独立部署的实现了MySQL二进制协议的服务器端版本,支持异构语言;

  • Sharding-Sidecar,配合云原生环境使用,面向Service Mesh使用。

 

目前,Sharding-JDBC和Sharding-Proxy可用于生产,Sharding-Sidecar还在开发中。

 

1)Sharding-JDBC

 

Sharding-JDBC被定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

 

  • 适用于任何基于Java的ORM框架,如:JPA、Hibernate、Mybatis、Spring JDBC Template或直接使用JDBC。

  • 基于任何第三方的数据库连接池,如:DBCP、C3P0、BoneCP、Druid、HikariCP等。

  • 支持任意实现JDBC规范的数据库。目前支持MySQL、Oracle、SQLServer和PostgreSQL。

 

 

2)Sharding-Proxy

 

Sharding-Proxy被定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。

 

目前先提供MySQL版本,它可以使用任何兼容MySQL协议的访问客户端(如:MySQL Command Client、MySQL Workbench等)操作数据,对DBA更加友好:

 

  • 向应用程序完全透明,可直接当做MySQL使用。

  • 适用于任何兼容MySQL协议的客户端。

 

 

3)Sharding-Sidecar

 

Sharding-Sidecar被定位为Kubernetes或Mesos的云原生数据库代理,以DaemonSet的形式代理所有对数据库的访问。 

 

通过无中心、零侵入的方案提供与数据库交互的的啮合层,即Database Mesh,又可称数据网格。

 

Database Mesh的关注重点在于如何将分布式的数据访问应用与数据库有机串联起来,它更加关注的是交互,是将杂乱无章的应用与数据库之间的交互有效的梳理。

 

使用Database Mesh,访问数据库的应用和数据库终将形成一个巨大的网格体系,应用和数据库只需在网格体系中对号入座即可,它们都是被啮合层所治理的对象。

 

 

三、Apache ShardingSphere

京东落地实战

 

当前ShardingSphere已在京东落地很多大小业务,这里只是列举较为大型的系统,这些业务系统有的是重要程度较高,有的是业务较为新颖。如下图所示:

 

 

从这个案例中可以看到:

 

  • 大家熟知的白条业务以及运维部门的监控系统-秒级监控主要使用ShardingSphere的数据分片功能及正在开发的弹性伸缩功能,使用到的主要有Sharding-JDBC和Sharding-Proxy;

  • 四要素加密主要是来自数据安全和审计的要求,主要使用到了数据脱敏的功能模块,所采用的产品是Sharding-JDBC;

  • 而城市计算这一新颖的业务,主要使用到了ShardingSphere的数据库治理模块,包括高可用管理和权限控制等。

 

每一个落地案例都可以成为独立的分享来为大家讲解,本次分享主要为大家介绍落地白条业务的实战情况。

 

在这个落地过程中,我特意总结了落地实战遇到的问题,已经对应的解决方案。我相信在各位的生产实践中多少都会遇到类似的问题,希望这些解决方案能给予大家相关经验和思考,送人玫瑰,手留余香。

 

主要遇到的问题以及对应的解决方案可参考下图所示:

 

 

1、SQL兼容程度
 

 

通过上面的讲解,大家可以看到使用上任何一款分布式数据库中间件都会面临一个问题:SQL是否全支持?

 

因为一条不含分片信息的SQL是需要经过解析、改写、路由、执行、归并这些步骤的,所以对SQL的加工处理,有可能会致使中间件对于部分SQL是不支持的。

 

在我们真正落地白条业务时,也出现了这个问题。

 

白条业务的业务逻辑非常复杂且庞大,同时多样化场景的需求对SQL的兼容程度有较高要求。

 

ShardingSphere为了能全面支撑白条业务,进行了两方面的优化重构:

 

  • 一方面是重构了SQL解析模块;

  • 另一方面是在除了解析模块之外的模块对更多的SQL进行兼容支持,例如COUNT(DISTINCT *) 等SQL。

 

SQL解析模块是中间件的基石,如果基石不牢靠,上层建筑将岌岌可危。

 

从第一代的解析引擎使用Druid的内置解析引擎到第二代自研了SQL解析引擎,再到现在使用Antlr解析器作为SQL解析器,经历了2年之久。

 

耗时费力如此之多,只为了真正搭建好基石,做到解析引擎自主可控、对SQL高效全面支持。当前,SQL支持情况为:

 

  • 路由至单节点,SQL100%支持;

  • 路由至多节点,全面支持DQL、DML、DDL、DCL、TCL和MySQL的部分DAL。支持分页、去重、排序、分组、聚合、关联查询(不支持跨库关联);

  • 具体支持情况,详见:

    https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/ 

 

2、分布式主键
 

 

传统数据库软件开发中,主键自动生成技术是基本需求。而各个数据库对于该需求也提供了相应的支持,比如MySQL的自增键、Oracle的自增序列等。 

 

数据分片后,不同数据节点生成全局唯一主键是非常棘手的问题。同一个逻辑表内的不同实际表之间的自增键由于无法互相感知而产生重复主键。 

 

虽然可通过约束自增主键初始值和步长的方式避免碰撞,但需引入额外的运维规则,使解决方案缺乏完整性和可扩展性。

 

目前有许多第三方解决方案可以完美解决这个问题,如UUID等依靠特定算法自生成不重复键,或者通过引入主键生成服务等。

 

为了方便用户使用、满足不同用户不同使用场景的需求,ShardingSphere提供了内置的分布式主键生成器,例如UUID、SNOWFLAKE等分布式主键生成器,用户仅需简单配置即可使用,生成全局性的唯一自增ID。

 

此外,我们还抽离出分布式主键生成器的接口,方便用户自行实现自定义的自增主键生成算法,以满足用户特殊场景的需求。

 

3、业务分片键值注入
 

 

通过解析SQL语句提取分片键列与值并进行分片,是ShardingSphere对SQL零侵入的实现方式。

 

若SQL语句中没有分片条件,则无法进行分片,需要全路由。在一些应用场景中,分片条件并不存在于SQL,而存在于外部业务逻辑。因此需要提供一种通过外部指定分片结果的方式,在ShardingSphere中叫做Hint。

 

ShardingSphere使用ThreadLocal管理分片键值。可以通过编程的方式向HintManager中添加分片条件,该分片条件仅在当前线程内生效。

 

除了通过编程的方式使用强制分片路由,ShardingSphere还计划通过SQL中的特殊注释的方式引用Hint,使开发者可以采用更加透明的方式使用该功能。指定了强制分片路由的SQL将会无视原有的分片逻辑,直接路由至指定的真实数据节点。

 

下面的图片将给出这一场景的具体实施案例:

 

 

通过向HintManager注入status和具体路由表的关系,ShardingSphere将按照用户指定规则,强制到db_0.t_order_1执行SQL,并将结果返回给用户。

 

4、性能优化
 

 

性能问题是任何一个上线系统在面临业务高峰时都必须要考虑的问题。面对京东白条这个量级的应用,ShardingSphere为了满足白条业务对TPS/QPS的强制要求,做了多方面优化,主要为:

 

  • SQL解析结果缓存;

  • JDBC元数据信息缓存;

  • Bind表&广播表的使用;

  • 自动化执行引擎&流式归并。

 

受篇幅所限,这里主要为大家介绍Bind表和广播表使用。这两种表的配置使用,主要是为了优化表关联问题中,切分表与切分表之间笛卡尔积表关联的情况,以及解决跨库表关联不支持的情况。

 

绑定表是指分片规则一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,从而关联查询效率将大大提升。

 

因为主表和子表使用相同的分片策略,数据在主表和子表的分布情况将一模一样,所以表关联查询的时候就能避免笛卡尔积。举例说明,如果SQL为:

 

 
SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

在不配置绑定表关系时,假设分片键order_id将数值10路由至第0片,将数值11路由至第1片,那么路由后的SQL应该为4条,它们呈现为笛卡尔积:

 

 
SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

 
SELECT i.* FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

 
SELECT i.* FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

 
SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

在配置绑定表关系后,路由的SQL应该为2条:

 

 
SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

 
SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);

 

其中t_order在FROM的最左侧,ShardingSphere将会以它作为整个绑定表的主表。

 

所有路由计算将会只使用主表的策略,那么t_order_item表的分片计算将会使用t_order的条件。故绑定表之间的分区键要完全相同。

 

广播表是指所有底层分片数据源中都存在的表,表结构和表中的数据在每个分库中完全一致。

 

这样在进行关联查询的时候,由于广播表在所有分库均存在,就避免了笛卡尔积关联查询以及跨库关联的情况。比较适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。

 

四、Apache ShardingSphere

迭代&规划

 

Apache ShardingSphere的发展及规划如下图所示:

 

 

官网及GitHub也欢迎大家的访问:

 

  • 官网: 

    https://shardingsphere.apache.org/

  • GitHub:

    https://github.com/apache/incubator-shardingsphere

 

 

五、写在最后

 

感谢各位朋友能阅读到文章最后,当然也可能是直接跳到了这里。这篇文章来自于线上的分享,有兴趣的朋友可以回顾线上分享,应该会比文字更生动有趣一些。

 

从最开始入职做DBA到现在转为分布式数据库中间件JAVA开发程序猿,也开始在开源领域里去探索寻找自我定位和意义。互联网行业如同大海航行时代,波涛汹涌,变化万千。

 

愿所有朋友都能做好舵手,直挂云帆济沧海。

 

直播回放
 

 

https://m.qlchat.com/topic/details?topicId=2000003991669127





最新评论
访客 2023年08月20日

230721

访客 2023年08月16日

1、导入Mongo Monitor监控工具表结构(mongo_monitor…

访客 2023年08月04日

上面提到: 在问题描述的架构图中我们可以看到,Click…

访客 2023年07月19日

PMM不香吗?

访客 2023年06月20日

如今看都很棒

活动预告