You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ki...@apache.org on 2020/06/16 08:30:25 UTC

[shardingsphere] branch master updated: update blog (#6071)

This is an automated email from the ASF dual-hosted git repository.

kimmking pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new b606232  update blog (#6071)
b606232 is described below

commit b606232bf5e13e786f9c4f2d349ab32b743b9412
Author: wubingting <49...@users.noreply.github.com>
AuthorDate: Tue Jun 16 16:30:09 2020 +0800

    update blog (#6071)
    
    Co-authored-by: unknown <wu...@360buyad.local>
---
 docs/blog/content/material/ANTLR.cn.md       | 370 ++++++++++++++++++++++++++
 docs/blog/content/material/ANTLR.en.md       |   7 +
 docs/blog/content/material/CNCF.cn.md        |  35 +++
 docs/blog/content/material/CNCF.en.md        |   7 +
 docs/blog/content/material/ElasticJob.cn.md  |  26 ++
 docs/blog/content/material/ElasticJob.en.md  |  26 ++
 docs/blog/content/material/committer.cn.md   |  90 +++++++
 docs/blog/content/material/committer.en.md   |   7 +
 docs/blog/content/material/database.cn.md    | 299 +++++++++++++++++++++
 docs/blog/content/material/database.en.md    |   7 +
 docs/blog/content/material/engine.cn.md      | 183 +++++++++++++
 docs/blog/content/material/engine.en.md      |   7 +
 docs/blog/content/material/proxy.cn.md       | 297 +++++++++++++++++++++
 docs/blog/content/material/proxy.en.md       |   7 +
 docs/blog/content/material/realization.cn.md | 382 +++++++++++++++++++++++++++
 docs/blog/content/material/realization.en.md |   7 +
 docs/blog/content/material/result.cn.md      | 184 +++++++++++++
 docs/blog/content/material/result.en.md      |   7 +
 docs/blog/content/material/seata.cn.md       |  71 +++++
 docs/blog/content/material/seata.en.md       |   7 +
 docs/blog/content/material/solution.cn.md    | 247 +++++++++++++++++
 docs/blog/content/material/solution.en.md    |   7 +
 22 files changed, 2280 insertions(+)

diff --git a/docs/blog/content/material/ANTLR.cn.md b/docs/blog/content/material/ANTLR.cn.md
new file mode 100644
index 0000000..c01ccd6
--- /dev/null
+++ b/docs/blog/content/material/ANTLR.cn.md
@@ -0,0 +1,370 @@
++++
+title = "关于SQL解析,为何编程语言解析器ANTLR更胜一筹?"
+weight = 2
+chapter = true
++++
+
+## 关于SQL解析,为何编程语言解析器ANTLR更胜一筹?
+
+本文转载自:DBAplus社群
+
+
+### 作者介绍
+
+**杜红军**,京东数科软件工程师,多年中间件开发及系统设计经验,对Spring、MyBatis等相关开源技术有深入了解。目前在Sharding-Sphere团队负责SQL解析开发工作。
+
+  
+
+相对于其他编程语言来说,SQL是比较简单的。不过,它依然是一门完善的编程语言,因此对SQL的语法进行解析,与解析其他编程语言(如:Java语言、C语言、Go语言等)并无本质区别。  
+
+  
+
+### 一、概念
+
+  
+
+谈到SQL解析,就不得不谈一下文本识别。文本识别是根据给定的规则把输入文本的各个部分识别出来,再按照特定的数据格式输出。以树形结构输出是最常见的方式,这就是通常所说的抽象语法树(AST)。
+
+  
+
+作为一个开发者,文本识别每天都和我们打交道。在编写完代码之后,编译器在编译时首先需要根据程序的语法对代码做解析,即文本识别,并生成中间代码。
+
+  
+
+SQL解析和程序代码解析类似,它按照SQL语法对SQL文本进行解析,识别出文本中各个部分然后以抽象语法树的形式输出。SQL也是一门编程语言,它并不比其他编程语言的语法简单。一个复杂的建表语句占用20多k字节也是正常的。
+
+  
+
+无论是对SQL进行解析,还是对其他编程语言的语法进行解析,都需要专门的解析器。从零开发则需要较长的时间,而且各种数据库的SQL方言不尽相同,这并不是一套能够完全通用的SQL解析引擎。在各种第三方类库十分完善的现今,找寻一个利器,比从零开发这种刀耕火种的方式好得多。开源的SQL解析器有JSQLParser、FDB和Druid等,用于语法解析的主要有ANTLR、JavaCC等。
+
+  
+
+JSQLParser是一个通用的SQL解析器,它提供一站式的SQL解析能力,将SQL转化为语法树,并提供树访问接口供程序遍历语法树。虽然使用便利,但它也有一些缺点:
+
+  
+
+*   无法根据所需的语法生成解析器。对于数据分片所需要的语法来说,它不如ANTLR这样能够根据自己需求书写语法规则的方式轻量级;
+    
+*   只支持部分常用的标准SQL语法,像ALTER TABLE、ALTER INDEX、DCL以及各类数据库的方言支持的力度不足;
+    
+*   它采用Visitor模式将抽象语法树完全封装,外围程序无法直接访问抽象语法树,在无需完全遍历树时,代码比较繁琐。
+    
+
+  
+
+FDB和Driuid与JSQLParser同类型。它们无需自定义SQL语法,可以拿来即用,但缺乏自定义语法的灵活度。
+
+  
+
+相对来说,ANTLR则好一些。它并非为SQL解析专门定制的解析器,而是通用的编程语言解析器。它只需编写名为G4的语法文件,即可自动生成解析的代码,并且以统一的格式输出,处理起来非常简单。由于G4文件是通过开发者自行定制的,因此由ANTLR所生成的代码也更加简洁和个性化。在编写仅适用于数据分片的语法规则时,可以简化大量无需关注的SQL语法。对于SQL审计等SQL解析的需求,完全可以用ANTRL编写另外一份语法规则,可以达到因地制宜的效果。JavaCC与ANTLR类似,都属于自定义语法类型的解析器。
+
+  
+
+无论采用哪种解析器,解析过程都是一致的,它分为词法解析(Lexer)和语法解析(Parser)两部分。
+
+  
+
+#### 1、词法解析
+
+先通过词法解析器将SQL拆分为一个个不可再分的词法单元(Token)。在SQL语法中,通常将词法单元分为关键字、标识符、字面量、运算符和分界符。
+
+  
+
+*   **关键字**:数据库引擎所用到的特殊词,为保留字符,不能用做标识符;
+    
+*   **标识符**:在SQL语法中是表名称、列名称等。对应于编程语言则是包名、类名、方法名、变量名、属性名等等;
+    
+*   **字面量**:包括字符串和数值;
+    
+*   **运算符**:包括加减乘除、位运算、逻辑运算等;
+    
+*   **分界符**:逗号、分号、括号等。
+    
+
+  
+
+词法解析器每次读取一个字符,在当前字符与之前的字符所属分类不一致时,即完成一个词法单元的识别。例如,读取SELECT时,第一个字符是’S’,满足关键字和标示符的规则,第二个字符’E’也同样满足,以此类推,直到第7个字符是空格时,则不满足该规则,那么就完成了一个词法单元的识别。SELECT既是SQL规范定义的关键字,又同时满足标识符规则,因此当一个词法单元是标识符时,解析器需要有优先级的判断,需要先确定它是否为关键字。其他的规则相对简单,如:以数字开头的字符则根据数值规则的字面量读取字符;以双引号或单引号开头的则根据字符串规则的字面量读取字符;运算符或分界符就更易识别。举例说明,以下SQL:
+
+```
+SELECT id, name FROM product WHERE id > 10;
+```
+  
+
+识别之后的词法单元为:
+
+- 关键字:SELECT、FROM、WHERE
+- 标识符:id、name、product
+- 字面量:10
+- 运算符:>
+- 分界符:,和;
+
+
+    
+
+#### 2、语法解析
+
+  
+
+语法解析器每次从词法解析器中获取一个词法单元。如果满足规则,则继续下一个词法单元的提取和匹配,直至字符串结束;若不满足规则,便提示错误并结束本次解析。
+
+  
+
+语法解析难点在于规则的循环处理以及分支选择,还有递归调用和复杂的计算表达式等。
+
+  
+
+在处理循环规则时,当匹配完成一个规则时,匹配规则需要循环地再次匹配当前规则,当其不再是当前的规则定义时,才可以继续进行后续规则的匹配。以CREATE TABLE语句为例。每张表可以包含多列,每个列都可能需要定义名称、类型、精度等参数。
+
+  
+
+当一个规则中存在多条分支路径时,则需要超前搜索,语法解析器必须和每个可能的分支进行匹配来确定正确的路径。以ALTER TABLE语句为例。
+
+  
+
+修改表名语法为:
+
+  
+```
+ALTER TABLE oldTableName RENAME TO newTableName;
+```
+  
+
+删除列的语法为:
+
+  
+```
+ALTER TABLE tableName DROP COLUMN columnName;
+```
+  
+
+两个语句均以ALTER TABLE开头,它们合并在一起的语法为:
+
+  
+```
+ALTER TABLE tableName (RENAME TO newTableName | DROP COLUMN columnName);
+```
+  
+
+匹配完成tableName之后的2个分支选项,需要超前搜索来确定正确的分支。
+
+  
+
+在选择分支时,可能会出现一个分支是另一个分支的子集。此时,当成功匹配短路径时,需要进一步匹配长路径,在无法匹配长路径时,再选取短路径,这称之为贪婪匹配。如果不使用贪婪匹配的算法,则最长的分支规则便永远不能被匹配了。
+
+  
+
+当词法单元不满足一个可选规则时,则需要与下个规则做匹配,直至匹配成功或与下个非可选规则匹配失败。在CREATE TABLE语句中,定义列时存在很多可选项,比如是否为空、是否主键、是否存在约束条件等。
+
+  
+
+语法解析器最终将SQL转换为抽象语法树。例如以下SQL:
+
+  
+```
+SELECT id, name FROM t_user WHERE status = 'ACTIVE' AND age > 18
+```
+  
+
+解析之后的为抽象语法树见下图:
+
+  
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/ANTLR1.jpg)
+
+  
+
+为了便于理解,抽象语法树中的关键字的Token用绿色表示,变量的Token用红色表示,灰色表示需要进一步拆分。
+
+  
+
+语法解析要比词法解析复杂一些,词法解析的规则相对简单,定义好词法单元的规则即可,极少出现分支选择;而且只需超前搜索一个字符即可确定词法单元。但它却是解析的基础,如果分词出现错误,语法解析则很难正确处理。
+
+  
+
+生成抽象语法树的第三方工具有很多,ANTLR是不错的选择。它将开发者定义的规则生成抽象语法树的Java代码并提供访问者接口。相比于代码生成,手写抽象语法树在执行效率方面会更加高效,但是工作量也比较大。在性能要求高的场景中,可以考虑定制化抽象语法树。
+
+  
+
+### 二、ANTLR
+
+  
+
+#### 1、介绍
+
+  
+
+ANTLR是Another Tool for Language Recognition的简写,是一个用Java语言编写的识别器工具。它能够自动生成解析器,并将用户编写的ANTLR语法规则直接生成目标语言的解析器,它能够生成Java、Go、C等语言的解析器客户端。
+
+  
+
+ANTLR所生成的解析器客户端将输入的文本生成抽象语法树,并提供遍历树的接口,以访问文本的各个部分。ANTLR的实现与前文所讲述的词法分析与语法分析是一致的。词法分析器根据语法规则做词法单元的拆分;语法分析器对词法单元做语义分析,并对规则进行优化以及消除左递归等操作。
+
+  
+
+#### 2、ANTLR语法规则
+
+  
+
+ANTLR语法规则的主要工作是定义词法解析规则和语法解析规则。ANTLR约定词法解析规则以大写字母开头,语法解析规则以小写字母开头。下面简单介绍一下ANTLR的规则。
+
+  
+
+首先需要定义Grammar类型及名称,名称必须和文件名一样。有Lexer、Parser、Tree和Combine这4种语法类型。
+
+  
+
+*   Lexer定义词法分析规则;
+    
+*   Parser 定义语法分析规则;
+    
+*   Tree用于遍历语法分析树;
+    
+*   Combine既可以定义语法分析规则,也可定义词法分析规则,规则名称遵循上述规则;
+    
+*   Import 用于导入语法规则。使用Import语法规则分类,可以使语法规则更加清晰;并且可以采用面向对象的思想设计规则文件,使其具有多态及继承的思想。值得注意的是,当前规则的优先级高于导入规则。
+    
+
+  
+
+规则名称及内容以冒号分隔,分号结尾。例如:
+
+  
+```
+NUM:[0-9]+;
+```
+
+规则的名称是NUM,以大写字母开头,因此是词法分析的规则;规则的内容是[0-9]+,表示所有的整数。
+
+ANTLR规则基于BNF范式,用’|’表示分支选项,’*’表示匹配前一个匹配项0次或者多次,’+’ 表示匹配前一个匹配项至少一次。
+
+语法其它部分,读者感兴趣的话请查阅官方文档。
+
+ANTLR生成SQL解析器,首先就是要定义SQL的词法解析器和语法解析器,下面一一介绍。
+
+
+
+  
+
+#### 3、ANTLR的词法解析
+
+  
+
+与之前的SQL解析原理相同,ANTLR的词法解析同样是将SQL拆分为词法单元。ANTLR解析词法规则时,并不理解规则的具体含义,不清楚哪些规则是关键字定义,哪些规则是标识符定义,它会根据读取顺序为每个规则编号,编号靠前的规则将优先匹配,匹配成功则直接返回该词法单元。在设计词法拆分规则时,需要将标识符规则放置在关键字规则之后,确保关键字匹配失败后,再去匹配标识符。
+
+  
+
+ANTLR采用状态转换表实现字符的匹配。它将词法拆分规则转换为表格,每次读取一个字符,根据当前字符类型及当前状态查询该表,并判断读入字符是否匹配规则。如果规则匹配,则接受该字符,并继续读取下个字符;如果规则不匹配,则拒绝接受该字符。此时,若当前状态是成功匹配某一词法单元的可接受状态,则返回该词法单元;反之则提示错误。以此类推,如果接受该字符,则继续读取下一字符。直至成功返回一个词法单元或匹配失败提示错误。
+
+  
+
+举例说明,以下是一个简易的查询语句词法拆分规则:
+
+  
+```
+lexer grammar SelectLexer;
+SELECT: [Ss] [Ee] [Ll] [Ee] [Cc] [Tt];
+FROM: [Ff] [Rr] [Oo] [Mm];
+WHERE: [Ww] [Hh] [Ee] [Rr] [Ee];
+LEFT: [Ll][Ee][Ff][Tt];
+RIGHT: [Rr][Ii][Gg][Hh][Tt];
+INNER: [Ii][Nn][Nn][Ee][Rr];
+JOIN: [Jj] [Oo] [Ii] [Nn];
+ON : [Oo][Nn];
+BETWEEN: [Bb] [Ee] [Ee] [Rr] [Ee];
+AND: [Aa] [Nn] [Dd];
+OR:[Oo][Rr];
+GROUP: [Gg] [Rr] [Oo] [Uu] [Pp];
+BY:[Bb] [Yy];
+ORDER: [Oo] [Rr] [Dd] [Ee] [Rr];
+ASC:[Aa][Ss][Cc];
+DESC:[Dd][Ee][Ss][Cc];
+IN: [Ii][Nn];
+ID: [a-zA-Z0-9]+;
+WS:  [ ] + ->skip;
+```
+  
+
+它定义了大小写不敏感的从SELECT到IN的关键字规则以及标识符规则ID,标识符规则放在最后。WS规则表示遇到空格、制表符、换行符跳过。输入字符中任何字符,在词法分析器中都要找到对应的规则,否则会提示失败。如果去掉WS规则,对于包含空格的SQL将会得到以下的错误提示。
+
+  
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/ANTLR2.jpg)
+
+  
+
+错误原因是第1行的第6、第10以及第11个字符是回车换行符,词法规则找不到对应的规则。
+
+  
+
+#### 4、ANTLR的语法解析
+
+  
+
+ANTLR的语法解析用于定义组成语句的短语规则。语法规则由各个数据库厂商提供,因此,在SQL解析时,只需要将它们转换为ANTLR的语法规则即可。需要注意的是,SQL表达式的规则定义十分复杂。不仅包括常见的数学表达式和布尔表达式,还包括函数调用以及各数据库的私有日期表达式、Window函数、Case语句等。
+
+  
+
+ANTLR同样采用状态转换表的方式检查词法单元是否满足语法规则。语法分析器调用词法分析器获取词法单元并其检查是否符合规则。当遇到多个选项分支时,则采用贪婪匹配原则,优先走完最长路径的分支。如果分支中有多个规则满足条件,按顺序匹配。
+
+  
+
+以如下规则举例说明:
+
+  
+```
+grammar Test;
+ID: [a-zA-Z0-9]+;
+WS:  [ ] + ->skip;
+testAll:test1 |test2|test3|test21;
+test1:ID;
+test2:ID ID;
+test21:ID ID;
+test3:ID ID ID;
+test4:test1+;
+```
+  
+
+使用testAll规则做如下测试:
+
+  
+
+*   当输入的参数为“a1 a2 a3”时,使用test3分支,而并未使用(test1 a1) (test1 a2) (test1 a3)或(test2 a1 a2) (test1 a3)这种匹配模式;
+    
+*   当输入的参数为“a1 a2”时,虽然test21规则也能够匹配,但前面有test2规则匹配,因此使用test2规则;
+    
+*   当输入的参数为“a1 a2 #”,由于无法匹配‘#’,因此提示错误。
+    
+
+  
+
+#### 5、分片上下文提取
+
+  
+
+完成了SQL解析之后,最后一步便是对数据分片所需的上下文进行提取。它通过对SQL的理解,以访问抽象语法树的方式去提炼分片所需的上下文,并标记有可能需要改写的位置。供分片使用的解析上下文包含查询选择项(Select Items)、表信息(Table)、分片条件(Sharding Condition)、自增主键信息(Auto increment Primary Key)、排序信息(Order By)、分组信息(Group By)以及分页信息(Limit、Rownum、Top)等。
+
+  
+
+### 三、Sharding-Sphere中的SQL解析
+
+  
+
+SQL解析作为分库分表类产品的核心,其性能和兼容性是最重要的衡量指标。
+
+  
+
+Sharding-Sphere的前身,Sharding-Sphere在1.4.x之前的版本使用Druid作为SQL解析器。经实际测试,它的性能远超其它解析器。
+
+  
+
+从1.5.x版本开始,Sharding-Sphere采用完全自研的SQL解析引擎。由于目的不同,Sharding-Sphere并不需要将SQL转为一颗完全的抽象语法树,也无需通过访问器模式进行二次遍历。它采用对SQL“半理解”的方式,仅提炼数据分片需要关注的上下文,因此SQL解析的性能和兼容性得到了进一步的提高。
+
+  
+
+在最新的3.x版本中,Sharding-Sphere尝试使用ANTLR作为SQL解析的引擎,并计划根据DDL->TCL->DAL–>DCL->DML–>DQL这个顺序,依次替换原有的解析引擎。使用ANTLR的原因是希望Sharding-Sphere的解析引擎能够更好地对SQL进行兼容。对于复杂的表达式、递归、子查询等语句,虽然Sharding-Sphere的分片核心并不关注,但是会影响对于SQL理解的友好度。自研的SQL解析引擎为了性能的极致,对这些方便并未处理,使用时会直接报错。
+
+  
+
+经过实例测试,ANTLR解析SQL的性能比自研的SQL解析引擎慢3倍左右。为弥补差距,Sharding-Sphere将使用Prepared Statement的SQL解析的语法树放入缓存。因此建议采用PreparedStatement这种SQL预编译的方式提升性能。Sharding-Sphere会提供配置项,将两种解析引擎共存,交由用户抉择SQL解析的兼容性与性能。
+
+  
diff --git a/docs/blog/content/material/ANTLR.en.md b/docs/blog/content/material/ANTLR.en.md
new file mode 100644
index 0000000..9c36997
--- /dev/null
+++ b/docs/blog/content/material/ANTLR.en.md
@@ -0,0 +1,7 @@
++++
+title = "ANTLR"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/CNCF.cn.md b/docs/blog/content/material/CNCF.cn.md
new file mode 100644
index 0000000..10f679c
--- /dev/null
+++ b/docs/blog/content/material/CNCF.cn.md
@@ -0,0 +1,35 @@
++++
+title = "CNCF全景图"
+weight = 2
+chapter = true
++++
+
+## 快讯!Apache ShardingSphere进入CNCF全景图
+
+### CNCF
+
+(Cloud Native Computing Foundation),是由Google牵头创立的云原生计算开源软件基金会。它致力于云原生(Cloud Native)技术的普及和可持续发展。云原生技术是通过一系列的软件、规范和标准帮助企业和组织,在现代的动态环境(如公共云、私有云和混合云)中构建和运行敏捷的、可扩展的应用程序。容器、微服务、微服务治理、声明式API等都是代表性的云原生技术。
+
+### CNCF Landscape
+
+(https://github.com/cncf/landscape) 是CNCF中的一个重要项目,它旨在为云原生应用者提供一个资源地图,帮助企业和开发人员快速了解云原生体系的全貌。
+
+CNCF将云原生的生态圈横向划分为五层,并且针对它们又纵向规划出两部分,作为横向五层的共用层。横向划分的五层分别是:应用定义与开发、编排与治理、运行时、供应保障和云设施。纵向划分的两部分是:观察与分析和平台。将这些功能整合起来即是一个完善的云平台服务产品,全景图如下:
+
+-- 以上内容摘自书籍《未来架构:从服务化到云原生》
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/CNCF1.jpg)
+
+### ShardingSphere
+
+北京时间2019年6月28日,Apache ShardingSphere进入CNCF Landscape。在全景图App Definition Development-Database领域占有一席之地,如下图所示。
+
+Apache ShardingSphere在开源领域及云原生领域会持续拓展,不断精进,构建有机开源生态圈!
+
+我们也希望有更多开源及云原生社区的爱好者能加入我们,共同前进,促进Apache ShardingSphere社区及贡献者们共同成长!
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/CNCF2.jpg)
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/CNCF3.jpg)
+
+Apache ShardingSphere(Incubating)自2016开源以来,不断精进、不断发展,被越来越多的企业和个人认可:Github上收获8000+的stars,近百家公司企业的成功案例。此外,越来越多的企业和个人也加入到Apache ShardingSphere(Incubating)的开源项目中,为它的成长和发展贡献了巨大力量。
diff --git a/docs/blog/content/material/CNCF.en.md b/docs/blog/content/material/CNCF.en.md
new file mode 100644
index 0000000..140f167
--- /dev/null
+++ b/docs/blog/content/material/CNCF.en.md
@@ -0,0 +1,7 @@
++++
+title = "CNCF"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/ElasticJob.cn.md b/docs/blog/content/material/ElasticJob.cn.md
new file mode 100644
index 0000000..7085451
--- /dev/null
+++ b/docs/blog/content/material/ElasticJob.cn.md
@@ -0,0 +1,26 @@
+
++++
+title = "ElasticJob"
+weight = 2
+chapter = true
++++
+
+## 快讯!分布式调度项目ElasticJob即将重新起航
+
+[ElasticJob](https://github.com/elasticjob)是一个分布式调度解决方案,提供分布式任务的分片,弹性伸缩,全自动发现,基于时间驱动、数据驱动、常驻任务和临时任务的多任务类型,任务聚合和动态调配资源,故障检测、自动修复,失效转移和重试,完善的运维平台和管理工具,以及对云原生的良好支持等功能特性,可以全面满足企业对于任务管理和批量作业的调度处理能力。
+
+ElasticJob自2014年底开源以来,经历了5年多的发展,以其功能的丰富性,文档的全面性,代码的高质量,框架的易用性,积累了大量的忠实用户和良好的业内口碑(5.8K star),一直也是分布式调度框架领域最受大家欢迎的项目之一。
+
+近两年来,由于核心开发者全力发展和维护Apache ShardingSphere项目等原因,ElasticJob放缓了发展的脚步。但是随着Apache ShardingSphere项目在分布式领域的不断拓展,以及用户对于多数据集群环境的分布式管理和数据迁移的弹性扩容等功能,需要一个强大的分布式调度组件。由此为契机,Apache ShardingSphere社区已经计划发起提议将ElasticJob作为其子项目进行长期持续的更新和维护。
+
+我们第一时间将此好消息公开,后续将带来更多关于ElasticJob的相关资讯。
+
+> 讨论邮件:
+https://lists.apache.org/thread.html/rd6171e2065be6bcfbeb7aba7e5c876eeed04db585c6ab78fc03a581c%40%3Cdev.shardingsphere.apache.org%3E
+
+
+> 捐赠Proposal:
+<br>https://cwiki.apache.org/confluence/display/SHARDINGSPHERE/ElasticJob+Donation+Proposal
+
+> 社区讨论:
+<br>https://github.com/elasticjob/elastic-job-lite/issues/728
diff --git a/docs/blog/content/material/ElasticJob.en.md b/docs/blog/content/material/ElasticJob.en.md
new file mode 100644
index 0000000..f7438d9
--- /dev/null
+++ b/docs/blog/content/material/ElasticJob.en.md
@@ -0,0 +1,26 @@
+
++++
+title = "ElasticJob"
+weight = 2
+chapter = true
++++
+
+## News! The distributed scheduling project ElasticJob is about to restart
+
+ElasticJob is a distributed scheduling solution that provides sharding of distributed tasks, elastic scaling, fully automatic discovery, lavish task types based on time-driven, data-driven, resident tasks and temporary tasks, task aggregation and dynamic resource allocation, fault detection, automatic repair, failover and retry. Perfect operation & maintenance platform and management tools as well as good support for cloud native can fully meet the needs of enterprises for task managemen [...]
+
+Since ElasticJob has been open sourced at the end of 2014, it has been more than 5 years. With its rich features, comprehensive documentation, high-quality code and ease of use of the framework, it has accumulated a large number of loyal users and a good industry reputation (5.8K star). It has been one of the most popular projects in the field of distributed scheduling framework.
+
+In the past two years, ElasticJob has slowed down its development due to core developers' efforts to develop and maintain the Apache ShardingSphere project. However, with the continuous expansion of the Apache ShardingSphere project in the distributed field and the user demands for functions such as distributed management of multiple data cluster environments and elastic expansion of data migration, a powerful distributed scheduling component is required. As a result, the Apache Sharding [...]
+
+We made this good news public for the first time and we will bring more information about ElasticJob in the future.
+
+> Discussion Email:
+https://lists.apache.org/thread.html/rd6171e2065be6bcfbeb7aba7e5c876eeed04db585c6ab78fc03a581c%40%3Cdev.shardingsphere.apache.org%3E
+
+
+> Donate Proposal:
+<br>https://cwiki.apache.org/confluence/display/SHARDINGSPHERE/ElasticJob+Donation+Proposal
+
+> Community Discussion:
+<br>https://github.com/elasticjob/elastic-job-lite/issues/728
diff --git a/docs/blog/content/material/committer.cn.md b/docs/blog/content/material/committer.cn.md
new file mode 100644
index 0000000..6b2df45
--- /dev/null
+++ b/docs/blog/content/material/committer.cn.md
@@ -0,0 +1,90 @@
++++
+title = "Committer"
+weight = 2
+chapter = true
++++
+## 成为Apache官方认可的Committer有什么优势
+
+### 什么是Apache软件基金会?
+
+Apache软件基金会(Apache Software Foundation),是当今最具影响力的非盈利性开源软件项目组织,正式成立于1999年,主要由开发者与用户的团体组成。在Apache软件基金会主导下,已有350多个顶级开源项目毕业,包括全球最著名的网络服务器软件Apache HTTP Server。秉持着“开放、创新、社区”的精神,很多Apache项目已经建立起强大成功的生态圈,社区充满活力。
+
+除了许多在信息技术领域十分具有影响力的项目外,Apache许可证(Apache License),Apache贡献者协议许可(CLAs)和开放合作的模式(Apache Way)也在业内有着突出的贡献,其影响力远远扩大到Apache软件基金会以外。
+
+Apache软件基金会如今已成为现代开源软件生态系统的基石。
+
+### 为什么要成为Apache committer?
+
+说了这么多,不管大家之前对Apache软件基金会了解到了什么程度,都可以看出,这是一个极具影响力的组织,在业内广受认可。
+
+如果能够成为一名官方承认的committer,不仅是对自己的极大认可,表明自身有能力参与到Apache级的项目开发中,并作出切实的贡献;而且还能够受到业内广泛尊重,无论是对求职还是升职加薪都很有帮助。
+
+简单来说,不管是和其他小伙伴们炫耀,还是写到简历上都倍儿有面子
+
+并且,官方认可的committer还会获取带@apache后缀的邮箱,还能名列Apache网站上
+
+(http://people.apache.org/committer-index.html)
+
+
+在世界上千百万的工程师中,只有极少数的人才能成为committer拥有这些特权,是不是很诱人呢?
+
+想象一下,小伙伴们浏览Apache网站时看到了你的名字,或者和面试官发邮件时,他们会不会有种不明觉厉的感觉,形象瞬间就高大上了有木有!
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/committer1.jpg)
+
+### 如何成为官方认可的committer?
+
+下面就是本篇文章的重点啦,需要做些什么,才会成为一名官方认可的committer呢?
+
+
+活跃地参与到Apache项目中,比如Apache ShardingSphere(Incubating)即可。
+
+
+
+不如从领个任务练练手开始?目前公布出的任务如下,欢迎领取:
+
+- 实现使用Inline表达式对Sharding-SpringBoot进行规则配置
+
+  https://github.com/sharding-sphere/sharding-sphere/issues/1686
+
+- 实现使用SpringBoot占位符方式对Sharding-SpringBoot进行规则配置
+
+  https://github.com/sharding-sphere/sharding-sphere/issues/1687
+
+
+我们以后也会定期在GitHub上以issue的方式发布一些开发功能任务, 欢迎通过订阅我们的邮件列表关注,具体方式可参照官网:
+
+http://shardingsphere.io/community/cn/contribute/subscribe/
+
+
+
+通过订阅Apache ShardingSphere的邮件列表,还可以了解到Apache ShardingSphere的最新项目进展,功能开发计划,Bug列表等;还能与ShardingSphere开发人员直接对话,讨论您遇到的问题,您的想法和建议等,我们一定会积极回复。
+
+P.S. ShardingSphere最近完成了向Apache过渡的重要一步,正式将官网和GitHub迁移到了Apache网站。
+
+以下是迁移后的网址:
+
+官网(http://shardingsphere.apache.org/)
+
+GitHub(https://github.com/apache/incubator-shardingsphere)
+
+### 结语
+Apache ShardingSphere(Incubating)自2016开源以来,不断精进、不断发展,被越来越多的企业和个人认可:Github上收获6000+的stars,70+公司企业的成功案例。此外,越来越多的企业和个人也加入到Apache ShardingSphere(Incubating)的开源项目中,为它的成长和发展贡献了巨大力量。
+
+
+
+我们从未停息过脚步,聆听社区伙伴的需求和建议,不断开发新的、强大的功能,不断使其健壮可靠!
+
+开源不易, 我们却愿向着最终的目标,步履不停!
+
+那么,正在阅读的你,是否可以助我们一臂之力呢?分享、转发、使用、交流,以及加入我们,都是对我们最大的鼓励!
+
+项目地址:
+
+https://github.com/apache/incubator-shardingsphere
+
+
+更多信息请浏览官网:
+
+http://shardingsphere.apache.org/
+
diff --git a/docs/blog/content/material/committer.en.md b/docs/blog/content/material/committer.en.md
new file mode 100644
index 0000000..3227366
--- /dev/null
+++ b/docs/blog/content/material/committer.en.md
@@ -0,0 +1,7 @@
++++
+title = "Committer"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/database.cn.md b/docs/blog/content/material/database.cn.md
new file mode 100644
index 0000000..ec736f2
--- /dev/null
+++ b/docs/blog/content/material/database.cn.md
@@ -0,0 +1,299 @@
++++
+title = "分布式数据库"
+weight = 2
+chapter = true
++++
+
+## 我们是怎样打造一款分布式数据库的
+
+作者 | 张亮
+
+关系型数据库在过去数十年的数据库领域一直占据着绝对主导的地位,它所带来的稳定性、安全性和易用性,成为了构建现代化系统的基石。随着的互联网高速发展,构架于单机系统的数据库已无法满足越来越高的并发请求和越来越大的数据存储需求,因此,分布式数据库被愈加广泛的采用。  
+  
+一直以来,数据库领域均由西方的科技公司和社区所主导。而今,越来越多的国产数据库解决方案以分布式为支点,逐渐在此领域有所建树。Apache ShardingSphere 是其中的一个分布式数据库解决方案,也是目前 Apache 软件基金会中唯一的数据库中间件。 
+
+### 1 背景
+
+全面兼容面向传统关系型数据库的 SQL 和事务,并且对分布式的天然友好,是分布式数据库解决方案的设计目标。它的核心功能主要集中在以下几点:
+
+- 分布式存储: 数据存储不受单机磁盘容量限制,可通过增加数据服务器的数量提升存储能力;
+    
+- 计算存储分离: 计算节点无状态,可通过水平扩展增加算力。存储节点和计算节点能够分层优化;
+    
+- 分布式事务: 高性能、完全支持本地事务 ACID 原义的分布式事务处理引擎;
+    
+- 弹性伸缩:可以随时随地的在不影响现有应用的情况下,动态对数据存储节点扩容和缩容;
+    
+- 多数据副本:自动将数据以强一致、高性能的方式复制至跨机房的多个副本,以保证数据的绝对安全;
+    
+- HTAP:采用同一套产品混合处理 OLTP 的事务型操作和 OLAP 的分析型操作。
+    
+
+分布式数据库的实现方案可以划分为进取型和稳定型。进取型实现方案是指开发全新架构的 NewSQL。这类产品以追求更高性能换取稳定性的缺失和运维经验的不足;稳定型的实现方案是指在现有数据库的基础上提供增量能力的中间件。这类产品则以牺牲部分性能以保证数据库的稳定性和运维经验的复用。
+
+### 2 架构
+
+Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar(计划中)这 3 款相互独立的产品组成。它们均提供标准化的数据分片、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。随着 Apache ShardingSphere 在查询优化器和分布式事务引擎的不断探索,它已渐渐地打破了实现方案的产品边界,向集进取型和稳定型于一身的平台级解决方案演进。
+
+**Sharding-JDBC**
+
+定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database1.jpg)
+
+**Sharding-Proxy**
+
+定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。目前已提供 MySQL 和 PostgreSQL 版本,它可以使用任何兼容 MySQL 和 PostgreSQL 协议的访问客户端 (如:MySQL Command Client, MySQL Workbench, Navicat 等) 操作数据,对 DBA 更加友好。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database2.jpg)
+
+**Sharding-Sidecar(规划中)**
+
+定位为 Kubernetes 的云原生数据库代理,以 Sidecar 的形式代理所有对数据库的访问。通过无中心、零侵入的方案提供与数据库交互的的啮合层,即 Database Mesh,又可称数据库网格。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database3.jpg)
+
+**计算存储分离的混合架构**
+
+Sharding-JDBC 采用无中心化架构,适用于 Java 开发的高性能的轻量级 OLTP 应用;Sharding-Proxy 提供静态入口以及异构语言的支持,适用于 OLAP 应用以及对分片数据库进行管理和运维的场景。
+
+每种架构方案都有其各自的优缺点,下面表格对比了各种架构模型的在不同场景下的优劣:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database4.jpg)
+
+Apache ShardingSphere 是多接入端共同组成的生态圈。通过混合使用 Sharding-JDBC 和 Sharding-Proxy,并采用同一配置中心统一配置分片策略,能够灵活的搭建适用于各种场景的应用系统,使得架构师更加自由的调整适合与当前业务的最佳系统架构。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database5.jpg)
+
+Apache ShardingSphere 采用 Share Nothing 架构,它的 JDBC 和 Proxy 接入端均采用无状态设计。作为计算节点,Apache ShardingSphere 负责对获取的数据进行最终的计算汇总。由于本身并不存储数据,因此 Apache ShardingSphere 可以将计算下推至数据节点,以充分利用数据库自身的计算能力。Apache ShardingSphere 可以通过增加部署节点数量来增加计算能力;增加数据库节点数量来增加存储能力。
+
+### 3 核心功能
+
+数据分片、分布式事务、弹性伸缩和分布式治理是 Apache ShardingSphere 目前阶段的 4 个最核心功能。
+
+#### 数据分片
+
+分而治之是 Apache ShardingSphere 用于处理海量数据的方案。Apache ShardingSphere 通过数据分片方案,使数据库具备分布式存储能力。
+
+它可以将 SQL 根据用户预置的分片算法自动路由至相应的数据节点,以达到操作多个数据库的目的。用户可以像使用单机数据库一样使用被 Apache ShardingSphere 所管理的多个数据库。目前支持 MySQL、PostgreSQL、Oracle、SQLServer 以及任何支持 SQL92 标准和 JDBC 标准协议的数据库。数据分片的内核流程见下图:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database6.jpg)
+
+主要流程如下:
+
+1.  通过解析数据库协议包或 JDBC 驱动获取用户输入的 SQL 和参数;
+    
+2.  根据词法分析器和语法分析器将 SQL 解析为 AST(抽象语法树),并提取分片所需信息;
+    
+3.  根据用户预置算法匹配分片键,并计算路由路径;
+    
+4.  将 SQL 改写为分布式可执行 SQL;
+    
+5.  向各数据节点并行发送 SQL,执行引擎负责连接池与内存资源的平衡;
+    
+6.  根据 AST 执行流式或全量内存结果集归并计算;
+    
+7.  封装数据库协议包或 JDBC 结果集,并返回至客户端。
+    
+
+#### 分布式事务
+
+事务是数据库系统的最核心功能。分布式的不确定和事务的复杂性,决定了分布式事务领域无法出现放之四海而皆准的方案。
+
+面对百花齐放的现状,Apache ShardingSphere 提供高度开放的方案,采用标准接口统一整合开发者自主选择的第三方分布式事务框架,以满足各种场景的应用需求。除此之外,Apache ShardingSphere 还提供了全新的分布式事务解决方案 JDTX,来弥补现有方案的缺失。
+
+标准化整合接口
+
+Apache ShardingSphere 为本地事务、两阶段事务和柔性事务提供了统一的适配接口,并对接了大量的现有第三方的成熟解决方案。通过标准接口,开发者可以轻松的将其他整合方案融入到 Apache ShardingSphere 平台中。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database7.jpg)
+
+然而,融合大量第三方解决方案,却不能覆盖所有分布式事务需求分支。各种解决方案均有各自的适合及不适合场景。各解决方案间是互斥的,无法将它们的优点叠加使用。针对于当前最常见 2PC(两阶段提交)和柔性事务,分别存在着以下的优势和不足:
+
+- 两阶段提交:基于 XA 协议实现的两阶段分布式事务对业务侵入很小。它最大的优势是对使用方透明,开发者可以像本地事务一样使用基于 XA 协议的分布式事务。XA 协议能够严格保障事务 ACID 特性,但这也是一把双刃剑。事务执行在过程中需要将所需资源全部锁定,它更加适用于执行时间确定的短事务。对于长事务来说,整个事务进行期间对资源的独占,将导致对热点数据依赖的业务系统并发性能衰退明显。因此,在高并发的性能至上场景中,基于 XA 协议两阶段提交类型的分布式事务并不是最佳选择。
+    
+- 柔性事务:如果将实现了 ACID 的事务要素的事务称为刚性事务的话,那么基于 BASE 事务要素的事务则称为柔性事务。BASE 是基本可用、柔性状态和最终一致性这 3 个要素的缩写。在 ACID 事务中对一致性和隔离性的要求很高,在事务执行过程中,必须将所有的资源占用。柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性和隔离性的要求,只要求当整个事务最终结束的时候,数据是一致的。而在事务执行期间,任何读取操作得到的数据都有可能被改变。这种弱一致性的设计可以用来换取系统吞吐量的提升。
+    
+
+基于 ACID 的两阶段事务和基于 BASE 的最终一致性事务都不是银弹,可通过下表详细对比它们之间的区别。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database8.jpg)
+
+缺乏并发度保障的两阶段事务不能称之为完善的分布式事务解决方案;而缺乏对 ACID 原义支持的柔性事务都甚至不能称之为数据库事务,它更适合服务层的事务处理。
+
+放眼当前,实难找到无需权衡即可放之四海而皆准的分布式事务解决方案。
+
+新一代分布式事务中间件 JDTX
+
+JDTX 是京东数科自研的分布式事务中间件,尚未开源。它的设计目标是强一致(支持 ACID 的事务原义)、高性能(不低于本地事务性能)、1PC(完全摒弃两阶段提交和两阶段锁)的完全分布式事务中间件,目前可用于关系型数据库。它采用完全开放 SPI 的设计方式,提供与 NoSQL 对接的可能,未来能够将多元异构数据维持在同一事务中。
+
+JDTX 通过完全自研的事务处理引擎,将 SQL 操作的事务中数据转化为 KV(键值对),并在其基础上实现了 MVCC(多版本快照)的事务可见性引擎,以及与数据库设计理念类似的 WAL(预写日志系统)存储引擎。可以通过下面的架构图来了解一下 JDTX 的构成:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database9.jpg)
+
+它的设计特点是将在事务中的数据(称之为活跃数据)和不在事务中的数据(称之为落盘数据)分离。活跃数据在落盘至 WAL 之后,再以 KV 的形态保存至 MVCC 内存引擎中。落盘数据则是通过异步刷盘的方式,将 WAL 中的 REDO 日志,以流量可控的方式同步至最终的存储介质中(如:关系型数据库)。事务内存查询引擎负责使用 SQL 从 KV 格式的活跃数据中检索到相关数据,与落盘数据合并,并根据事务隔离级别获取符合当前事务可见的数据版本。
+
+JDTX 以全新的架构重新诠释了数据库的事务模型,主要亮点有:
+
+**1、内化分布式事务为本地事务**
+
+JDTX 的 MVCC 引擎是一个集中式缓存。它能够将两阶段提交内化至一阶段提交,以维持单一节点中数据的原子性和一致性,即将分布式事务的范畴缩减到本地事务的范畴。JDTX 通过保证所有对事务数据的访问都通过 MVCC 引擎的活跃数据 + 最终数据端的落盘数据的合并的方式,以保证事务数据的原子性和一致性。
+
+**2、无损的事务隔离机制**
+
+以 MVCC 的方式实现事务隔离性。目前完整的支持 4 种标准隔离级别中的读已提交和可重复读,已经可以满足绝大部分需求。
+
+**3、高性能**
+
+采用将活跃数据异步刷盘至存储介质的方式,极大地提高了数据写入的性能上限。它的性能瓶颈从数据库写入耗时转移到了落盘至 WAL 和 MVCC 引擎的耗时。
+
+与数据库的 WAL 系统类似,JDTX 的 WAL 也采用顺序日志追加的方式,因此可以简单的理解为 JDTX 的 WAL 耗时 = 数据库系统的 WAL 耗时。而 MVCC 引擎则采用 KV 数据结构,其写入耗时小于维护 BTree 索引的数据库。因此,JDTX 的数据更新性能的上限甚至可以高于不开启事务。
+
+**4、高可用**
+
+WAL 和 MVCC 引擎均可以通过主备 + 分片的方式维持高可用和水平扩展的能力。在 MVCC 引擎完全不可用的情况下,可通过恢复模式将 WAL 中的数据同步至数据库,以保证数据的完整性。
+
+**5、跨多元数据库事务**
+
+将事务活跃数据和落盘数据分离的设计方案,使其落盘数据存储端无任何限制。由于事务活跃数据通过异步的落盘执行器存储至后端存储介质,因此后端是否为同构数据库,其实并无影响。使用 JDTX 能够保证跨多元存储端(如:MySQL、PostgreSQL,甚至是 MongoDB、Redis 等 NoSQL)的分布式事务维持在同一事务语义之中。
+
+通过 Apache ShardingSphere 提供的分布式事务统一适配接口,可以将 JDTX 像其他第三方分布式事务解决方案一样轻松地融入 Apache ShardingSphere 生态,将数据分片与分布式事务无缝结合,使它们具备组成分布式数据库基础设施的能力。架设在产品最前端的 Apache ShardingSphere 用于 SQL 解析、数据库协议和数据分片;位于中层的 JDTX 用于通过 KV 和 MVCC 的方式处理事务活跃数据;最底层的数据库则仅作为最终的数据存储端。下图是 ShardingSphere + JDTX 的架构图。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database10.jpg)
+
+可以说,JDTX 的存在,使得 Apache ShardingSphere 打破了稳定型的数据库中间件的定位,在保持稳定的同时,逐步向进取型 NewSQL 发展。
+
+#### 弹性伸缩
+
+与无状态的服务化应用不同,数据节点中均持有不可丢失的重要用户数据。当数据节点的容量不足以承担快速增长的业务时,数据节点的扩容则在所难免。根据用户预置的分片策略不同,扩容的策略也会随之不同。
+
+弹性伸缩可以让被 Apache ShardingSphere 所管理的数据库在不停止对外服务的情况下进行扩容和缩容。弹性伸缩分为弹性迁移和范围扩容两个组件,目前它们均在孵化中。
+
+弹性迁移
+
+数据迁移是面向用户定制分片策略的标准扩缩容方案。在迁移过程中,需要准备两套数据节点。原数据节点在继续提供服务的同时,将数据以存量和增量的方式,分别写入新数据节点。整个迁移过程无需停止对外服务,可以平顺的过渡新旧数据节点。Apache ShardingSphere 还将提供工作流界面,让迁移过程完全自主可控。弹性迁移的架构图如下:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database11.jpg)
+
+具体流程如下:
+
+1.  通过配置中心修改数据分片配置,以触发迁移流程。
+    
+2.  记录当前迁移数据开启前的位点之后,开启历史迁移作业,分批迁移全量数据。
+    
+3.  开启 Binlog 订阅作业,迁移位点之后的增量数据。
+    
+4.  根据采样率设置比对数据。
+    
+5.  设置原数据源只读,确保实时数据迁移完成。
+    
+6.  将应用连接切换至新数据源。
+    
+7.  旧数据源下线。
+    
+
+迁移时长根据数据量的大小可能是几分钟至几周不等。迁移过程中可以随时回退或重新迁移。整个迁移流程完全自主可控,降低迁移过程中的风险;并且通过自动化工具完全屏蔽人工操作,避免繁琐的操作带来的巨大工作量。
+
+范围扩容
+
+如果弹性迁移称之为硬伸缩的话,那么范围扩容则称之为软伸缩。Apache ShardingSphere 的范围扩容不涉及内核改造,也无需迁移数据,它只需通过优化范围分片策略,即可达到自动扩(缩)容的目标。使用范围扩容,用户无需感知分片策略和分片键等分库分表方案中必要概念,让 Apache ShardingSphere 更加接近一体化的分布式数据库。
+
+使用范围扩容的用户,只需向 Apache ShardingSphere 提供数据库资源池。容量巡检器会在表容量到达阈值时,从资源池中依次寻找下一个数据节点,并在新数据节点创建新表之后,修改分片策略的范围元数据。当资源池中没有新数据节点后,Apache ShardingSphere 会按照同样的顺序,在已经创建过表的数据库中增加新表。当表数据大量删除时,之前的数据节点的数据将不再紧凑,垃圾回收器会定时压缩表范围,以释放更多的碎片空间。范围扩容的结构如下:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database12.jpg)
+
+Apache ShardingSphere 为不同的应用场景,提供了更加灵活的弹性伸缩策略。目前仍在孵化中的两个弹性伸缩相关的项目,也力争尽快提供试用版本。
+
+#### 分布式治理
+
+治理模块的设计目标是为了更好管理和使用分布式数据库。
+
+数据库治理
+
+与所有的分布式系统的设计理念一脉相承,分而治之同样是分布式数据库的指导方针。数据库治理能力的存在,能够让管理成本不随着数据库实例数目的增长而提升。
+
+配置动态化
+
+Apache ShardingSphere 使用配置中心来管理配置,可以在配置修改后的极短时间内传播到所有的接入端实例。配置中心采用开放的 SPI 方式,能够充分利用配置中心自身的能力,如配置多版本变更等。
+
+高可用
+
+Apache ShardingSphere 使用注册中心管理接入端实例和数据库实例的运行状态。注册中心同样采用配置中心的开放 SPI 方式。部分注册中心的实现可以涵盖配置中心的能力,因此用户可以叠加使用注册中心和配置中心的能力。
+
+Apache ShardingSphere 提供了数据库实例禁用和接入端熔断的能力,分别用于处理数据库实例不可用和接入端被大流量冲击的场景。
+
+Apache ShardingSphere 目前正在孵化高可用的 SPI,让用户能够复用数据库自身提供的高可用方案。目前正在对接 MySQL 的 MGR 高可用方案。Apache ShardingSphere 可以通过自动探知 MGR 的选举变化并快速传播至所有的应用实例。
+
+可观察性
+
+大量数据库和接入端实例,使得 DBA 和运维人员无法迅速感知当前系统的状况。Apache ShardingSphere 通过对 OpenTracing 协议的实现,将监控数据发送至实现其协议的第三方 APM 系统中;除此之外,Apache ShardingSphere 还提供了 Apache SkyWalking 的自动探针,可以让使用它作为可观察性产品的用户直接观测到 Apache ShardingSphere 的性能、调用链关系以及系统的整体拓扑图。
+
+数据治理
+
+得益于 Apache ShardingSphere 对 SQL 灵活的处理能力和对数据库协议的高度兼容性,数据相关的治理能力也被很方便的加入到了产品生态中。
+
+脱敏
+
+Apache ShardingSphere 可以让用户在无需修改代码的情况下,自动将指定的数据列加密后存储至数据库,并在应用程序获取数据时解密,以保证数据的安全。当数据库的数据被不慎泄露时,敏感数据信息由于被完全加密,从而不会造成更大的安全隐患。
+
+影子库表
+
+Apache ShardingSphere 可以在系统进行全链路压测时,自动将用户标记的数据路由至影子库(表)。影子库(表)压测功能可以让线上压测成为常态,用户无需在关心压测数据的清理。此项功能也正在高速的孵化中。
+
+### 4 线路规划
+
+如您所见,Apache ShardingSphere 正处于高速发展的轨道中,越来越多与“分库分表”这条曾经主线并无强关联的功能被加入其中。但这些产品功能却并不突兀,它们反而能助力 Apache ShardingSphere 成为更加多元化的分布式数据库解决方案。Apache ShardingSphere 未来的线路主要会集中在以下几点。
+
+#### 可插拔平台
+
+越来越多的零散功能需要进一步梳理。Apache ShardingSphere 现有的架构还不足以完全吸收如此广泛的产品功能。弹性化的功能可插拔平台是 Apache ShardingSphere 未来架构的调整方向。
+
+可插拔平台会将 Apache ShardingSphere 从技术和功能两方面完全拆开。Apache ShardingSphere 的全景图如下所示:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/database13.jpg)
+
+Apache ShardingSphere 会根据技术架构横向分为 4 层,分别是接入层、SQL 解析层、内核处理层和存储访问层;并且将功能以可插拔的形态融入至 4 层架构中。
+
+Apache ShardingSphere 对数据库类型的支持将完全开放,除了关系型数据库,NoSQL 也会完全开放支持,数据库方言互不影响,完全解耦。在功能方面,Apache ShardingSphere 采用叠加式架构模型,使各个功能可以灵活的组合使用。每个功能模块只需关注自身的核心功能,由 Apache ShardingSphere 架构负责功能的叠加组合使用。即使没有任何功能,Apache ShardingSphere 也可以作为一个空白的接入端直接启动,为开发者的定制化开发提供脚手架以及 SQL 解析等基础设施。融入 Apache ShardingSphere 生态的数据库,将直接获得平台提供的所有基础能力;在 Apache ShardingSphere 平台上开发的功能,也将直接获得已接入平台的数据库类型的全部支持。数据库类型和功能类型将以相乘的方式排列组合,基础设施 + 乐高的组合,将为 Apache ShardingSphere 提供各种想象和提升的空间。
+
+#### 查询引擎
+
+目前 Apache ShardingSphere 只是将 SQL 通过正确的路由和改写,分发至相应的数据库以操作数据。计算下发能够充分利用的数据库的查询引擎,但无法有效的支持复杂关联查询和子查询。基于关系代数实现的 SQL on KV 查询引擎随着 JDTX 的开发日臻成熟,将其积累的经验反哺于 SQL 查询引擎,能够让 Apache ShardingSphere 更好的支持子查询和跨库关联查询等复杂查询。
+
+#### 多数据副本
+
+分布式数据库所需要的多数据副本能力目前的 Apache ShardingSphere 还未具备。未来 Apache ShardingSphere 将提供基于 Raft 的多副本写入能力。
+
+#### Database Mesh
+
+上文中提到的 Sharding-Sidecar 接入端,是 Apache ShardingSphere 未来的第三个接入端形态,旨在更好的与 Kubernetes 配合,打造云原生数据库。
+
+Database Mesh 的关注重点在于如何将分布式的数据访问应用与数据库有机串联起来,它更加关注的是交互,是将杂乱无章的应用与数据库之间的交互有效的梳理。使用 Database Mesh,访问数据库的应用和数据库终将形成一个巨大的网格体系,应用和数据库只需在网格体系中对号入座即可,它们都是被啮合层所治理的对象。
+
+#### Data Federation
+
+支持更多的数据库类型之后,Apache ShardingSphere 会将工作重点放在多元异构的数据库类型的统一查询引擎之上。除此之外,Apache ShardingSphere 还将配合 JDTX,将更加多元的数据存储介质纳入到同一事务中。
+
+### 5 开源与社区
+
+Apache ShardingSphere 在 2016 年 1 月 17 日在 GitHub 平台首次开源,开源项目的初始名称是 Sharding-JDBC。在 2018 年 11 月 10 日,ShardingSphere 改名并正式进入 Apache 软件基金会的孵化器。
+
+在开源至今走过的 4 年里程中,Apache ShardingSphere 的架构模型在不断的演进的同时,整体产品的功能范围也在急速地扩张。它从开源之初的分库分表 Java 开发框架,逐渐演化为分布式数据库解决方案。
+
+随着 Apache ShardingSphere 的生态圈的扩张,由少数开发者掌控项目的状态早已被打破。目前的 Apache ShardingSphere 有近百名贡献者,以及近 20 名核心提交者,他们共同打造着这个遵循着 Apache Way 的社区。Apache ShardingSphere 是一个标准的 Apache 软件基金会开源项目,并不受某一商业公司或某几位核心开发者掌控。
+
+目前有超过 100 家公司明确的声明他们在使用 Apache ShardingSphere,读者可以从官方网站找到采用公司的用户墙。
+
+随着社区的成熟,Apache ShardingSphere 的成长也越来越迅速。我们诚邀感兴趣的开发者一同参与到 Apache ShardingSphere 社区中,完善不断扩大的生态。
+
+**项目地址:**
+
+https://github.com/apache/incubator-shardingsphere
+
+### 6 作者介绍
+
+张亮,京东数科数据研发负责人,Apache ShardingSphere 发起人 & PPMC,JDTX 负责人。  
+  
+热爱开源,主导开源项目 ShardingSphere(原名 Sharding-JDBC) 和 Elastic-Job。擅长以 java 为主分布式架构,推崇优雅代码,对如何写出具有展现力的代码有较多研究。  
+  
+目前主要精力投入在将 ShardingSphere 和 JDTX 打造为业界一流的金融级数据解决方案之上。ShardingSphere 已经进入 Apache 孵化器,是京东集团首个进入 Apache 基金会的开源项目,也是 Apache 基金会首个分布式数据库中间件。
diff --git a/docs/blog/content/material/database.en.md b/docs/blog/content/material/database.en.md
new file mode 100644
index 0000000..1622963
--- /dev/null
+++ b/docs/blog/content/material/database.en.md
@@ -0,0 +1,7 @@
++++
+title = "Database"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/engine.cn.md b/docs/blog/content/material/engine.cn.md
new file mode 100644
index 0000000..ef9d246
--- /dev/null
+++ b/docs/blog/content/material/engine.cn.md
@@ -0,0 +1,183 @@
++++
+title = "自动化执行引擎"
+weight = 2
+chapter = true
++++
+
+## 自动化执行引擎 
+
+今天「剖析Sharding-Sphere系列文章」为大家带来对Sharding-Sphere自动化执行引擎模块的相关介绍。鉴于老板比较喜欢正经的技术文章,所以妹子我尽量用正经又不失肃穆的叙述风格,为大家带来《Sharding-Sphere自动化执行引擎模块》的分享。
+
+传说鱼的记忆只有7秒钟。前段时间刚把这个模块的代码抒写整理完,趁着我还没有失忆之前,先为大家叙述一二,愿对各位看官有所帮助。
+
+「剖析Sharding-Sphere系列文章」是由Sharding-Sphere的核心开发成员亲自操刀向大家介绍和剖析Sharding-Sphere的核心模块、所使用的前沿技术、有价值的经验总结等。这一系列的文章将带您走进Sharding-Sphere的内核世界,获得新知、激发灵感。更希望您关注我们,共同交流切磋,一同前行。
+
+### 作者介绍
+
+潘娟,京东金融运维DBA,主要负责京东金融生产数据库运维及数据库平台、中间件开发工作。多次参与京东金融6.18、11.11大促活动的护航工作。曾负责京东金融数据库自动化平台设计与开发项目,现专注于Sharding-Sphere分布式数据库中间件开发。乐于在数据库、自动化、分布式、中间件等相关领域进行学习和探索。
+
+### 概念介绍
+
+Q: 什么叫"自动化执行引擎"?  
+
+A: 一条SQL的生命周期是:从客户端发起、经过Sharding-Sphere处理、再到底层数据库执行消化。而在Sharding-Sphere里过程则是:SQL解析-->SQL优化-->SQL路由-->SQL改写-->SQL执行-->结果归并。自动化执行引擎是为了处理SQL执行问题的,即将路由改写后的真实SQL如何有控制且高效地传送到底层数据库执行。那么直接通过JDBC发送SQL至数据库执行难道行不通吗?还有其他需要考虑吗?答案是:肯定有其他考虑,否则我就不用写这篇文章了。这就体现在它的"自动化"上了。所谓"自动化",其实是为了平衡数据库连接创建与结果归并模式选择问题,为了平衡资源控制与执行效率问题。
+
+### 需求场景
+
+Q: 为何需要自动化执行引擎呢?
+
+A: 在概念介绍部分,我们介绍了主角-自动化执行引擎。也谈到它的自动化是为了平衡数据库连接创建以及结果归并模式选择问题。这是它诞生的宿命,历史的选择。下面将为大家介绍这两个需要平衡的问题:
+
+1.数据库连接创建
+
+作为一位混娱乐圈的DBA出身的Java coder, 多少还是会从DBA角度考虑问题。比如从资源控制的角度看,业务方访问数据库的连接数量应当有所限制,这能够有效地防止某一业务操作过多地占用资源,从而将数据库连接的资源耗尽,以致于影响其他业务的正常访问。特别是在一个数据库实例中存在较多分表的情况下,一条不包含分片键的逻辑SQL将产生落在同库不同表的大量真实SQL,如果每条真实SQL都占用一个独立的连接,那么一次查询肯定将会占用过多的资源。Sharding-Sphere作为数据库中间层,如果没有控制好数据库连接数量而导致连接暴增、数据库压力过大的话,极有可能被强行背锅。
+
+2.结果归并模式选择
+
+但是从执行效率的角度看,为每个分片查询维持一个独立的数据库连接,可以更加有效地利用多线程来提升执行效率。为每个数据库连接开启独立的线程,可以并行化IO所产生的消耗。独立的数据库连接,能够保持查询结果集的引用以及游标位置,在需要获取相应数据时移动游标即可,避免了过早将查询结果数据加载至内存。这就涉及到了结果归并模式的选择问题。通过上一篇文章《剖析Sharding-Sphere系列——结果归并》介绍,我们知道当前有两种结果归并的模式,分别是:
+
+流式归并:以结果集游标下移进行结果归并的方式,称之为流式归并,它无需将结果数据全数加载至内存,可以有效地节省内存资源,进而减少垃圾回收的频次。
+
+内存归并:以读取内存中加载的结果集进行归并的方式,进行数据对比归并。它需要将结果数据全数加载至内存。
+
+相信只要是智商在线的朋友,一定会选择流式归并来处理结果集。可是,如果无法保证每个分片查询持有一个独立数据库连接的话,那么就需要在复用该数据库连接、获取下一张分表的查询结果集之前,将当前的查询结果集全数加载至内存。因此,即使可以采用流式归并,在此场景下也不得不退化为内存归并。
+
+一方面是对数据库连接资源的控制保护,一方面是采用更优的归并模式达到内存资源节省的目的,如何处理好两者之间的关系,是Sharding-Sphere执行引擎需求解决的问题。具体来说,如果一条SQL在经过Sharding-Sphere的分片后,需要操作某数据库实例下的200张表,那么,是选择创建200个连接并行执行,还是选择创建一个连接串行执行呢?效率与资源控制又应该如何抉择呢?
+
+### 进化论
+
+针对上述的场景,Sharding-Sphere在3.0.0.M4之前提供了一种解决思路,即提出了连接模式(Connection Mode)的概念,并划分了两种模式:内存限制模式(MEMORY\_STRICTLY)和连接限制模式(CONNECTION\_STRICTLY)这两种类型。
+
+- 内存限制模式。使用此模式的前提是数据库对其一次操作所耗费的连接数量不做限制。如果实际执行的SQL需要对某数据库实例中的200张表做操作,则对每张表创建一个新的数据库连接,并通过多线程的方式并发处理,以达成执行效率最大化。并且在SQL满足条件情况下,优先选择流式归并,以防止出现内存溢出或避免频繁垃圾回收情况。
+    
+
+- 连接限制模式。使用此模式的前提是数据库严格控制对其一次操作所耗费的连接数量。如果实际执行的SQL需要对某数据库实例中的200张表做操作,那么只会创建唯一的数据库连接,并对其200张表串行处理。如果分片在不同的数据库,仍然是多线程处理不同库,但每个库的每次操作仍然只创建一个唯一的数据库连接。这样即可以防止对一次请求对数据库连接占用过多所带来的问题。该模式始终选择内存归并。
+    
+
+  
+
+内存限制模式适用于OLAP操作,可以通过放宽对数据库连接的限制提升系统吞吐量;连接限制模式适用于OLTP操作,OLTP通常带有分片键,会路由到单一的分片,因此严格控制数据库连接,以保证在线系统数据库资源能够被更多的应用所使用,是明智的选择。
+
+  
+
+而Sharding-Sphere最终使用何种模式的决定权就交由用户。Sharding-Sphere提供对连接模式的配置,让开发者依据自己业务的实际场景需求选择使用内存限制模式或连接限制模式。
+
+  
+
+可是,将两难的选择的决定权甩锅给用户,使得用户必须要了解这两种模式的利弊,并依据业务场景需求进行选择。这显然增加了用户对Sharding-Sphere的学习和使用的成本,这并不是一种最优的解决方案。
+
+  
+
+此外,这种一分为二的处理方案,将两种模式的切换交由静态的初始化配置,缺乏灵活应性。在实际的使用场景中,面对不同SQL以及占位符参数,每次的路由结果是不同的。这就意味着某些操作可能需要使用内存归并,而某些操作则可能选择流式归并更优,它们不应该由用户在Sharding-Sphere启动之前配置好,而更应该根据SQL和占位符参数的场景,来动态的决定连接模式。
+
+  
+
+像Sharding-Sphere这样,总是站在用户角度考虑问题并且不断优化精进的七道杠青年是一定要进行相关优化调整的,于是自动化执行引擎就进化出来了。
+
+  
+
+为了降低用户的使用成本以及连接模式动态化这两个问题,Sharding-Sphere提炼出自动化执行引擎的思路,在其内部消化了连接模式的概念。用户无需了解所谓的内存限制模式和连接限制模式是什么,而是交由执行引擎根据当前场景自动选择最优的执行方案。
+
+  
+
+同时,自动化执行引擎将连接模式的选择粒度细化至每一次SQL的操作。针对每次SQL请求,自动化执行引擎都将根据其路由结果,进行实时的演算和权衡,并自主地采用恰当的连接模式执行,以达到资源控制和效率的最优平衡。针对自动化的执行引擎,用户只需配置maxConnectionSizePerQuery即可,该参数表示一次查询时每个数据库所允许使用的最大连接数,剩余的处理逻辑将由自动化执行引擎为您负责。
+
+### 实现解析
+
+  
+
+整个自动化执行引擎的执行流程如下图所示。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/engine1.jpg)
+
+  
+
+在路由改写完成后,我们会得到路由结果(SQLRouteResult),这个结果集主要包含了SQL、SQL的参数集、数据库等信息。其数据结构如下图所示:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/engine2.jpg)
+
+执行引擎的执行过程分为准备、执行两个阶段。
+
+  
+
+*   准备阶段  
+    
+
+顾名思义,此阶段用于准备执行的数据。它分为结果集分组和执行单元创建两个步骤。
+
+  
+
+ a. 结果集分组
+
+该步骤是实现内化连接模式概念的关键。执行引擎根据maxConnectionSizePerQuery配置项,结合当前路由结果,自动选择恰当的连接模式。具体步骤如下:
+
+  
+
+- 将SQL的路由结果按照数据库的名称进行分组。
+
+- 通过下图的公式获得每个数据库实例在maxConnectionSizePerQuery的允许范围内,每个数据库连接需要执行的SQL路由结果组,并演算出本次请求最优的连接模式。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/engine3.jpg)
+
+在maxConnectionSizePerQuery允许的范围内,当一个连接需要执行的请求数量大于1时,意味着当前的数据库连接无法持有相应的数据结果集,则必须采用内存归并;反之,当一个连接需要执行的请求数量等于1时,意味着当前的数据库连接可以持有相应的数据结果集,则可以采用流式归并。
+
+  
+
+每一次的连接模式的选择,是针对每一个物理数据库的。也就是说,在同一次查询中,如果路由至一个以上的数据库,每个数据库的连接模式不一定一样,它们可能是混合存在的形态。
+
+  
+
+ b. 执行单元创建  
+
+该步骤通过上一步骤获得的路由分组结果创建用于执行的单元。执行单元是指为每个路由分组结果创建相应的数据库连接。
+
+  
+
+当数据库被限制了连接资源数量且线上业务出现大量并发操作时,如果不妥善处理并发获取数据库连接的问题,则很有可能会发送死锁。在多个请求相互等待对方释放数据库连接资源时,就会产生饥饿等待,造成交叉死锁。
+
+  
+
+举个栗子,假设一次查询需要在某一数据库上获取2个数据库连接,用于路由至一库的2个分表查询。有可能出现查询A已获取到该数据库的1个数据库连接,并等待获取另一个数据库连接;而查询B则也已经获得了该数据库上的1个数据库连接,并同样等待另一个数据库连接的获取。如果数据库连接池的允许最大连接数是2,那么这2个查询请求将永远孤独地等待着彼此,图绘版的解释可能会更便于大家理解:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/engine4.jpg)
+
+为了避免死锁的出现,Sharding-Sphere在获取数据库连接时进行了同步处理。它在创建执行单元时,以原子性的方式一次性获取本次SQL请求所需的全部数据库连接,杜绝了每次查询请求获取到部分资源的可能。这种加锁做法确实可以解决死锁问题,只是,同时会带来一定程度并发性能的损失。为了展示我们不一样!有啥不一样呢?
+
+我们针对此问题还进行了以下两方面优化:
+
+  
+
+1\.    避免锁定一次性只需获取一个数据库连接的操作。因为每次仅需要获取一个连接,就不会发生两个请求相互等待的场景,无需锁定。对于大部分OLTP的操作,都是使用分片键路由至唯一的数据节点,此时无需担心交叉死锁问题,也无需考虑加锁问题,从而减少对并发效率的影响。除了路由至单分片的情况,读写分离也属于此范畴之内的场景。
+
+2\.    仅针对内存限制模式进行链接资源的锁定。在使用连接限制模式时,数据库连接资源在所有查询结果集装载至内存之后被释放掉,因此不必考虑死锁等待、加锁处理的问题。
+
+  
+
+*   执行阶段
+    
+  
+
+该阶段用于真正的执行SQL,它分为分组执行和归并结果集生成两个步骤。
+
+ a. 分组执行
+
+该步骤将准备执行阶段生成的执行单元分组下发至底层并发执行引擎,并针对执行过程中的每个关键步骤发送事件。如:执行开始事件、执行成功事件以及执行失败事件。执行引擎仅关注事件的发送,它并不关心事件的订阅者。Sharding-Sphere的其他模块,如:分布式事务、调用链路追踪等,会订阅感兴趣的事件,并进行相应的处理。
+
+ b. 归并结果集生成
+
+Sharding-Sphere通过在执行准备阶段的获取的连接模式,生成内存归并结果集或流式归并结果集,并将其传递至结果归并引擎,以进行下一步的工作。内存归并结果集或流式归并结果集的核心区别是:流式归并结果集会通过游标方式获取结果集的数据,而内存归并结果集则是从内存里获取数据。这也是内存归并和流式归并的数据基础。
+
+  
+
+通过上述所有步骤就完成了自动化执行引擎的执行流程。其核心目的是自动化平衡数据库连接创建以及结果归并模式选择问题,实现细粒度地平衡把控每一次查询的资源控制与执行效率,从而减少用户的使用学习成本和业务场景变化的担忧。
+
+  
+
+看官一杯茶的时间,是妹子我反复修改数次的结果。妹子无法被打赏,只愿正在阅读的你能有所收获,这也是我们coding、writing的意义所在。以后还会有「剖析Sharding-Sphere系列文章」其他文章与大家见面,敬请关注~
+
+
+
+
+
+
+
diff --git a/docs/blog/content/material/engine.en.md b/docs/blog/content/material/engine.en.md
new file mode 100644
index 0000000..e2f023e
--- /dev/null
+++ b/docs/blog/content/material/engine.en.md
@@ -0,0 +1,7 @@
++++
+title = "engine"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/proxy.cn.md b/docs/blog/content/material/proxy.cn.md
new file mode 100644
index 0000000..78f2d66
--- /dev/null
+++ b/docs/blog/content/material/proxy.cn.md
@@ -0,0 +1,297 @@
++++
+title = "揭秘Sharding-Proxy——面向DBA的数据库中间层"
+weight = 2
+chapter = true
++++
+
+## 揭秘Sharding-Proxy——面向DBA的数据库中间层
+
+### 讲师介绍
+
+**张永伦**:京东金融运维部高级软件工程师
+
+曾在传统行业工作多年,从事基础软件开发工作。后投身互联网,在京东金融开始了爬虫生涯,感叹互联网数据量之大,但心中仍对偏底层的软件感兴趣。今年有幸加入到Sharding-Sphere,能够做自己感兴趣的事情,希望以后多做些工作,提升自己,回报社区。
+
+大家好,我今天想跟大家分享的是Sharding-Sphere的第二个产品Sharding-Proxy。
+
+在上个月亮相的Sharding-Sphere 3.0.0.M1中首次发布了Sharding-Proxy,希望这次分享能够通过几个优化实践,帮助大家管中窥豹,从几个关键细节想象出Sharding-Proxy的全貌。至于更详细的MySQL协议、IO模型、Netty等议题,以后有机会再和大家专题分享。
+
+### 一、Sharding-Proxy简介
+
+  
+
+#### 1\. Sharding-Proxy概览
+
+Sharding-Proxy定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。目前先提供MySQL版本,它可以使用任何兼容MySQL协议的访问客户端操作数据(如:MySQLCommandClient、MySQLWorkbench等),对DBA更加友好。
+
+*   对应用程序完全透明,可直接当做MySQL使用;
+    
+*   适用于任何兼容MySQL协议的客户端。
+    
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy1.jpg)
+
+与其他两个产品(Sharding-JDBC、Sharding-Sidecar)的对比:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy2.jpg)
+
+它们既可以独立使用,也可以相互配合,以不同的架构模型、不同的切入点,实现相同的功能目标。而其核心功能,如数据分片、读写分离、柔性事务等,都是同一套实现代码。
+
+举个例子,对于仅使用Java为开发技术栈的场景,Sharding-JDBC对各种Java的ORM框架支持度非常高,开发人员可以非常便利地将数据分片能力引入到现有的系统中,并将其部署至线上环境运行,而DBA就可以通过部署一个Sharding-Proxy实例,对数据进行查询和管理。
+
+#### 2\. Sharding-Proxy架构
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy3.jpg)
+
+整个架构可以分为前端、后端和核心组件三部分来看:
+
+*   前端(Frontend)负责与客户端进行网络通信,采用的是基于NIO的客户端/服务器框架,在Windows和Mac操作系统下采用NIO模型,Linux系统自动适配为Epoll模型,在通信的过程中完成对MySQL协议的编解码;
+    
+*   核心组件(Core-module)得到解码的MySQL命令后,开始调用Sharding-Core对SQL进行解析、改写、路由、归并等核心功能;
+    
+*   后端(Backend)与真实数据库的交互暂时借助基于BIO的Hikari连接池。BIO的方式在数据库集群规模很大,或者一主多从的情况下,性能会有所下降。所以未来我们还会提供NIO的方式连接真实数据库。
+    
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy4.jpg)
+
+这种方式下Proxy的吞吐量将得到极大提高,能够有效应对大规模数据库集群。
+
+### 二、Sharding-Proxy功能细节
+
+#### 1. PreparedStatement功能实现
+
+我在Sharding-Sphere的第一个任务就是实现Proxy的PreparedStatement功能。据说这是一个高大上的功能,能够预编译SQL提高查询速度和防止SQL注入攻击等。一次服务端预编译,多次查询,降低SQL编译开销,提升了效率,听起来没毛病。然而在做完之后却发现被坑了,SQL执行效率不但没有提高,甚至用肉眼都能看出来比原始的Statement还要慢。
+
+先抛开Proxy不说,我们通过wireshark抓包看看运行PreparedStatement时MySQL协议是如何交互的。
+
+示例代码如下:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy5.jpg)
+
+代码很容易理解,使用PreparedStatement执行两次查询操作,每次都把参数user_id设置为10。分析抓到的包,JDBC和MySQL之间的协议消息交互如下:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy6.jpg)
+
+JDBC向MySQL进行了两次查询(Query),MySQL返回给JDBC两次结果(Response),第一条消息不是我们期望的PreparedStatement,SELECT里面也没有问号,这就说明prepare没有生效,至少对MySQL服务来说没有生效。
+
+对于这个问题,我想大家心里都有数,是因为JDBC的url没有设置参数useServerPrepStmts=true,这个参数的作用是让MySQL服务进行prepare。没有这个参数就是让JDBC进行prepare,MySQL完全感知不到,是没有什么意义的。接下来我们在url中加上这个参数:
+
+```
+jdbc:mysql://127.0.0.1:3306/demo_ds?useServerPrepStmts=true
+```
+
+交互过程变成了这样:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy7.jpg)
+
+初看这是一个正确的流程,第1条消息是PreparedStatement,SELECT里也带问号了,通知MySQL对SQL进行预编译;第2条消息MySQL告诉JDBC准备成功;第3条消息JDBC把参数设置为10;第4条消息MySQL返回查询结果。然而到了第5条,JDBC怎么又发了一遍PreparedStatement?
+
+预期应该是以后的每条查询都只是通过ExecuteStatement传参数的值,这样才能达到一次预编译多次运行的效果。
+
+如果每次都“预编译”,那就相当于没有预编译,而且相对于普通查询,还多了两次消息传递的开销:Response(prepareok)和ExecuteStatement(parameter=10)。看来性能的问题就是出在这里了。
+
+像这样使用PreparedStatement还不如不用,一定是哪里搞错了,于是我开始阅读JDBC源代码,终于发现了另一个需要设置的参数——cachePrepStmts。我们加上这个参数看看会不会发生奇迹:
+
+```
+jdbc:mysql://127.0.0.1:3306/demo_ds?
+useServerPrepStmts=true&cachePrepStmts=true
+```
+
+果然得到了我们预期的消息流程,而且经过测试,速度也比普通查询快了:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy8.jpg)
+
+从第5条消息开始,每次查询只传参数值就可以了,终于达到了一次编译多次运行的效果,MySQL的效率得到了提高。而且由于ExecuteStatement只传了参数的值,消息长度上比完整的SQL短了很多,网络IO的效率也得到了提升。
+
+原来cachePrepStmts=true这个参数的意思是告诉JDBC缓存需要prepare的SQL,比如“SELECT*FROMt_orderWHEREuser_id=?”,运行过一次后,下次再运行就跳过PreparedStatement,直接用ExecuteStatement设置参数值。
+
+明白原理后,就知道该怎么优化Proxy了。Proxy采用的是Hikari数据库连接池,在初始化的时候为其设置上面的两个参数:
+
+```
+config.addDataSourceProperty("useServerPrepStmts","true");
+config.addDataSourceProperty("cachePrepStmts","true");
+```
+
+这样就保证了Proxy和MySQL服务之间的性能。那么Proxy和Client之间的性能如何保证呢?
+
+Proxy在收到Client的PreparedStatement的时候,并不会把这条消息转发给MySQL,因为SQL里的分片键是问号,Proxy不知道该路由到哪个真实数据库。Proxy收到这条消息后只是缓存了SQL,存储在一个StatementId到SQL的Map里面,等收到ExecuteStatement的时候才真正请求数据库。
+
+这个逻辑在优化前是没问题的,因为每一次查询都是一个新的PreparedStatement流程,ExecuteStatement会把参数类型和参数值告诉客户端。
+
+加上两个参数后,消息内容发生了变化,ExecuteStatement在发送第二次的时候,消息体里只有参数值而没有参数类型,Proxy不知道类型就不能正确的取出值。所以Proxy需要做的优化就是在PreparedStatement开始的时候缓存参数类型。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy9.jpg)
+
+完成以上优化后,Client-Proxy和Proxy-MySQL两侧的消息交互都变成了最后这张图的流程,从第9步开始高效查询。
+
+#### 2. Hikari连接池配置优化
+
+Proxy在初始化的时候,会为每一个真实数据库配置一个Hikari连接池。根据分片规则,SQL被路由到某些真实库,通过Hikari连接得到执行结果,最后Proxy对结果进行归并返回给客户端。那么,数据库连接池到底该设置多大?对于这个众说纷纭的话题,今天该有一个定论了。
+
+你会惊喜的发现,这个问题不是设置“多大”,反而是应该设置“多小”!如果我说执行一个任务,串行比并行更快,是不是有点反直觉?
+
+即使是单核CPU的计算机也能“同时”支持数百个线程。但我们都应该知道这只不过是操作系统用“时间片”玩的一个小花招。事实上,一个CPU核心同一时刻只能执行一个线程,然后操作系统切换上下文,CPU执行另一个线程,如此往复。
+
+一个CPU进行计算的基本规律是,顺序执行任务A和任务B永远比通过时间片“同时”执行A和B要快。一旦线程的数量超过了CPU核心的数量,再增加线程数就只会更慢,而不是更快。一个对Oracle的测试验证了这个观点。
+
+参考链接:
+
+http://www.dailymotion.com/video/x2s8uec
+
+测试者把连接池的大小从2048逐渐降低到96,TPS从16163上升到20702,平响从110ms下降到3ms。
+
+当然,也不是那么简单地让连接数等于CPU数就行了,还要考虑网络IO和磁盘IO的影响。当发生IO时,线程被阻塞,此时操作系统可以将那个空闲的CPU核心用于服务其他线程。所以,由于线程总是在I/O上阻塞,我们可以让线程(连接)数比CPU核心多一些,这样能够在同样的时间内完成更多的工作。到底应该多多少呢?PostgreSQL进行了一个benchmark测试:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy10.jpg)
+
+TPS的增长速度从50个连接的时候开始变慢。根据这个结果,PostgreSQL给出了如下公式:
+
+```
+connections=((core_count*2)+effective_spindle_count)
+```
+
+连接数=((核心数\*2)+磁盘数)。即使是32核的机器,60多个连接也就够用了。所以,小伙伴们在配置Proxy数据源的时候,不要动不动就写上几百个连接,不仅浪费资源,还会拖慢速度。
+
+#### 3.  结果归并优化
+
+目前Proxy访问真实数据库使用的是JDBC,很快Netty+MySQLProtocol异步访问方式也会上线,两者会并存,由用户选择用哪种方法访问。
+
+在Proxy中使用JDBC的ResultSet会对内存造成非常大的压力。Proxy前端对应m个client,后端又对应n个真实数据库,后端把数据传递给前端client的过程中,数据都需要经过Proxy的内存。如果数据在Proxy内存中呆的时间长了,那么内存就可能被打满,造成服务不可用的后果。所以,ResultSet内存效率可以从两个方向优化,一个是减少数据在Proxy中的停留时间,另一个是限流。
+
+我们先看看优化前Proxy的内存表现。使用5个客户端连接Proxy,每个客户端查询出15万条数据。结果如下图:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy11.jpg)
+
+
+可以看到,Proxy的内存在一直增长,即时GC也回收不掉的。这是因为ResultSet会阻塞住next(),直到查询回来的所有数据都保存到内存中。这是ResultSet默认提取数据的方式,大量占用内存。
+
+那么,有没有一种方式,让ResultSet收到一条数据就可以立即消费呢?在Connector/J文档中有这样一句话:
+
+```
+If you are working with ResultSets that have a large number of rows or large values and cannot allocate heap space in your JVM for the memory required , you can tell the driver to stream the results back one row at a time.
+
+如果你使用ResultSet遇到查询结果太多,以致堆内存都装不下的情况,你可以指示驱动使用流式结果集,一次返回一条数据。
+```
+
+  
+
+文档参考链接:
+
+https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-implementation-notes.html
+
+激活这个功能只需在创建Statement实例的时候设置一个参数:
+
+```
+stmt.setFetchSize(Integer.MIN_VALUE);
+```
+
+这样就完成了。这样Proxy就可以在查询指令后立即通过next()消费数据了,数据也可以在下次GC的时候被清理掉。当然,Proxy在对结果做归并的时候,也需要优化成即时归并,而不再是把所有数据都取出来再进行归并,Sharding-Core提供即时归并的接口,这里就不详细介绍了。下面看看优化后的效果,如下图:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy12.jpg)
+
+
+
+数据在内存中停留时间缩短,每次GC都回收掉了数据,内存效率大幅提升。看到这里,好像已经大功告成了,然而水还很深,请大家穿上潜水服继续跟我探索。图2是在最理想的情况产生的,即Client从Proxy消费数据的速度,大于等于Proxy从MySQL消费数据的速度。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy13.jpg)
+
+如果Client由于某种原因消费变慢了,或者干脆不消费了,会发生什么呢?通过测试发现,内存使用量直线拉升,比图1更强劲,最后将内存耗尽,Proxy被KO。
+
+下面我们就先搞清楚为什么会发生这种现象,然后介绍对ResultSet的第2个优化:限流。
+
+下图加上了几个主要的缓存:
+
+*   SO_RCVBUF/SO_SNDBUF是TCP缓存;
+    
+*   ChannelOutboundBuffer是Netty写缓存。
+    
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy14.jpg)
+
+当Client阻塞的时候,它的SO_RCVBUF会被瞬间打满,然后通过滑动窗口机制通知Proxy不要再发送数据了,同时Proxy的SO_SNDBUF也会瞬间被Netty打满。
+
+Proxy的SO_SNDBUF满了之后,Netty的ChannelOutboundBuffer就会像一个无底洞一样,吞掉所有MySQL发来的数据,因为在默认情况下ChannelOutboundBuffer是无界的。
+
+由于有用户(Netty)在消费,所以Proxy的SO_RCVBUF一直有空间,导致MySQL会一直发送数据,而Netty则不停的把数据存到ChannelOutboundBuffer,直到内存耗尽。
+
+搞清原理之后就知道,我们的目标就是当Client阻塞的时候,Proxy不再接收MySQL的数据。
+
+Netty通过水位参数WRITE_BUFFER_WATER_MARK来控制写缓冲区:
+
+*   当Buffer大小超过高水位线,我们就控制Netty不让再往里面写,当Buffer大小低于低水位线的时候,才允许写入;
+    
+*   当ChannelOutboundBuffer满时,Proxy的SO_RCVBUF被打满,通知MySQL停止发送数据。
+    
+
+所以,在这种情况下,Proxy所消耗的内存只是ChannelOutboundBuffer高水位线的大小。
+
+#### 4. Proxy的两种模式
+在即将发布的Sharding-Sphere3.0.0.M2版本中,Proxy会加入两种代理模式的配置:
+
+*   MEMORY_STRICTLY:Proxy会保持一个数据库中所有被路由到的表的连接,这种方式的好处是利用流式ResultSet来节省内存。
+    
+*   CONNECTION_STRICTLY:代理在取出ResultSet中的所有数据后会释放连接,同时,内存的消耗将会增加。
+    
+
+简单可以理解为,如果你想消耗更小的内存,就用MEMORY_STRICTLY模式;如果你想消耗更少的连接,就用CONNECTION_STRICTLY模式。
+
+MEMORY_STRICTLY的原理其实就是我们前面介绍的内容,优点已经说过了。它带来的一个副作用是,流式ResultSet需要保持对数据库的连接,必须与所有路由到的真实表成功建立连接后,才能够进行即时归并,进而返回结果给客户端。
+
+假设数据库设置max_user_connections=80,而该库被路由到的表是100个,那么无论如何也不可能同时建立100个连接,也就无法归并返回结果。
+
+CONNECTION_STRICTLY就是为了解决以上问题而存在的。不使用流式ResultSet,内存消耗增加。但该模式不需要保持与数据库的连接,每次取出ResultSet内的全量数据后即可释放连接。
+
+还是刚才的例子max_user_connections=80,而该库被路由到的表是100个。Proxy会先建立80个连接查询数据,另外20个连接请求被缓存在连接池队列中,随着前面查询的完成,这20个请求会陆续成功连接数据库。
+
+如果你对这个配置还感到迷惑,那么记住一句话,只有当max_user_connections小于该库可能被路由到的最大表数量时,才使用CONNECTION_STRICTLY。
+
+### 三、小结
+Sharding-Sphere自2016年开源以来不断精进和发展,被越来越多企业和个人所使用,同时也为我们提供了重要的成功案例。未来,我们将不断优化当前的特性,陆续推出大家关注的柔性事务、数据治理等更多新特性。如果大家有什么想法、意见和建议,也欢迎留言与我们交流,更欢迎加入到Sharding-Sphere的开源项目中:
+
+*   https://github.com/sharding-sphere/sharding-sphere/
+    
+*   https://gitee.com/sharding-sphere/sharding-sphere/
+    
+
+  
+
+  
+
+### Q&A
+
+Q1:Sidecar是干什么的?
+
+A1:Sharding-Sidecar是Sharding-Sphere的第三个产品,目前仍在规划中。定位为Kubernetes或Mesos的云原生数据库代理,以DaemonSet的形式代理所有对数据库的访问。
+
+  
+
+Q2:“问如果你对这个配置还感到迷惑,那么记住一句话,只有当max_user_connections小于该库可能被路由到的最大表数量时,才使用CONNECTION_STRICTLY。”这句话是不是说反了?
+
+A2:CONNECTION_STRICTLY就是为了省连接的。max_user_connections小,所以用CONNECTION_STRICTLY模式。
+
+  
+
+Q3:stmt.setFetchSize(custom_size);设置的场景使用类似Mybatis之类的框架查询大量数据到内存,一般就是放到一个list中,然后处理。内存还是会占用。
+
+A3:这种情况占的是客户端的内存,不会影响Proxy。
+
+  
+
+Q4:问出现查询大数据量到内存的场景,是不是只能使用原生JDBC,查一批处理一批,不放内存?
+
+A4:Mybatis是在客户端控制的,不影响Proxy。
+
+  
+
+### 直播回放链接
+
+https://m.qlchat.com/topic/details?topicId=2000001395952730&minimal=1
+
+想了解关于Sharding-Sphere的更多细节?
+
+**不妨来“2018 DAMS中国数据资产管理峰会”**
+
+**听听京东金融数据研发负责人张亮老师的解析**
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/proxy15.jpg)
+
diff --git a/docs/blog/content/material/proxy.en.md b/docs/blog/content/material/proxy.en.md
new file mode 100644
index 0000000..839186d
--- /dev/null
+++ b/docs/blog/content/material/proxy.en.md
@@ -0,0 +1,7 @@
++++
+title = "proxy"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/realization.cn.md b/docs/blog/content/material/realization.cn.md
new file mode 100644
index 0000000..a92e22a
--- /dev/null
+++ b/docs/blog/content/material/realization.cn.md
@@ -0,0 +1,382 @@
++++
+title = "分布式事务在Sharding-Sphere中的实现"
+weight = 2
+chapter = true
++++
+
+## 分布式事务在Sharding-Sphere中的实现
+
+### 讲师简介
+
+**赵俊**
+
+京东金融
+
+高级Java开发工程师
+
+- 多年互联网开发经验,热爱开源技术,对分布式存储有浓厚的兴趣。熟悉ElasticSearch、HBase、Presto、Storm等离线和实时数据处理
+
+- 目前主要在Sharding-Sphere团队负责分布式事务的开发
+
+### 分布式事务的使用场景
+
+#### ACID
+
+一切从ACID开始说起。ACID是本地事务所具有的四大特征:
+
+*   **Atomicity:原子性**
+    
+    事务作为整体来执行,要么全部执行,要么全不执行。
+    
+*   **Consistency:一致性**
+    
+    事务应确保数据从一个一致的状态转变为另一个一致的状态。
+    
+*   **Isolation:隔离性**
+    
+    多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
+    
+*   **Durability:持久性**
+    
+    已提交的事务修改数据会被持久保持。
+    
+
+关系型数据库的本地事务完美的提供了对ACID的原生支持。但在分布式的场景下,它却成为系统性能的桎梏。如何让数据库在分布式场景下满足ACID的特性或找寻相应的替代方案,是本文将要阐述的话题。
+
+#### CAP和Base理论
+
+对于互联网应用而言,随着访问量和数据量的激增,传统的单体架构模式将无法满足业务的高速发展。这时,开发者需要把单体应用拆分为多个独立的小应用,把单个数据库按照分片规则拆分为多个库和多个表。
+
+数据拆分后,如何在多个数据库节点间保证本地事务的ACID特性则成为一个技术难题,并且由此而衍生出了CAP和BASE经典理论。
+
+CAP理论指出,对于分布式的应用而言,不可能同时满足C(一致性),A(可用性),P(分区容错性),由于网络分区是分布式应用的基本要素,因此开发者需要在C和A上做出平衡。  
+
+由于C和A互斥性,其权衡的结果就是BASE理论。  
+
+对于大部分的分布式应用而言,只要数据在规定的时间内达到最终一致性即可。我们可以把符合传统的ACID叫做刚性事务,把满足BASE理论的最终一致性事务叫做柔性事务。  
+
+一味的追求强一致性,并非最佳方案。对于分布式应用来说,刚柔并济是更加合理的设计方案,即在本地服务中采用强一致事务,在跨系统调用中采用最终一致性。如何权衡系统的性能与一致性,是十分考验架构师与开发者的设计功力的。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization1.jpg)
+
+### 业界方法
+
+具体到分布式事务的实现上,业界主要采用了XA协议的强一致规范以及柔性事务的最终一致规范。
+
+#### XA
+
+XA是X/Open CAE Specification (Distributed Transaction Processing)模型中定义的TM(Transaction Manager)与RM(Resource Manager)之间进行通信的接口。
+
+Java中的javax.transaction.xa.XAResource定义了XA接口,它依赖数据库厂商对jdbc-driver的具体实现。
+
+mysql-connector-java-5.1.30的实现可参考:
+
+com.mysql.jdbc.jdbc2.optional.MysqlXAConnection。  
+
+在XA规范中,数据库充当RM角色,应用需要充当TM的角色,即生成全局的txId,调用XAResource接口,把多个本地事务协调为全局统一的分布式事务。  
+
+**一阶段提交:弱XA**
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization2.jpg)
+弱XA通过去掉XA的Prepare阶段,以达到减少资源锁定范围而提升并发性能的效果。典型的实现为在一个业务线程中,遍历所有的数据库连接,依次做commit或者rollback。弱XA同本地事务相比,性能损耗低,但在事务提交的执行过程中,若出现网络故障、数据库宕机等预期之外的异常,将会造成数据不一致,且无法进行回滚。基于弱XA的事务无需额外的实现成本,因此Sharding-Sphere默认支持。
+
+**二阶段提交:2PC**
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization3.jpg)
+
+二阶段提交是XA的标准实现。它将分布式事务的提交拆分为2个阶段:prepare和commit/rollback。
+
+开启XA全局事务后,所有子事务会按照本地默认的隔离级别锁定资源,并记录undo和redo日志,然后由TM发起prepare投票,询问所有的子事务是否可以进行提交:当所有子事务反馈的结果为“yes”时,TM再发起commit;若其中任何一个子事务反馈的结果为“no”,TM则发起rollback;如果在prepare阶段的反馈结果为yes,而commit的过程中出现宕机等异常时,则在节点服务重启后,可根据XA recover再次进行commit补偿,以保证数据的一致性。
+
+2PC模型中,在prepare阶段需要等待所有参与子事务的反馈,因此可能造成数据库资源锁定时间过长,不适合并发高以及子事务生命周长较长的业务场景。
+
+Sharding-Sphere支持基于XA的强一致性事务解决方案,可以通过SPI注入不同的第三方组件作为事务管理器实现XA协议,如Atomikos和Narayana。
+
+#### 柔性事务
+
+柔性事务是对XA协议的妥协和补偿,它通过对强一致性要求的降低,已达到降低数据库资源锁定时间的效果。柔性事务的种类很多,可以通过各种不同的策略来权衡使用。
+
+**一阶段提交 + 补偿 :最大努力送达(BED)**
+
+最大努力送达,是针对于弱XA的一种补偿策略。它采用事务表记录所有的事务操作SQL,如果子事务提交成功,将会删除事务日志;如果执行失败,则会按照配置的重试次数,尝试再次提交,即最大努力的进行提交,尽量保证数据的一致性,这里可以根据不同的业务场景,平衡C和A,采用同步重试或异步重试。
+
+这种策略的优点是无锁定资源时间,性能损耗小。缺点是尝试多次提交失败后,无法回滚,它仅适用于事务最终一定能够成功的业务场景。因此BED是通过事务回滚功能上的妥协,来换取性能的提升。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization4.jpg)
+
+**TCC: Try-Confirm-Cancel**  
+
+TCC模型是把锁的粒度完全交给业务处理,它需要每个子事务业务都实现Try-Confirm/Cancel接口。
+
+*   **Try:**
+    
+    尝试执行业务;
+    
+    完成所有业务检查(一致性);
+    
+    预留必须业务资源(准隔离性);
+    
+*   **Confirm:**
+    
+    确认执行业务;
+    
+    真正执行业务,不作任何业务检查;
+    
+    只使用Try阶段预留的业务资源;
+    
+    Confirm操作满足幂等性;
+    
+*   **Cancel:**
+    
+    取消执行业务;
+    
+    释放Try阶段预留的业务资源;
+    
+    Cancel操作满足幂等性。
+    
+
+这三个阶段都会按本地事务的方式执行,不同于XA的prepare,TCC无需将XA的投票期间的所有资源挂起,因此极大的提高了吞吐量。  
+
+下面对TCC模式下,A账户往B账户汇款100元为例子,对业务的改造进行详细的分析:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization5.jpg)
+
+汇款服务和收款服务分别需要实现,Try-Confirm-Cancel接口,并在业务初始化阶段将其注入到TCC事务管理器中。
+
+汇款服务
+
+*   **Try:**
+    
+    检查A账户有效性,即查看A账户的状态是否为“转帐中”或者“冻结”;
+    
+    检查A账户余额是否充足;
+    
+    从A账户中扣减100元,并将状态置为“转账中”;
+    
+    预留扣减资源,将从A往B账户转账100元这个事件存入消息或者日志中;
+    
+*   **Confirm:**
+    
+    不做任何操作;
+    
+*   **Cancel:**
+    
+    A账户增加100元;
+    
+    从日志或者消息中,释放扣减资源。
+    
+
+收款服务
+
+*   **Try:**
+    
+    检查B账户账户是否有效;
+    
+*   **Confirm**:
+    
+    读取日志或者消息,B账户增加100元;
+    
+    从日志或者消息中,释放扣减资源;
+    
+*   **Cancel:**
+    
+    不做任何操作。
+    
+
+由此可以看出,TCC模型对业务的侵入强,改造的难度大。  
+
+**消息驱动**
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization6.jpg)
+
+消息一致性方案是通过消息中间件保证上下游应用数据操作的一致性。基本思路是将本地操作和发送消息放在一个事务中,下游应用向消息系统订阅该消息,收到消息后执行相应操作。本质上是依靠消息的重试机制,达到最终一致性。消息驱动的缺点是:耦合度高,需要在业务系统中引入MQ,导致系统复杂度增加。
+
+**SAGA**
+
+Saga起源于1987年Hector & Kenneth发表的论文Sagas。
+
+参考地址:
+
+https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
+
+Saga工作原理
+
+Saga模型把一个分布式事务拆分为多个本地事务,每个本地事务都有相应的执行模块和补偿模块( TCC中的Confirm和Cancel)。当Saga事务中任意一个本地事务出错时,可以通过调用相关的补偿方法恢复之前的事务,达到事务最终的一致性。
+
+当每个Saga子事务 T1, T2, …, Tn 都有对应的补偿定义 C1, C2, …, Cn-1,那么Saga系统可以保证:
+
+*   子事务序列 T1, T2, …, Tn得以完成 (最佳情况);
+    
+*   或者序列 T1, T2, …, Tj, Cj, …, C2, C1, 0 < j < n, 得以完成。
+    
+
+由于Saga模型中没有Prepare阶段,因此事务间不能保证隔离性,当多个Saga事务操作同一资源时,就会产生更新丢失、脏数据读取等问题,这时需要在业务层控制并发,例如:
+
+*   在应用层面加锁;
+    
+*   应用层面预先冻结资源。
+    
+
+Saga恢复方式
+
+Saga支持向前和向后恢复:
+
+*   向后恢复:补偿所有已完成的事务,如果任一子事务失败;
+    
+*   向前恢复:重试失败的事务,假设每个子事务最终都会成功。
+    
+
+显然,向前恢复没有必要提供补偿事务,如果你的业务中,子事务(最终)总会成功,或补偿事务难以定义或不可能,向前恢复更符合你的需求。理论上补偿事务永不失败,然而,在分布式世界中,服务器可能会宕机、网络可能会失败,甚至数据中心也可能会停电,这时需要提供故障恢复后回退的机制,比如人工干预。
+
+总的来说,TCC和MQ都是以服务为范围进行分布式事务的处理,而XA、BED、SAGA则是以数据库为范围进行分布式处理,我们更趋向于选择后者,对于业务而言侵入小,改造的成本低。
+
+### Sharding-Sphere对分布式事务的支持
+
+Sharding-Sphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这3款相互独立的产品组成。它们均提供标准化的数据分片、读写分离、柔性事务和数据治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。
+
+项目地址:
+
+https://github.com/sharding-sphere/sharding-sphere/
+
+Sharding-Sphere同时支持XA和柔性事务,它允许每次对数据库的访问,可以自由选择事务类型。分布式事务对业务操作完全透明,极大地降低了引入分布式事务的成本。
+
+#### 事务模型
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization7.jpg)
+
+Sharding-Sphere事务管理器集成了XA和柔性事务模型:
+
+- 对于XA事务而言,采用SPI的方式让弱XA、Atomikos、Narayana间保持互斥;
+    
+- 对于柔性事务而言,根据每次连接中事务的类型,可以选择独立的事务管理器进行处理,每个事务管理器都会实现标准的ShardingTransaction接口,在TransactionEvent到来时,执行对应的begin、commit、rollback操作。
+    
+
+下面将Sharding-Sphere内部如何用事件驱动方式,将事务从分片主流程中解耦进行详细说明:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization8.jpg)
+
+从图可以看出在Sharding-core在调用执行引擎时,会根据SQL的种类产生事件进行分发。事务监听线程在收到符合要求的事件后,再调用对应的事务处理器进行处理。
+
+#### Sharding-Proxy事务实现
+
+Sharding-Proxy是基于netty开发的数据库中间代理层,实现了标准的MySQL协议,可以看做是一个实现了数据分片的数据库。Sharding-Proxy已经实现了基于Atomikos的XA事务,为了保证所有的子事务都处于同一个线程之中,整个Proxy的线程模型进行了如下的调整:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization9.jpg)
+
+当开启事务后,Proxy后端的SQL命令执行引擎将采用一通道一线程的模式,此事务线程的生命周期同通道保持一致。事务处理的具体过程与Proxy彻底解耦,即Proxy将发布事务类型的事件,然后Sharding-Sphere-TM根据传入的事务消息,选择具体的TM进行处理。
+
+压测结果表明:XA事务的插入和更新的性能,基本上同跨库的个数呈线性关系,查询的性能基本不受影响,建议在并发量不大,每次事务涉及的库在10个以内时,可以使用XA。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization10.jpg)
+
+Atomikos事务管理器原理分析
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization11.jpg)
+
+Atomikos的事务管理器可以内嵌到业务进程中,当应用调用TransactionManager.begin时,将会创建本次XA事务,并且与当前线程关联。同时Atomikos也对DataSource中的connection做了二次封装,代理connection中含有本次事务相关信息的状态,并且拦截了connection的JDBC操作。
+
+在createStatement时,调用XAResource.start进行资源注册;在close时,调用XAResource.end让XA事务处于idel可提交状态;在commit或rollback时,依次调用prepare和commit进行二阶段提交。
+
+**Sharding-Sphere的Saga事务实现**
+
+Sharding-Sphere通过与Apache Service Comb的合作,将采用Service Comb的Saga事务引擎作为的分布式事务实现。
+
+Apache Service Comb是华为开源的微服务框架,其中微服务事务处理框架分为集中式和分布式协调器。未来会在Sharding-Sphere内部集成Saga集中式协调器,支持同一线程内不同服务(本地)间的分布式事务。
+
+参考链接:
+
+https://github.com/apache/incubator-servicecomb-saga
+
+Service Comb 集中式事务协调器
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization12.jpg)
+
+集中式的协调器,包含了Saga调用请求接收、分析、执行以及结果查询的内容。任务代理模块需要预先知道Saga事务调用关系图,执行模块根据生成的调用图产生调用任务,调用相关微服务服务接口。如果服务调用执行出错,会调用服务的相关的补偿方法回滚。
+
+Saga执行模块通过分析请求的JSON数据,来构建一个调用关系图。Sharding-Sphere是通过JSON描述Saga事务串行调用子事务或者并行调用子事务。关系调用图被Saga实现中的任务运行模块分解成为一个一个执行任务,执行任务由任务消费者获取并生成相关的调用 (同时支持串行和并行调用)。Saga任务会根据执行的情况向Saga Log中记录对应的Saga事务的关键事件,并可以通过事件查看器查查询执行情况。
+
+Sharding-Sphere内嵌Saga事务管理器
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization13.jpg)
+
+Saga以jar包的形式提供分布式事务治理能力。
+
+对Sharding-Sphere而言,confirm和cancel过程代表了子事务中的正常执行SQL和逆向执行SQL,(未来Sharding-Sphere将提供自动生成逆向SQL的能力)。当启用Saga柔性事务后,路由完成之后的物理数据源将开启本地自动提交事务,每次confirm和cancel都会直接提交。
+
+在Sharding-Sphere内部,触发SQL执行引擎后,将会产生Saga事务事件,这时Sharding-Sphere事务监听器会注册本次子事务的confirm和cancel至Saga事务管理器的队列中;在业务线程触发commit和rollback后,Saga事务管理器再根据子事务执行的结果,判断进行confirm重试或者cancel流程。
+
+### 未来计划
+
+未来Sharding-Sphere将按照文中介绍的Sharding-Sphere-TM逐步完善整个事务框架:
+
+*   弱XA事务 (已发布)
+    
+*   基于Atomikos的XA事务(近期发布)
+    
+*   基于Narayana的XA事务(规划中)
+    
+*   BED柔性事务(已发布)
+    
+*   SAGA(开发中)
+    
+*   TCC(规划中)
+    
+
+如果前面的分享太过冗长,那么千言万语汇聚成一张表格,欢迎阅读。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/realization14.jpg)
+
+未来,我们将不断优化当前的特性,陆续推出大家关注的柔性事务、数据治理等更多新特性。如果有什么想法、意见和建议,也欢迎留言交流,更欢迎加入到Sharding-Sphere的开源项目中:
+
+*   https://github.com/sharding-sphere/sharding-sphere/
+    
+*   https://gitee.com/sharding-sphere/sharding-sphere/
+
+### Q&A
+
+**Q1**:基于XA的事物,可以应用到微服务架构中吗?
+
+**A1**:目前我们是把事务管理器内嵌到JVM进程中,对于并发量小,短事务的业务,可以用XA。
+
+  
+
+**Q2**:对于各个事务框架开发计划的先后顺序是基本什么来确定的呢?
+
+**A2**:基于难易程度,所以我们把TCC放到了最后。
+
+  
+
+**Q3**:支持多语言吗?比如golang?
+
+**A3**:多语言可以用Sharding-Proxy。
+
+  
+
+**Q4**:这次是Proxy实现分布式事务吧?我记得之前Sharding-JDBC有实现。
+
+**A4**:这次是整个SS的事务实现,包含Sharding-JDBC和Proxy,目前SJ的实现是弱XA和BED(最大努力送达),以后会增加SAGA和TCC。
+
+  
+
+**Q5**:如果我只想用SS里的事务模块,可以吗?
+
+**A5**:SS是以事件驱动的方式进行的架构,未来事务模块只负责事务相关的处理。
+
+  
+
+**Q6**:SAGA不支持ACID中的I,咱们这边怎么考虑的呢?
+
+**A6**:目前暂不支持隔离性,今后我们有增加I的规划,其实所有的柔性事务都不支持I,TCC增加了Try阶段,可以理解是准隔离性,使用SAGA时,可以在业务层面控制并发,防止脏读等产生。
+
+  
+
+**Q7**:那意思,现在3的版本还不能单独用事务的模块?
+
+**A7**:现在3.0版本,事务模块依赖了Sharding-JDBC模块,事务模块需要监听Sharding-JDBC和Proxy中的事件,然后进行事务操作。如果你想单独用事务模块,需要按Core中定义的事件,在你的业务里进行发布。
+
+### 直播回放
+
+https://m.qlchat.com/topic/details?topicId=2000001669563722&tracePage=liveCenter
+
+
+
diff --git a/docs/blog/content/material/realization.en.md b/docs/blog/content/material/realization.en.md
new file mode 100644
index 0000000..ef9f54b
--- /dev/null
+++ b/docs/blog/content/material/realization.en.md
@@ -0,0 +1,7 @@
++++
+title = "realization"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/result.cn.md b/docs/blog/content/material/result.cn.md
new file mode 100644
index 0000000..e3316b7
--- /dev/null
+++ b/docs/blog/content/material/result.cn.md
@@ -0,0 +1,184 @@
++++
+title = "剖析Sharding-Sphere系列——结果归并 "
+weight = 2
+chapter = true
++++
+
+## 剖析Sharding-Sphere系列——结果归并 
+
+这一系列文章是由SS的核心开发成员亲自操刀向大家介绍和剖析SS的核心模块、所使用的前沿技术、有价值的经验总结等。这一系列的文章将带您走进SS的内核世界,获得新知、激发灵感。更希望您关注我们,共同交流切磋,一同前行。
+
+### 讲师介绍
+
+张亮,原当当架构部负责人。热爱开源,目前主导两个开源项目Elastic-Job和Sharding-Sphere(Sharding-JDBC)。擅长以java为主分布式架构以及以Kubernetes和Mesos为主的云平台方向,推崇优雅代码,对如何写出具有展现力的代码有较多研究。2018年初加入京东金融,现担任数据研发负责人。目前主要精力投入在将Sharding-Sphere打造为业界一流的金融级数据解决方案之上。
+
+### 简介
+
+将从各个数据节点获取的多数据结果集,组合成为一个结果集并正确的返回至请求客户端,称为结果归并。
+
+  
+
+Sharding-Sphere支持的结果归并从功能上分为遍历、排序、分组和分页4种类型,它们是组合而非互斥的关系。从结构划分,可分为流式归并、内存归并和装饰者归并。流式归并和内存归并是互斥的,装饰者归并可以在流式归并和内存归并之上做进一步的处理。
+
+  
+
+由于从数据库中返回的结果集是逐条返回的,并不需要将所有的数据一次性加载至内存中,因此,在进行结果归并时,沿用数据库返回结果集的方式进行归并,能够极大减少内存的消耗,是归并方式的优先选择。
+
+  
+
+流式归并是指每一次从结果集中获取到的数据,都能够通过逐条获取的方式返回正确的单条数据,它与数据库原生的返回结果集的方式最为契合。遍历、排序以及流式分组都属于流式归并的一种。
+
+  
+
+内存归并则是需要将结果集的所有数据都遍历并存储在内存中,再通过统一的分组、排序以及聚合等计算之后,再将其封装成为逐条访问的数据结果集返回。
+
+  
+
+装饰者归并是对所有的结果集归并进行统一的功能增强,目前装饰者归并只有分页归并这一种类型。
+
+### 分类
+
+#### 遍历归并
+
+  
+
+它是最为简单的归并方式。只需将多个数据结果集合并为一个单向链表即可。在遍历完成链表中当前数据结果集之后,将链表元素后移一位,继续遍历下一个数据结果集即可。
+
+#### 排序归并
+
+由于在SQL中存在ORDER BY语句,因此每个数据结果集自身是有序的,因此只需要将数据结果集当前游标指向的数据值进行排序即可。这相当于对多个有序的数组进行排序,归并排序是最适合此场景的排序算法。
+
+Sharding-Sphere在对排序的查询进行归并时,将每个结果集的当前数据值进行比较(通过实现Java的Comparable接口完成),并将其放入优先级队列。每次获取下一条数据时,只需将队列顶端结果集的游标下移,并根据新游标重新进入优先级排序队列找到自己的位置即可。通过一个例子来说明Sharding-Sphere的排序归并,下图是一个通过分数进行排序的示例图。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result1.jpg)
+
+示例中展示了3张表返回的数据结果集,每个数据结果集已经根据分数排序完毕,但是3个数据结果集之间是无序的。将3个数据结果集的当前游标指向的数据值进行排序,并放入优先级队列,t_score_0的第一个数据值最大,t_score_2的第一个数据值次之,t_score_1的第一个数据值最小,因此优先级队列根据t_score_0,t_score_2和t_score_1的方式排序队列。
+
+下图则展现了进行next调用的时候,排序归并是如何进行的。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result2.jpg)
+
+通过图中我们可以看到,当进行第一次next调用时,排在队列首位的t\_score\_0将会被弹出队列,并且将当前游标指向的数据值(也就是100)返回至查询客户端,并且将游标下移一位之后,重新放入优先级队列。而优先级队列也会根据t\_score\_0的当前数据结果集指向游标的数据值(这里是90)进行排序,根据当前数值,t\_score\_0排列在队列的最后一位。之前队列中排名第二的t\_score\_2的数据结果集则自动排在了队列首位。
+
+  
+
+在进行第二次next时,只需要将目前排列在队列首位的t\_score\_2弹出队列,并且将其数据结果集游标指向的值返回至客户端,并下移游标,继续加入队列排队,以此类推。
+
+  
+
+当一个结果集中已经没有数据了,则无需再次加入队列。
+
+  
+
+可以看到,对于每个数据结果集中的数据有序,而多数据结果集整体无序的情况下,Sharding-Sphere无需将所有的数据都加在至内存即可排序,它使用的是流式归并的方式,每次next仅获取唯一正确的一条数据,极大的节省了内存的消耗。
+
+  
+
+从另一个角度来说,Sharding-Sphere的排序归并,是在维护数据结果集的纵轴和横轴这两个维度的有序性。纵轴是指每个数据结果集本身,它是天然有序的,它通过包含ORDER BY的SQL所获取。横轴是指每个数据结果集当前游标所指向的值,它需要通过优先级队列来维护其正确顺序。每一次数据结果集当前游标的下移,都需要将该数据结果集重新放入优先级队列排序,而只有排列在队列首位的数据结果集才可能发生游标下移的操作。
+
+#### 分组归并
+
+分组归并的情况最为复杂,它分为流式分组归并和内存分组归并。流式分组归并要求SQL的排序项与分组项的字段以及排序类型(ASC或DESC)必须保持一致,否则只能通过内存归并才能保证其数据的正确性。
+
+  
+
+举例说明,假设根据科目分片,表结构中包含考生的姓名(为了简单起见,不考虑重名的情况)和分数。通过SQL获取每位考生的总分,可通过如下SQL:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result3.jpg)
+
+在分组项与排序项完全一致的情况下,取得的数据是连续的,分组所需的数据全数存在于各个数据结果集的当前游标所指向的数据值,因此可以采用流式归并。如下图所示。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result4.jpg)
+
+进行归并时,逻辑与排序归并类似。下图展现了进行next调用的时候,流式分组归并是如何进行的。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result5.jpg)
+
+
+通过图中我们可以看到,当进行第一次next调用时,排在队列首位的t\_score\_java将会被弹出队列,并且将分组值同为“Jetty”的其他结果集中的数据一同弹出队列。在获取了所有的姓名为“Jetty”的同学的分数之后,进行累加操作,那么,在第一次next调用结束后,取出的结果集是“Jetty”的分数总和。于此同时,所有的数据结果集中的游标都将下移至数据值“Jetty”的下一个不同的数据值,并且根据数据结果集当前游标指向的值进行重排序。因此,包含名字顺着第二位的“John”的相关数据结果集则排在的队列的前列。
+
+  
+
+流式分组归并与排序归并的区别仅仅在于两点:
+
+  
+
+1.它会一次性的将多个数据结果集中的分组项相同的数据全数取出。
+
+2.它需要根据聚合函数的类型进行聚合计算。
+
+  
+
+对于分组项与排序项不一致的情况,由于需要获取分组的相关的数据值并非连续的,因此无法使用流式归并,需要将所有的结果集数据加载至内存中进行分组和聚合。例如,若通过以下SQL获取每位考生的总分并按照分数从高至低排序:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result6.jpg)
+
+
+那么各个数据结果集中取出的数据与分数进行排序示例图的上半部分的表结构的原始数据一致,是无法进行流式归并的。
+
+  
+
+当SQL中只包含分组语句时,根据不同数据库的实现,其排序的顺序不一定与分组顺序一致。但由于排序语句的缺失,则表示此SQL并不在意排序顺序。因此,Sharding-Sphere通过SQL优化的改写,自动增加与分组项一致的排序项,使其能够从消耗内存的内存分组归并方式转化为流式分组归并方案。
+
+  
+
+无论是流式分组归并还是内存分组归并,对聚合函数的处理都是一致的。聚合函数可以归类为比较、累加和求平均值这3种类型。
+
+  
+
+比较类型的聚合函数是指MAX和MIN。它们需要对每一个同组的结果集数据进行比较,并且直接返回其最大或最小值即可。
+
+  
+
+累加类型的聚合函数是指SUM和COUNT。它们需要将每一个同组的结果集数据进行累加。
+
+  
+
+求平均值的聚合函数只有AVG。它必须通过SQL改写的SUM和COUNT进行计算,相关内容已在SQL改写的内容中涵盖,不再赘述。
+
+#### 分页归并
+
+上文所述的所有归并类型都可能进行分页。分页是追加在其他归并类型之上的装饰器,Sharding-Sphere通过装饰者模式来增加对数据结果集进行分页的能力。分页归并负责将无需获取的数据过滤掉。
+
+  
+
+Sharding-Sphere的分页功能比较容易让使用者误解,用户通常认为分页归并会占用大量内存。在分布式的场景中,将LIMIT 10000000, 10改写为LIMIT 0, 10000010,才能保证其数据的正确性。用户非常容易产生Sharding-Sphere会将大量无意义的数据加载至内存中,造成内存溢出风险的错觉。其实,通过流式归并的原理可知,会将数据全部加载到内存中的只有内存分组归并这一种情况,而通常来说,进行OLAP的分组SQL,不会产生大量的结果数据,它更多的用于大量的计算,以及少量结果产出的场景。除了内存分组归并这种情况之外,其他情况都通过流式归并获取数据结果集,因此Sharding-Sphere会通过结果集的next方法将无需取出的数据全部跳过,并不会将其存入内存。
+
+  
+
+但同时需要注意的是,由于排序的需要,大量的数据仍然需要传输到Sharding-Sphere的内存空间。因此,采用LIMIT这种方式分页,并非最佳实践。 由于LIMIT并不能通过索引查询数据,因此如果可以保证ID的连续性,通过ID进行分页是比较好的解决方案,例如:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result7.jpg)
+
+
+或通过记录上次查询结果的最后一条记录的ID进行下一页的查询,例如:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result8.jpg)
+
+### 小结
+
+归并引擎的整体结构划分如下图所示。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/result9.jpg)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/blog/content/material/result.en.md b/docs/blog/content/material/result.en.md
new file mode 100644
index 0000000..44d52f4
--- /dev/null
+++ b/docs/blog/content/material/result.en.md
@@ -0,0 +1,7 @@
++++
+title = "result_merge"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/seata.cn.md b/docs/blog/content/material/seata.cn.md
new file mode 100644
index 0000000..0f64f41
--- /dev/null
+++ b/docs/blog/content/material/seata.cn.md
@@ -0,0 +1,71 @@
++++
+title = "整合Seata AT分布式事务"
+weight = 2
+chapter = true
++++
+
+## Apache ShardingSphere整合Seata AT分布式事务
+
+### 背景知识
+
+Seata是阿里集团和蚂蚁金服联合打造的分布式事务框架,目前版本包含了AT事务和TCC事务。其中AT事务的目标是在微服务架构下,提供增量的事务ACID语意,让用户像使用本地事务一样,使用分布式事务,核心理念同ShardingSphere一脉相承。
+
+Github: https://github.com/seata/seata
+
+### Seata AT模型
+
+Seata AT事务模型包含TM(事务管理器),RM(资源管理器),TC(事务协调器)。
+
+其中TC是一个独立的服务需要单独部署,TM和RM以jar包的方式同业务应用部署在一起,它们同TC建立长连接,在整个事务生命周期内,保持RPC通信。 
+
+其中全局事务的发起方作为TM,全局事务的参与者作为RM ; TM负责全局事务的begin和commit/rollback,RM负责分支事务的执行和commit/rollback。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/seata1.jpg)
+
+### ShardingSphere分布式事务SPI
+
+ShardingSphere提供了一套接入分布式事务的SPI,设计的目标是保证数据分片后,事务的ACID语意。分布式事务的实现目前主要包含两阶段的XA和BASE柔性事务。Seata AT事务作为BASE柔性事务的一种实现,可以无缝接入到ShardingSphere生态中。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/seata2.jpg)
+
+两阶段XA事务方面,我们已经整合了Atomikos,Narayana,Bitronix事务管理器,XA事务底层依赖具体的数据库厂商对XA两阶段提交协议的支持,通常XA协议通过在Prepare和Commit阶段进行2PL(2阶段锁),保证了分布式事务的ACID,通常适用于短事务及非云化环境(云化环境下一次IO操作大概需要20ms,两阶段锁会锁住资源长达40ms,因此事务的TPS会降到25/s左右,非云化环境通常一次IO只需几毫秒,因此锁热点数据的时间相对较低)\[1\]。
+
+BASE柔性事务方面,目前我们已经完成了对ServiceComb Saga的整合,Saga通过一阶段提交+补偿的方式提高了整体事务的性能,其中补偿的方式同Seata大致相同,即对分片后的物理SQL进行revert来生成补偿的SQL,但Saga模型在理论上不支持隔离级别,适用于对性能要求较高,对一致性要求比较低的业务。Seata AT事务在一阶段提交+补偿的基础上,通过TC的全局锁实现了RC隔离级别的支持,是介于XA和Saga之间的另一种实现。消息柔性事务方面,也欢迎大家参考我们的SPI提供整合的方案。
+
+### 整合方案
+
+整合Seata AT事务时,需要把TM,RM,TC的模型融入到ShardingSphere 分布式事务的SPI的生态中。在数据库资源上,Seata通过对接DataSource接口,让JDBC操作可以同TC进行RPC通信。同样,ShardingSphere也是面向DataSource接口对用户配置的物理DataSource进行了聚合,因此把物理DataSource二次包装为Seata的DataSource后,就可以把Seata AT事务融入到ShardingSphere的分片中。
+
+在Seata模型中,全局事务的上下文存放在线程变量中,通过扩展服务间的transport,可以完成线程变量的传递,分支事务通过线程变量判断是否加入到整个Seata全局事务中。而ShardingSphere的分片执行引擎通常是按多线程执行,因此整合Seata AT事务时,需要扩展主线程和子线程的事务上下文传递,这同服务间的上下文传递思路完全相同。
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/seata3.jpg)
+
+### Quick Start
+
+我们已经实现了base-seata-raw-jdbc-example,大家可以自行进行尝试。
+
+https://github.com/apache/incubator-shardingsphere-example/tree/dev/sharding-jdbc-example/transaction-example/transaction-base-seata-example/transaction-base-seata-raw-jdbc-example
+
+操作手册:
+
+1.按照seata-work-shop中的步骤,下载并启动seata server。
+
+https://github.com/seata/seata-workshop
+
+参考 Step6 和 Step7即可
+
+2.在每一个分片数据库实例中执行resources/sql/undo_log.sql脚本,创建undo_log表
+
+3.Run YamlConfigurationTransactionExample.java
+
+### 待优化项
+
+Seata AT事务在Revert SQL时,需要对ShardingSphere分片后的物理SQL进行二次的解析,这里我们需要设计一个SPI,避免SQL二次解析的性能损耗。
+
+参考论文
+
+[1]: Transactions for Distributed Actors in the Cloud
+
+https://www.microsoft.com/en-us/research/wp-content/uploads/2016/10/EldeebBernstein-TransactionalActors-MSR-TR-1.pdf
+
+
diff --git a/docs/blog/content/material/seata.en.md b/docs/blog/content/material/seata.en.md
new file mode 100644
index 0000000..84b3b80
--- /dev/null
+++ b/docs/blog/content/material/seata.en.md
@@ -0,0 +1,7 @@
++++
+title = "Seata_AT"
+weight = 2
+chapter = true
++++
+
+## TODO
diff --git a/docs/blog/content/material/solution.cn.md b/docs/blog/content/material/solution.cn.md
new file mode 100644
index 0000000..2bde9ab
--- /dev/null
+++ b/docs/blog/content/material/solution.cn.md
@@ -0,0 +1,247 @@
++++
+title = "刚柔并济的开源分布式事务解决方案"
+weight = 2
+chapter = true
++++
+
+## 刚柔并济的开源分布式事务解决方案
+
+### 作者
+
+张亮,京东数科数据研发负责人,Apache ShardingSphere发起人 & PPMC
+
+热爱开源,目前主导开源项目ShardingSphere(原名Sharding-JDBC)和Elastic-Job。擅长以java为主分布式架构以及以Kubernetes和Mesos为主的云平台方向,推崇优雅代码,对如何写出具有展现力的代码有较多研究。
+
+目前主要精力投入在将ShardingSphere打造为业界一流的金融级数据解决方案之上。ShardingSphere已经进入Apache孵化器,是京东集团首个进入Apache基金会的开源项目,也是Apache基金会首个分布式数据库中间件。
+
+---
+姜宁,华为开源能力中心技术专家,Apache ServiceComb项目负责人。前红帽软件首席软件工程师,在企业级开源中间件开发方面有十余年经验,有丰富的Java开发和使用经验,函数式编程爱好者。从2006年开始一直从事Apache开源中间件项目的开发工作,先后参与Apache CXF,Apache Camel,以及Apache ServiceMix的开发。对微服务架构,WebServices,Enterprise Integration Pattern,SOA, OSGi 均有比较深入的研究。
+
+博客地址:https://willemjiang.github.io/
+
+---
+
+冯征,红帽软件工程师。2009年加入红帽软件公司,主要从事事务管理器方面的工作,做为核心开发人员参与了Narayan和Blacktie项目,在与多个应用服务器(Wildfly, Karaf, Tomcat)和框架(Common DBCP, Spring Boot)的事务处理集成方面有过贡献。从2017年开始参与了Apache ServiceComb项目,目前是PMC成员之一。对于分布式事务处理以及微服务环境中的事务处理,有过深入的研究。
+
+### 导读
+
+相比于数据分片方案的逐渐成熟,集性能、透明化、自动化、强一致、并能适用于各种应用场景于一体的分布式事务解决方案则显得凤毛麟角。基于两(三)阶段提交的分布式事务的性能瓶颈以及柔性事务的业务改造问题,使得分布式事务至今依然是令架构师们头疼的问题。
+
+Apache ShardingSphere(Incubating)不失时机的在2019年初,提供了一个刚柔并济的一体化分布式事务解决方案。如果您的应用系统正在受到这方面的困扰,不妨倒上一杯咖啡,花十分钟阅读此文,说不定会有些收获呢?
+
+### 背景
+
+数据库事务需要满足ACID(原子性、一致性、隔离性、持久性)4个特性。
+
+- 原子性(Atomicity)指事务作为整体来执行,要么全部执行,要么全不执行。
+
+- 一致性(Consistency)指事务应确保数据从一个一致的状态转变为另一个一致的状态。
+
+- 隔离性(Isolation)指多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
+
+- 持久性(Durability)指已提交的事务修改数据会被持久保存。
+
+在单一数据节点中,事务仅限于对单一数据库资源的访问控制,称之为本地事务。几乎所有的成熟的关系型数据库都提供了对本地事务的原生支持。 但是在基于微服务的分布式应用环境下,越来越多的应用场景要求对多个服务的访问及其相对应的多个数据库资源能纳入到同一个事务当中,分布式事务应运而生。
+
+关系型数据库虽然对本地事务提供了完美的ACID原生支持。 但在分布式的场景下,它却成为系统性能的桎梏。如何让数据库在分布式场景下满足ACID的特性或找寻相应的替代方案,是分布式事务的重点工作。
+
+#### 本地事务
+
+在不开启任何分布式事务管理器的前提下,让每个数据节点各自管理自己的事务。 它们之间没有协调以及通信的能力,也并不互相知晓其他数据节点事务的成功与否。 本地事务在性能方面无任何损耗,但在强一致性以及最终一致性方面则力不从心。
+
+#### 两阶段提交
+
+XA协议最早的分布式事务模型是由X/Open国际联盟提出的X/Open Distributed Transaction Processing(DTP)模型,简称XA协议。
+
+基于XA协议实现的分布式事务对业务侵入很小。 它最大的优势就是对使用方透明,用户可以像使用本地事务一样使用基于XA协议的分布式事务。 XA协议能够严格保障事务ACID特性。
+
+严格保障事务ACID特性是一把双刃剑。 事务执行在过程中需要将所需资源全部锁定,它更加适用于执行时间确定的短事务。 对于长事务来说,整个事务进行期间对数据的独占,将导致对热点数据依赖的业务系统并发性能衰退明显。 因此,在高并发的性能至上场景中,基于XA协议两阶段提交类型的分布式事务并不是最佳选择。
+
+#### 柔性事务
+
+如果将实现了ACID的事务要素的事务称为刚性事务的话,那么基于BASE事务要素的事务则称为柔性事务。 BASE是基本可用、柔性状态和最终一致性这3个要素的缩写。
+
+- 基本可用(Basically Available)保证分布式事务参与方不一定同时在线。
+
+- 柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉。
+
+- 最终一致性(Eventually consistent)通常是通过消息传递的方式保证系统的最终一致性。
+
+在ACID事务中对一致性和隔离性的要求很高,在事务执行过程中,必须将所有的资源占用。 柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性和隔离性的要求,只要求当整个事务最终结束的时候,数据是一致的。而在事务执行期间,任何读取操作得到的数据都有可能被改变。这种弱一致性的设计可以用来换取系统吞吐量的提升。
+
+Saga是典型的柔性事务管理器。Sagas这个概念来源于三十多年前的一篇数据库论文[http://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf] ,一个Saga事务是一个有多个短时事务组成的长时的事务。 在分布式事务场景下,我们把一个Saga分布式事务看做是一个由多个本地事务组成的事务,每个本地事务都有一个与之对应的补偿事务。在Saga事务的执行过程中,如果某一步执行出现异常,Saga事务会被终止,同时会调用对应的补偿事务完成相关的恢复操作,这样保证Saga相关的本地事务要么都是执行成功,要么通过补偿恢复成为事务执行之前的状态。
+
+TCC(Try-Cancel/Confirm实现)是另一种柔性事务的协调实现。TCC借助两阶段提交协议提供了一种比较完美的恢复方式。在TCC方式下,cancel补偿显然是在第二阶段需要执行业务逻辑来取消第一阶段产生的后果。Try是在第一阶段执行相关的业务操作,完成相关业务资源的占用,例如预先分配票务资源,或者检查并刷新用户账户信用额度。 在取消阶段释放相关的业务资源,例如释放预先分配的票务资源或者恢复之前占用的用户信用额度。 那我们为什么还要加入确认操作呢?这需要从业务资源的使用生命周期来入手。在try过程中,我们只是占用的业务资源,相关的执行操作只是出于待定状态,只有在确认操作执行完毕之后,业务资源才能真正被确认。
+
+基于ACID的强一致性事务和基于BASE的最终一致性事务都不是银弹,只有在最适合的场景中才能发挥它们的最大长处。可通过下表详细对比它们之间的区别,以帮助开发者进行技术选型。
+
+<center>
+
+|  对比 |本地事务|两阶段提交|柔性事务|
+| :--------:   | :-----:  | :----:  | :----:  |
+| 业务改造  |无|无|实现相关接口|
+|  一致性 |不支持|支持|最终一致|
+| 隔离性  |不支持|支持|业务方保证|
+| 并发性能  |无影响|严重衰退|略微衰退|
+| 适合场景  |业务方处理不一致|短事务 & 低并发|长事务 & 高并发|
+
+</center>
+
+#### 挑战
+
+由于应用的场景不同,需要开发者能够合理的在性能与功能之间权衡各种分布式事务。
+
+两阶段提交与柔性事务的API和功能并不完全相同,在它们之间并不能做到自由的透明切换。在开发决策阶段,就不得不在两阶段提交的事务和柔性事务之间抉择,使得设计和开发成本被大幅增加。
+
+基于XA的两阶段提交事务使用相对简单,但是无法很好的应对互联网的高并发或复杂系统的长事务场景;柔性事务则需要开发者对应用进行改造,接入成本非常高,并且需要开发者自行实现资源占用和反向补偿。
+
+### ShardingSphere的分布式事务
+
+整合现有的成熟事务方案,为本地事务、两阶段提交和柔性事务提供统一的分布式事务接口,并弥补当前方案的不足,提供一站式的分布式事务解决方案是Apache ShardingSphere(Incubating)分布式事务模块的主要设计目标。该模块的名称是sharding-transaction。可以用刚柔并济、自动化和透明化这3个关键词来概括sharding-transaction模块的设计理念和功能呈现。
+
+1.刚柔并济
+
+同时提供基于XA的两阶段提交事务与基于Saga的柔性事务解决方案,并且能够一起配合使用。
+
+2.自动化
+
+XA事务和Saga事务都通过自动化的方式完成,使用方无感知。XA事务无需使用XADataSource接口以及JTA事务管理器;Saga事务也无需用户自行实现补偿接口。
+
+3.透明化
+
+在Apache ShardingSphere(Incubating)的两个接入端——Sharding-JDBC和Sharding-Proxy中,分别提供了面向本地事务接口的封装。使用方完全可以将被ShardingSphere管理的水平分片的多个数据源当成一个数据库使用,通过本地事务API即可实现完全的分布式事务的能力。用户可以透明地在应用中任意切换事务类型。
+
+sharding-transaction模块由sharding-transaction-core,sharding-transaction-2pc和sharding-transaction-base这3个子模块组成。
+
+- sharding-transaction-core:
+
+提供了面向使用者的API与面向开发者的SPI。
+
+- sharding-transaction-2pc:
+
+两阶段提交事务父模块。目前只有sharding-transaction-xa模块,提供了XA协议的支持。未来会引入更多的基于两阶段提交的事务类型,如:percolator,参见:
+
+[https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36726.pdf]。
+
+- sharding-transaction-base:
+
+柔性事务父模块。目前只有sharding-transaction-saga模块,采用Apache ServiceComb Saga Actuator提供的Saga执行器提供柔性事务支持,并在其基础之上提供了反向SQL和快照的能力,并由此实现自动逆向补偿功能。
+
+下面将对ShardingSphere的XA和Saga事务模块的功能亮点进行说明。
+
+#### XA事务——三大XA事务管理器共护航
+
+成熟的XA事务管理器非常多,Apache ShardingSphere(Incubating)并未选择重新造轮子,而是寄望于打造一个生态,将合适的轮子有机地整合在一起,提供成熟稳定的分布式事务处理能力。它的主要功能如下:
+
+**1.复用成熟引擎,自动切换底层实现**
+
+Sharding-transaction-xa模块进一步定义了面向XA事务管理器开发者的SPI,开发者仅需实现SPI定义的接口,即可自动加入至Apache ShardingSphere(Incubating)生态,作为其XA事务管理器。
+
+Apache ShardingSphere(Incubating)官方目前实现了基于Atomikos和Bitronix的SPI,并且邀请了Radhat JBoss的XA事务引擎Narayana [https://github.com/jbosstm/narayana] 开发团队实现了JBoss的SPI。用户可以自行的在Atomikos,Bitronix和Narayana间选择自己喜欢的XA事务管理器。
+
+
+
+受限于Apache基金会项目License的原因,Apache ShardingSphere(Incubating)将采用Apache协议的Atomikos作为其默认实现,关于基于LGPL协议的Bitronix和基于LGPL协议的Narayana,用户可以自行引用相应jar包至项目的classpath即可。
+
+
+
+如果这3个XA事务管理器仍未满足用户需求,开发者则可通过扩展SPI来实现定制化的XA事务管理器。
+
+
+
+**2.数据源透明化自动接入**
+
+
+
+Apache ShardingSphere(Incubating)能够自动将XADataSource作为数据库驱动的数据源接入XA事务管理器。而针对于使用DataSource作为数据库驱动的应用,用户也无需改变其编码以及配置,Apache ShardingSphere(Incubating)通过自动适配的方式,在中间件内部将其转化为支持XA协议的XADataSource和XAConnection,并将其作为XA资源注册到底层的XA事务管理器中。
+
+
+
+XA模块的架构图如下:
+
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/solution1.jpg)
+
+#### Saga事务—跨越柔性事务限制,实现自动补偿
+
+在柔性事务中,每一次对数据库的更新操作都将数据真正的提交至数据库,以达到高并发系统中最佳资源释放的效果。当数据出现问题需要回滚时,通过柔性事务管理器保持数据的最终一致性以及隔离行为。Apache ShardingSphere(Incubating)采用Apache ServiceComb Saga Actuator [https://github.com/apache/servicecomb-saga-actuator] 作为Saga事务管理器,它的主要功能如下:
+
+
+
+**1. 自动反向补偿**
+
+
+
+Saga定义了一个事务中的每个子事务都有一个与之对应的反向补偿操作。由Saga事务管理器根据程序执行结果生成一张有向无环图,并在需要执行回滚操作时,根据该图依次按照相反的顺序调用反向补偿操作。Saga事务管理器只用于控制何时重试,合适补偿,并不负责补偿的内容,补偿的具体操作需要由开发者自行提供。
+
+
+
+另一个柔性事务管理器TCC与Saga理念相似,均需要由使用方开发者提供补偿操作。除了补偿,TCC还提供了资源占用的能力,但也需要由使用方开发者提供资源占用操作。虽然功能上强于Saga,但TCC的使用成本较之Saga也更高。
+
+
+
+由使用方开发者提供资源占用和补偿操作,这就使得柔性事务的解决方案始终难于大规模的在业务系统中落地。并且由于业务系统的介入,使得柔性事务框架的使用范畴始终定位于服务而非数据库,数据库能够直接使用的成熟的柔性事务管理器目前还不多见。
+
+
+
+Apache ShardingSphere(Incubating)采用反向SQL技术,将对数据库进行更新操作的SQL自动生成数据快照以及反向SQL,并交由Apache ServiceComb Saga Actuator执行,使用方则无需再关注如何实现补偿方法,将柔性事务管理器的应用范畴成功的定位回了事务的本源——数据库层面。
+
+
+
+对于能够处理复杂查询语句的Apache ShardingSphere(Incubating)SQL解析引擎来说,插入/更新/删除等语句解析难度则要小很多;ShardingSphere是通过拦截用户执行的SQL进行数据分片的,所有的SQL都能够被其直接管控。因此将反向SQL和补偿能力与Apache ServiceComb Saga Actuator相结合,达到了自动化柔性事务的能力,是数据分片和柔性事务结合的典范。
+
+
+
+Saga模块的架构图如下:
+
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/solution2.jpg)
+
+#### 接入端—面向原生事务接口的分布式事务
+
+Apache ShardingSphere(Incubating)的目标是像使用一个数据库一样使用分片后的多数据库,在事务模块,这个目标依然适用。无论被ShardingSphere所管理的数据库如何分片,面向开发者的逻辑数据库始终只有一个。因此,ShardingSphere的事务接口依然是原生的本地事务接口,即JDBC的java.sql.Connection的setAutoCommit, commit和rollback方法;以及面向数据库事务管理器的begin, commit和rollback语句。在用户调用原生本地事务接口的同时,ShardingSphere则通过sharding-transaction模块保证后端分片数据库的分布式事务。
+
+
+
+由于原生的事务接口并不支持事务类型,因此ShardingSphere提供了3种方式供使用者切换事务类型。
+
+
+
+1.通过SCTL(sharding-ctl,即ShardingSphere提供的数据库管理命令)切换当前事务类型。以SQL执行的方式输入即可,适用于Sharding-JDBC和Sharding-Proxy。例如:SCTL:SET TRANSACTION_TYPE=BASE
+
+2.通过Threadlocal切换当前事务类型,适用于Sharding-JDBC。例如:TransactionTypeHolder.set (TransactionType.XA)
+
+3.通过元注解,并与Spring配合使用切换当前事务类型,适用于Sharding-JDBC和Sharding-Proxy。例如:@ShardingTransactionType (TransactionType.BASE)
+
+### 线路规划
+
+分布式事务模块在github的开发分支 [https://github.com/apache/incubator-shardingsphere] 已经基本可用,将随着4.0.0.M1的版本发布,这也将是ShardingSphere进入Apache基金会孵化器之后的第一个发布版本。分布式事务是数据分片以及微服务架构的重要组成部分,也是Apache ShardingSphere(Incubating)的关注重心,发布之后仍将继续完善,线路规划如下。
+
+#### 事务隔离引擎
+
+在SQL反向引擎稳定之后,柔性事务的重点将放在打造事务隔离之上。由于事务的隔离性并非Saga所规划的范畴,因此Apache ShardingSphere(Incubating)会在Saga之外将其完善,与SQL反向引擎一起作为整个柔性事务的组成部分。
+
+
+
+Apache ShardingSphere(Incubating)将通过乐观锁、悲观锁、无隔离等几种策略,做到读已提交、读未提交、可重复读以及序列化等隔离级别的一一支持。并通过多版本快照进一步提升系统的并发度。
+
+#### 对外XA事务接口
+
+Apache ShardingSphere(Incubating)的两个接入端Sharding-JDBC和Sharding-Proxy在支持自身的内部事务问题之后,将提供融入与其他数据源一起作为被JTA等分布式事务管理器管理的能力。
+
+
+
+实现对外XA事务接口之后,Sharding-JDBC的DataSource将实现XADataSource接口,提供与其他数据源共同加入到一个XA事务的可能;Sharding-Proxy的数据库协议也将实现基于XA的两阶段提交协议;使其可以成为被XA所加载的资源管理器。
+
+
+
+除此之外,ShardingSphere还会实现XA协议的recovery部分,即在事务处理器出现崩溃的情况时,可以有能力提供in-doubt transactions来实现事务恢复。
+
+
+### 总结
+
+Apache ShardingSphere(Incubating)提供的分布式事务能力可以通过下表总结一下,读者不妨与文章开始时的表格对比一下,看看ShardingSphere的分布式事务模块所带来的变化。
+
+ 
+![](https://github.com/apache/shardingsphere/tree/master/docs/blog/static/img/solution3.jpg)
+
+在高速发展的Apache ShardingSphere(Incubating)中,分布式事务的雏形已成,我们会尽快将其打造为可用的产品,并持续为社区提供优质解决方案。对于一篇不算短的文章,阅读完此文的您,相信一定对这个领域有一定兴趣。不妨先尝试一下,是否满足您的预期?或者干脆加入我们的社区,一起打造更完善的分布式事务方案。 
diff --git a/docs/blog/content/material/solution.en.md b/docs/blog/content/material/solution.en.md
new file mode 100644
index 0000000..1b3e548
--- /dev/null
+++ b/docs/blog/content/material/solution.en.md
@@ -0,0 +1,7 @@
++++
+title = "Solution to distributed transaction"
+weight = 2
+chapter = true
++++
+
+## TODO