This is an automated email from the ASF dual-hosted git repository.
jimin pushed a commit to branch docusaurus
in repository https://gitbox.apache.org/repos/asf/incubator-seata-website.git
The following commit(s) were added to refs/heads/docusaurus by this push:
new 63ff5609b5 update: translate the blog to english (#832)
63ff5609b5 is described below
commit 63ff5609b5dfb885d76953b12547dea76e39aa94
Author: 云清 <[email protected]>
AuthorDate: Thu Feb 15 20:13:39 2024 +0800
update: translate the blog to english (#832)
---
.../en/docusaurus-plugin-content-blog/iscas2023.md | 67 +++++
.../docusaurus-plugin-content-blog/seata-1.6.0.md | 148 ++++++++++
.../seata-analysis-config-modular.md | 105 +++++++
.../seata-analysis-core-modular.md | 112 +++++++
.../seata-analysis-dubbo-transmit-xid.md | 140 +++++++++
.../seata-analysis-go-server.md | 76 +++++
.../seata-analysis-java-server.md | 322 +++++++++++++++++++++
.../seata-analysis-tcc-modular.md | 251 ++++++++++++++++
.../seata-at-lock.md | 178 ++++++++++++
.../seata-meetup-hangzhou.md | 51 ++++
10 files changed, 1450 insertions(+)
diff --git a/i18n/en/docusaurus-plugin-content-blog/iscas2023.md
b/i18n/en/docusaurus-plugin-content-blog/iscas2023.md
index c37ff78b50..54aa247f12 100644
--- a/i18n/en/docusaurus-plugin-content-blog/iscas2023.md
+++ b/i18n/en/docusaurus-plugin-content-blog/iscas2023.md
@@ -4,3 +4,70 @@ author: Seata Community
date: 2023/05/12
keywords: [open source summer, seata, distributed transaction]
---
+# 6 Major Topics Now Open for Selection | Welcome to Register for Seata Open
Source Summer
+
+### Welcome everyone to register for Seata Open Source Summer 2023 topics
+The registration period for Open Source Summer 2023 runs from **April 29th to
June 4th**, and we welcome registration for Seata 2023 topics! Here, you will
have the opportunity to delve into the theory and application of distributed
transactions, and collaborate with students from different backgrounds to
complete practical projects. We look forward to your active participation and
contribution, jointly promoting the development of the distributed transaction
field.
+
+
+
+### Seata Open Source Summer 2023
+Open Source Summer is a summer open source activity initiated and long-term
supported by the Institute of Software, Chinese Academy of Sciences, as part of
the "Open Source Software Supply Chain Lighting Program", aimed at encouraging
students to actively participate in the development and maintenance of open
source software, cultivating and discovering more outstanding developers,
promoting the vigorous development of excellent open source software
communities, and assisting in the cons [...]
+
+Participating students will collaborate remotely online with senior mentors to
participate in the development of various organizational projects in the open
source community and receive bonuses, gifts, and certificates. **These gains
are not only a highlight on future graduation resumes but also a brilliant
starting point towards becoming top developers.** Each project is divided into
two difficulty levels: basic and advanced, with corresponding project
completion bonuses of RMB 8,000 an [...]
+
+### Introduction to the Seata Community
+**Seata** is an open-source distributed transaction solution, with over 23K+
stars on GitHub, dedicated to providing high-performance and easy-to-use
distributed transaction services under the microservices architecture. Before
being open-sourced, Seata played a role as a middleware for distributed data
consistency within Alibaba, where almost every transaction needed to use Seata.
After undergoing the baptism of Double 11's massive traffic, it provided strong
technical support for business.
+
+### Summary of Seata Community Open Source Summer 2023 Project Topics
+The Seata community recommends 6 selected project topics for the Open Source
Summer 2023 organizing committee. You can visit the following link to make your
selection:
+https://summer-ospp.ac.cn/org/orgdetail/064c15df-705c-483a-8fc8-02831370db14?lang=zh
+Please communicate promptly with the respective mentors and prepare project
application materials, and register through the official channels (the
following topics are not listed in any particular order):
+
+
+
+#### Project One: Implementation of NamingServer for Service Discovery and
Registration
+
+**Difficulty:** Advanced
+
+**Project Community Mentor:** Chen Jianbin
+
+**Mentor's Contact Email:** [email protected]
+
+**Project Description:**
+Currently, Seata's service exposure and discovery mainly rely on third-party
registration centers. With the evolution and development of the project, it
brings additional learning and usage costs. Most mainstream middleware with
servers have begun to evolve their own service self-loop and control and
provide components or functions with higher compatibility and reliability to
the server, such as Kafka's KRaft, RocketMQ's NameServer, ClickHouse's
ClickHouse Keeper, etc. To address the abo [...]
+
+**Project Link:**
+https://summer-ospp.ac.cn/org/prodetail/230640380?list=org&navpage=org
+
+...
+
+(Projects Two to Six translated in the same manner)
+
+...
+
+### How to Participate in Seata Open Source Summer 2023 and Quickly Select a
Project?
+**Welcome to communicate with each mentor through the above contact
information and prepare project application materials.**
+
+During the project participation period, students can work online from
anywhere in the world. The completion of Seata-related projects needs to be
submitted to the Seata community repository as a PR by **September 30th**, so
please prepare early.
+
+
+
+**To obtain information about mentors and other information during the
project, you can scan the QR code below to enter the DingTalk group for
communication** —— Understand various projects in the Seata community, meet
Seata community open source mentors, and help with subsequent applications.
+
+
+
+#### Reference Materials:
+**Seata Website:** https://seata.apache.org/
+
+**Seata GitHub:** https://github.com/seata
+
+**Open Source Summer Official Website:**
https://summer-ospp.ac.cn/org/orgdetail/ab188e59-fab8-468f-bc89-bdc2bd8b5e64?lang=zh
+
+If students are interested in other areas of microservices projects, they can
also try to apply, such as:
+
+- For students interested in **microservice configuration registration
centers**, they can try to apply for [Nacos Open Source
Summer](https://nacos.io/zh-cn/blog/iscas2023.html);
+- For students interested in **microservice frameworks and RPC frameworks**,
they can try to apply for [Spring Cloud Alibaba Open Source
Summer](https://summer-ospp.ac.cn/org/orgdetail/41d68399-ed48-4d6d-9d4d-3ff4128dc132?lang=zh)
and [Dubbo Open Source
Summer](https://summer-ospp.ac.cn/org/orgdetail/a7f6e2ad-4acc-47f8-9471-4e54b9a166a6?lang=zh);
+- For students interested in **cloud-native gateways**, they can try to apply
for [Higress Open Source Summer](https://higress.io/zh-cn/blog/ospp-2023);
+- For students interested in **distributed high-availability protection**,
they can try to apply for [Sentinel Open Source Summer](https://summer-ospp.ac.
cn/org/orgdetail/5e879522-bd90-4a8b-bf8b-b11aea48626b?lang=zh);
+- For students interested in **microservices governance**, they can try to
apply for [OpenSergo Open Source Summer](https://summer-ospp.ac.
cn/org/orgdetail/aaff4eec-11b1-4375-997d-5eea8f51762b?lang=zh).
diff --git a/i18n/en/docusaurus-plugin-content-blog/seata-1.6.0.md
b/i18n/en/docusaurus-plugin-content-blog/seata-1.6.0.md
index b9c98eea1f..a3ce1d460e 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-1.6.0.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-1.6.0.md
@@ -5,3 +5,151 @@ keywords: [seata, distributed transaction, 1.6.0]
description: Seata 1.6.0 Released with Significant Performance Improvement
date: 2022/12/17
---
+### Seata 1.6.0 Released with Significant Performance Improvement
+
+Seata is an open-source distributed transaction solution that provides high
performance and easy-to-use distributed transaction services.
+
+**Download Links for seata-server:**
+
+[source](https://github.com/apache/incubator-seata/archive/v1.6.0.zip) |
+[binary](https://github.com/apache/incubator-seata/releases/download/v1.6.0/seata-server-1.6.0.zip)
+
+Updates in this version:
+
+### feature:
+- [[#4863](https://github.com/apache/incubator-seata/pull/4863)] Support for
multiple primary keys in Oracle and PostgreSQL
+- [[#4649](https://github.com/apache/incubator-seata/pull/4649)] Support for
multiple registry centers in seata-server
+- [[#4779](https://github.com/apache/incubator-seata/pull/4779)] Support for
Apache Dubbo3
+- [[#4479](https://github.com/apache/incubator-seata/pull/4479)] TCC
annotations can now be added to interfaces and implementation classes
+- [[#4877](https://github.com/apache/incubator-seata/pull/4877)] Client SDK
supports JDK17
+- [[#4914](https://github.com/apache/incubator-seata/pull/4914)] Support for
update join syntax for MySQL
+- [[#4542](https://github.com/apache/incubator-seata/pull/4542)] Support for
Oracle timestamp type
+- [[#5111](https://github.com/apache/incubator-seata/pull/5111)] Support for
Nacos contextPath configuration
+- [[#4802](https://github.com/apache/incubator-seata/pull/4802)] Dockerfile
supports arm64
+
+### Bug Fixes:
+- [[#4780](https://github.com/apache/incubator-seata/pull/4780)] Fixed the
issue where TimeoutRollbacked event wasn't sent after a successful timeout
rollback.
+- [[#4954](https://github.com/apache/incubator-seata/pull/4954)] Fixed
NullPointerException when the output expression was incorrect.
+- [[#4817](https://github.com/apache/incubator-seata/pull/4817)] Fixed the
problem with non-standard configuration in higher versions of Spring Boot.
+- [[#4838](https://github.com/apache/incubator-seata/pull/4838)] Fixed the
issue where undo log wasn't generated when using Statement.executeBatch().
+- [[#4533](https://github.com/apache/incubator-seata/pull/4533)] Fixed
inaccurate metric data caused by duplicate events handling for
handleRetryRollbacking.
+- [[#4912](https://github.com/apache/incubator-seata/pull/4912)] Fixed the
issue where mysql InsertOnDuplicateUpdate couldn't correctly match column names
due to inconsistent case.
+- [[#4543](https://github.com/apache/incubator-seata/pull/4543)] Fixed support
for Oracle nclob data type.
+- [[#4915](https://github.com/apache/incubator-seata/pull/4915)] Fixed the
problem of not obtaining ServerRecoveryProperties attributes.
+- [[#4919](https://github.com/apache/incubator-seata/pull/4919)] Fixed the
issue where XID's port and address appeared as null:0.
+- [[#4928](https://github.com/apache/incubator-seata/pull/4928)] Fixed NPE
issue in rpcContext.getClientRMHolderMap.
+- [[#4953](https://github.com/apache/incubator-seata/pull/4953)] Fixed the
issue where InsertOnDuplicateUpdate could bypass primary key modification.
+- [[#4978](https://github.com/apache/incubator-seata/pull/4978)] Fixed kryo
support for cyclic dependencies.
+- [[#4985](https://github.com/apache/incubator-seata/pull/4985)] Fixed the
issue of duplicate undo_log id.
+- [[#4874](https://github.com/apache/incubator-seata/pull/4874)] Fixed startup
failure with OpenJDK 11.
+- [[#5018](https://github.com/apache/incubator-seata/pull/5018)] Fixed server
startup failure issue due to loader path using relative path in startup script.
+- [[#5004](https://github.com/apache/incubator-seata/pull/5004)] Fixed the
issue of duplicate row data in mysql update join.
+- [[#5032](https://github.com/apache/incubator-seata/pull/5032)] Fixed the
abnormal SQL statement in mysql InsertOnDuplicateUpdate due to incorrect
calculation of condition parameter fill position.
+- [[#5033](https://github.com/apache/incubator-seata/pull/5033)] Fixed
NullPointerException issue in SQL statement of InsertOnDuplicateUpdate due to
missing insert column field.
+- [[#5038](https://github.com/apache/incubator-seata/pull/5038)] Fixed
SagaAsyncThreadPoolProperties conflict issue.
+- [[#5050](https://github.com/apache/incubator-seata/pull/5050)] Fixed the
issue where global status under Saga mode wasn't correctly changed to Committed.
+- [[#5052](https://github.com/apache/incubator-seata/pull/5052)] Fixed
placeholder parameter issue in update join condition.
+- [[#5031](https://github.com/apache/incubator-seata/pull/5031)] Fixed the
issue of using null value index as query condition in InsertOnDuplicateUpdate.
+- [[#5075](https://github.com/apache/incubator-seata/pull/5075)] Fixed the
inability to intercept SQL statements with no primary key and unique index in
InsertOnDuplicateUpdate.
+- [[#5093](https://github.com/apache/incubator-seata/pull/5093)] Fixed
accessKey loss issue after seata server restart.
+- [[#5092](https://github.com/apache/incubator-seata/pull/5092)] Fixed the
issue of incorrect AutoConfiguration order when seata and jpa are used together.
+- [[#5109](https://github.com/apache/incubator-seata/pull/5109)] Fixed NPE
issue when @GlobalTransactional is not applied on RM side.
+- [[#5098](https://github.com/apache/incubator-seata/pull/5098)] Disabled
oracle implicit cache for Druid.
+- [[#4860](https://github.com/apache/incubator-seata/pull/4860)] Fixed metrics
tag override issue.
+- [[#5028](https://github.com/apache/incubator-seata/pull/5028)] Fixed null
value issue in insert on duplicate SQL.
+- [[#5078](https://github.com/apache/incubator-seata/pull/5078)] Fixed
interception issue for SQL statements without primary keys and unique keys.
+- [[#5097](https://github.com/apache/incubator-seata/pull/5097)] Fixed
accessKey loss issue when Server restarts.
+- [[#5131](https://github.com/apache/incubator-seata/pull/5131)] Fixed issue
where XAConn cannot rollback when in active state.
+- [[#5134](https://github.com/apache/incubator-seata/pull/5134)] Fixed issue
where hikariDataSource auto proxy fails in some cases.
+- [[#5163](https://github.com/apache/incubator-seata/pull/5163)] Fixed
compilation failure in higher versions of JDK.
+
+### Optimization:
+- [[#4681](https://github.com/apache/incubator-seata/pull/4681)] Optimized the
process of competing locks.
+- [[#4774](https://github.com/apache/incubator-seata/pull/4774)] Optimized
mysql8 dependency in seataio/seata-server image.
+- [[#4750](https://github.com/apache/incubator-seata/pull/4750)] Optimized the
release of global locks in AT branch to not use xid.
+- [[#4790](https://github.com/apache/incubator-seata/pull/4790)] Added
automatic OSSRH github action publishing.
+- [[#4765](https://github.com/apache/incubator-seata/pull/4765)] XA mode in
mysql8.0.29 and above no longer holds connection to the second phase.
+- [[#4797](https://github.com/apache/incubator-seata/pull/4797)] Optimized all
github actions scripts.
+- [[#4800](https://github.com/apache/incubator-seata/pull/4800)] Added NOTICE
file.
+- [[#4761](https://github.com/apache/incubator-seata/pull/4761)] Used hget
instead of hmget in RedisLocker.
+- [[#4414](https://github.com/apache/incubator-seata/pull/4414)] Removed log4j
dependency.
+- [[#4836](https://github.com/apache/incubator-seata/pull/4836)] Improved
readability of BaseTransactionalExecutor#buildLockKey(TableRecords
rowsIncludingPK) method.
+- [[#4865](https://github.com/apache/incubator-seata/pull/4865)] Fixed
security vulnerabilities in Saga visualization designer GGEditor.
+- [[#4590](https://github.com/apache/incubator-seata/pull/4590)] Dynamic
configuration support for automatic degradation switch.
+- [[#4490](https://github.com/apache/incubator-seata/pull/4490)] Optimized
tccfence record table to delete by index.
+- [[#4911](https://github.com/apache/incubator-seata/pull/4911)] Added header
and license checks.
+- [[#4917](https://github.com/apache/incubator-seata/pull/4917)] Upgraded
package-lock.json to fix vulnerabilities.
+- [[#4924](https://github.com/apache/incubator-seata/pull/4924)] Optimized pom
dependencies.
+- [[#4932](https://github.com/apache/incubator-seata/pull/4932)] Extracted
default values for some configurations.
+- [[#4925](https://github.com/apache/incubator-seata/pull/4925)] Optimized
javadoc comments.
+- [[#4921](https://github.com/apache/incubator-seata/pull/4921)] Fixed
security vulnerabilities in console module and upgraded skywalking-eyes version.
+- [[#4936](https://github.com/apache/incubator-seata/pull/4936)] Optimized
storage configuration reading.
+- [[#4946](https://github.com/apache/incubator-seata/pull/4946)] Passed SQL
exceptions encountered when acquiring locks to the client.
+- [[#4962](https://github.com/apache/incubator-seata/pull/4962)] Optimized
build configuration and corrected base image of docker image.
+- [[#4974](https://github.com/apache/incubator-seata/pull/4974)] Removed
limitation on querying globalStatus quantity under redis mode.
+- [[#4981](https://github.com/apache/incubator-seata/pull/4981)] Improved
error message when tcc fence record cannot be found.
+- [[#4995](https://github.com/apache/incubator-seata/pull/4995)] Fixed
duplicate primary key query conditions in the SQL statement after mysql
InsertOnDuplicateUpdate.
+- [[#5047](https://github.com/apache/incubator-seata/pull/5047)] Removed
unused code.
+- [[#5051](https://github.com/apache/incubator-seata/pull/5051)] When undolog
generates dirty write during rollback, throw exception
BranchRollbackFailed_Unretriable.
+- [[#5075](https://github.com/apache/incubator-seata/pull/5075)] Intercept
insert on duplicate update statements without primary keys and unique indexes.
+- [[#5104](https://github.com/apache/incubator-seata/pull/5104)]
ConnectionProxy is no longer dependent on druid.
+- [[#5124](https://github.com/apache/incubator-seata/pull/5124)] Support
deleting TCC fence record table for oracle.
+- [[#4468](https://github.com/apache/incubator-seata/pull/4968)] Support kryo
5.3.0.
+- [[#4807](https://github.com/apache/incubator-seata/pull/4807)] Optimized
image and OSS repository publishing pipelines.
+- [[#4445](https://github.com/apache/incubator-seata/pull/4445)] Optimized
transaction timeout judgment.
+- [[#4958](https://github.com/apache/incubator-seata/pull/4958)] Optimized
execution of triggerAfterCommit() for timeout transactions.
+- [[#4582](https://github.com/apache/incubator-seata/pull/4582)] Optimized
transaction sorting in redis storage mode.
+- [[#4963](https://github.com/apache/incubator-seata/pull/4963)] Added ARM64
pipeline CI testing.
+- [[#4434](https://github.com/apache/incubator-seata/pull/4434)] Removed
seata-server CMS GC parameters.
+
+### Testing:
+- [[#4411](https://github.com/apache/incubator-seata/pull/4411)] Tested Oracle
database AT mode type support.
+- [[#4794](https://github.com/apache/incubator-seata/pull/4794)] Refactored
code and attempted to fix unit test `DataSourceProxyTest.getResourceIdTest()`.
+- [[#5101](https://github.com/apache/incubator-seata/pull/5101)] Fixed
ClassNotFoundException issue in zk registration and configuration center
`DataSourceProxyTest.getResourceIdTest()`.
+
+Special thanks to the following contributors for their code contributions. If
there are any unintentional omissions, please report.
+
+<!-- 请确保您的 GitHub ID 在以下列表中 -->
+- [slievrly](https://github.com/slievrly)
+- [renliangyu857](https://github.com/renliangyu857)
+- [wangliang181230](https://github.com/wangliang181230)
+- [funky-eyes](https://github.com/funky-eyes)
+- [tuwenlin](https://github.com/tuwenlin)
+- [conghuhu](https://github.com/conghuhu)
+- [a1104321118](https://github.com/a1104321118)
+- [duanqiaoyanyu](https://github.com/duanqiaoyanyu)
+- [robynron](https://github.com/robynron)
+- [lcmvs](https://github.com/lcmvs)
+- [github-ganyu](https://github.com/github-ganyu)
+- [1181954449](https://github.com/1181954449)
+- [zw201913](https://github.com/zw201913)
+- [wingchi-leung](https://github.com/wingchi-leung)
+- [AlexStocks](https://github.com/AlexStocks)
+- [liujunlin5168](https://github.com/liujunlin5168)
+- [pengten](https://github.com/pengten)
+- [liuqiufeng](https://github.com/liuqiufeng)
+- [yujianfei1986](https://github.com/yujianfei1986)
+- [Bughue](https://github.com/Bughue)
+- [AlbumenJ](https://github.com/AlbumenJ)
+- [doubleDimple](https://github.com/doubleDimple)
+- [jsbxyyx](https://github.com/jsbxyyx)
+- [tuwenlin](https://github.com/tuwenlin)
+- [CrazyLionLi](https://github.com/JavaLionLi)
+- [whxxxxx](https://github.com/whxxxxx)
+- [neillee95](https://github.com/neillee95)
+- [crazy-sheep](https://github.com/crazy-sheep)
+- [zhangzq7](https://github.com/zhangzq7)
+- [l81893521](https://github.com/l81893521)
+- [zhuyoufeng](https://github.com/zhuyoufeng)
+- [xingfudeshi](https://github.com/xingfudeshi)
+- [odidev](https://github.com/odidev)
+- [miaoxueyu](https://github.com/miaoxueyu)
+
+At the same time, we have received many valuable issues and suggestions from
the community, and we are very grateful to everyone.
+
+#### Link
+
+- **Seata:** https://github.com/apache/incubator-seata
+- **Seata-Samples:** https://github.com/apache/incubator-seata-samples
+- **Release:** https://github.com/apache/incubator-seata/releases
+- **WebSite:** https://seata.apache.org
diff --git
a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-config-modular.md
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-config-modular.md
index dba86841be..c171c51b55 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-config-modular.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-config-modular.md
@@ -4,3 +4,108 @@ author: runze.zhao
keywords: [Seata, distributed transaction]
date: 2020/1/11
---
+## 1. Introduction
+According to the classification defined by
[experts](https://www.iteye.com/blog/javatar-949527), configurations can be
categorized into three types: environment configuration, descriptive
configuration, and extension configuration.
+
+- Environment configuration: Typically consists of discrete simple values like
parameters for component startup, often in key-value pair format.
+- Descriptive configuration: Pertains to business logic, such as transaction
initiators and participants, and is usually embedded within the lifecycle
management of the business. Descriptive configuration contains more
information, sometimes with hierarchical relationships.
+- Extension configuration: Products need to discover third-party
implementations, requiring high aggregation of configurations. Examples include
various configuration centers and registration centers. The common practice is
to place the fully qualified class name files under the META-INF/services
directory of the JAR file, with each line representing an implementation class
name.
+
+## 2. Environment Configuration
+
+When the Seata server is loaded, it uses `resources/registry.conf` to
determine the types of configuration centers and registration centers. Starting
from version 1.0, Seata client not only loads configurations using the `conf`
file but also allows configuration through YAML files in Spring Boot using
`seata.config.{type}` for choosing the configuration center, similar to
selecting the registration center. The source code for loading configurations
via YAML is located in the `io.seata.sp [...]
+
+If the user of the Seata client places both a `conf` configuration file under
`resources` and configures via YAML files, the configuration in the YAML file
will take precedence. Code example:
+
+
+```java
+CURRENT_FILE_INSTANCE = null == extConfiguration ? configuration :
extConfiguration;
+```
+
+Here, `extConfiguration` is an instance of external configuration provided by
the `ExtConfigurationProvider#provide()` external configuration provider class,
while `configuration` is provided by another configuration provider class,
`ConfigurationProvider#provide()`. These two configuration provider classes are
loaded through SPI in the static block of the `ConfigurationFactory` in the
config module.
+
+
+```java
+EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration);
+```
+
+The selection of configuration center types discussed above is related to
determining the configuration environment. Once the type of configuration
center to be used is determined, the environment configuration is loaded
through the corresponding configuration center. File-based configuration,
represented by `File`, is also considered a type of configuration center.
+
+Both the client and server obtain configuration parameters by using
`ConfigurationFactory#getInstance()` to get an instance of the configuration
class, and then retrieve configuration parameters using the instance. The
constants defining configuration keys are mainly found in the `config` file
under the `core` module.
+
+The meanings of some important environment configuration properties are
documented on the [official website](/docs/user/configurations/).
+
+During instantiation, the configuration parameters obtained through
`ConfigurationFactory` and injected into constructors require a restart to take
effect. However, parameters obtained in real-time using `ConfigurationFactory`
become effective immediately when the configuration changes.
+
+The `config` module provides the `ConfigurationChangeListener#onChangeEvent`
interface method to modify internal attributes of instances. In this method,
dynamic changes to properties are monitored, and if the properties used by the
instance are found to have changed from the initial injection, the attributes
stored in the instance are modified to align with the configuration center.
This enables dynamic configuration updates.
+
+
+```java
+public class GlobalTransactionalInterceptor implements
ConfigurationChangeListener {
+private volatile boolean disable =
ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,false);
+@Override public Object invoke(Param param) {
+ if(disable){//Transaction business processing}
+}
+@Override public void onChangeEvent(Param param) {
+ disable = param;
+}}
+```
+
+The code snippet above pertains to the pseudo-code related to the
`GlobalTransactionalInterceptor` and its degradation properties under the
Spring module. When the `GlobalTransactionalScanner` instantiates the
interceptor class mentioned above, it registers the interceptor into the list
of configuration change listeners. When a configuration change occurs, the
listener is invoked:
+
+
+```java
+ConfigurationFactory.getInstance().addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,(ConfigurationChangeListener)interceptor);
+```
+
+The term "degradation" refers to the scenario where a particular functionality
of a service becomes unavailable. By dynamically configuring properties, this
functionality can be turned off to avoid continuous attempts and failures. The
`interceptor#invoke()` method executes Seata transaction-related business only
when the `disable` attribute is set to true.
+
+## 3. Descriptive Configuration
+Descriptive configurations in general frameworks often contain abundant
information, sometimes with hierarchical relationships. XML configuration is
convenient for describing tree structures due to its strong descriptive
capabilities. However, the current trend advocates for eliminating cumbersome
prescriptive configurations in favor of using conventions.
+
+In Seata's AT (Automatic Transaction) mode, transaction processing is achieved
through proxying data sources, resulting in minimal intrusion on the business
logic. Simply identifying which business components need to enable global
transactions during Seata startup can be achieved using annotations, thus
facilitating descriptive configuration.
+
+
+```java
+@GlobalTransactional(timeoutMills = 300000, name = "busi-doBiz")
+public String doBiz(String msg) {}
+```
+If using the TCC (Try-Confirm-Cancel) mode, transaction participants also need
to annotate their involvement:
+
+
+```java
+@TwoPhaseBusinessAction(name = "tccActionForSpringTest" , commitMethod =
"commit", rollbackMethod = "rollback")
+public boolean prepare(BusinessActionContext actionContext, int i);
+public boolean commit(BusinessActionContext actionContext);
+public boolean rollback(BusinessActionContext actionContext);
+```
+
+## 4. Extension Configuration
+Extension configurations typically have high requirements for product
aggregation because products need to discover third-party implementations and
incorporate them into their internals.
+
+
+
+Here's an example of a custom configuration center provider class. Place a
text file with the same name as the interface under META-INF/services, and the
content of the file should be the implementation class of the interface. This
follows the standard SPI (Service Provider Interface) approach. Then, modify
the configuration file `registry.conf` to set `config.type=test`.
+
+However, if you think that by doing so, Seata can recognize it and replace the
configuration center, then you are mistaken. When Seata loads the configuration
center, it encapsulates the value of the configuration center type specified in
the configuration file using the enum `ConfigType`:
+
+
+```java
+private static Configuration buildConfiguration() {
+ configTypeName = "test";//The 'config.type' configured in 'registry.conf
+ configType = ConfigType.getType(configTypeName);//An exception will be
thrown if ConfigType cannot be retrieved.
+}
+```
+
+If a configuration center type like `test` is not defined in `ConfigType`, it
will throw an exception. Therefore, merely modifying the configuration file
without changing the source code will not enable the use of configuration
center provider classes other than those defined in `ConfigType`.
+
+Currently, in version 1.0, the configuration center types defined in
`ConfigType` include: File, ZK, Nacos, Apollo, Consul, Etcd3,
SpringCloudConfig, and Custom. If a user wishes to use a custom configuration
center type, they can use the `Custom` type.
+
+
+
+One inelegant approach here is to provide an implementation class with a
specified name `ZK` but with a higher priority level (order=3) than the default
`ZK` implementation (which has order=1). This will make `ConfigurationFactory`
use `TestConfigurationProvider` as the configuration center provider class.
+
+Through the above steps, Seata can be configured to use our own provided code.
Modules in Seata such as codec, compressor, discovery, integration, etc., all
use the SPI mechanism to load functional classes, adhering to the design
philosophy of microkernel + plug-in, treating third parties equally.
+
+## 5. Seata Source Code Analysis Series
+Author: Zhao Runze, [Series
Address](https://blog.csdn.net/qq_37804737/category_9530078.html).
diff --git
a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-core-modular.md
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-core-modular.md
index df85bd2af7..1b40daeaa7 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-core-modular.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-core-modular.md
@@ -4,3 +4,115 @@ author: runze.zhao
keywords: [Seata, distributed transaction]
date: 2019/12/23
---
+## 1. Introduction
+The core module defines the types and states of transactions, common
behaviors, protocols, and message models for communication between clients and
servers, as well as exception handling methods, compilation, compression types,
configuration information names, environment context, etc. It also encapsulates
RPC based on Netty for use by both clients and servers.
+
+Let's analyze the main functional classes of the core module according to the
package order:
+
+
+
+codec: Defines a codec factory class, which provides a method to find the
corresponding processing class based on the serialization type. It also
provides an interface class Codec with two abstract methods:
+
+```java
+<T> byte[] encode(T t);
+```
+
+```java
+<T> T decode(byte[] bytes);
+```
+## 1. codec Module
+In version 1.0, the codec module has three serialization implementations:
SEATA, PROTOBUF, and KRYO.
+
+compressor: Similar to classes under the codec package, there are three
classes here: a compression type class, a factory class, and an abstract class
for compression and decompression operations. In version 1.0, there is only one
compression method: Gzip.
+
+constants: Consists of two classes, ClientTableColumnsName and
ServerTableColumnsName, representing the models for transaction tables stored
on the client and server sides respectively. It also includes classes defining
supported database types and prefixes for configuration information attributes.
+
+context: The environment class RootContext holds a ThreadLocalContextCore to
store transaction identification information. For example, TX_XID uniquely
identifies a transaction, and TX_LOCK indicates the need for global lock
control for local transactions on update/delete/insert/selectForUpdate SQL
operations.
+
+event: Utilizes the Guava EventBus event bus for registration and
notification, implementing the listener pattern. In the server module's metrics
package, MetricsManager registers monitoring events for changes in
GlobalStatus, which represents several states of transaction processing in the
server module. When the server processes transactions, the callback methods
registered for monitoring events are invoked, primarily for statistical
purposes.
+
+lock: When the server receives a registerBranch message for branch
registration, it acquires a lock. In version 1.0, there are two lock
implementations: DataBaseLocker and MemoryLocker, representing database locks
and in-memory locks respectively. Database locks are acquired based on the
rowKey = resourceId + tableName + pk, while memory locks are based directly on
the primary key.
+
+model: BranchStatus, GlobalStatus, and BranchType are used to define
transaction types and global/branch states. Additionally, TransactionManager
and ResourceManager are abstract classes representing resource managers (RMs)
and transaction managers (TMs) respectively. Specific implementations of RMs
and TMs are not provided here due to variations in transaction types.
+
+protocol: Defines entity classes used for transmission in the RPC module,
representing models for requests and responses under different transaction
status scenarios.
+
+store: Defines data models for interacting with databases and the SQL
statements used for database interactions.
+
+
+```java
+ public void exceptionHandleTemplate(Callback callback,
AbstractTransactionRequest request,
+ AbstractTransactionResponse response) {
+ try {
+ callback.execute(request, response); //执行事务业务的方法
+ callback.onSuccess(request, response); //设置response返回码
+ } catch (TransactionException tex) {
+ LOGGER.error("Catch TransactionException while do RPC, request:
{}", request, tex);
+ callback.onTransactionException(request, response, tex);
//设置response返回码并设置msg
+ } catch (RuntimeException rex) {
+ LOGGER.error("Catch RuntimeException while do RPC, request: {}",
request, rex);
+ callback.onException(request, response, rex);
//设置response返回码并设置msg
+ }
+ }
+```
+## 2. Analysis of Exception Handling in the exception Package
+
+This is the UML diagram of AbstractExceptionHandler. Callback and
AbstractCallback are internal interfaces and classes of
AbstractExceptionHandler. AbstractCallback implements three methods of the
Callback interface but leaves the execute() method unimplemented.
AbstractExceptionHandler uses AbstractCallback as a parameter for the template
method and utilizes its implemented methods. However, the execute() method is
left to be implemented by subclasses.
+
+
+
+From an external perspective, AbstractExceptionHandler defines a template
method with exception handling. The template includes four behaviors, three of
which are already implemented, and the behavior execution is delegated to
subclasses.
+
+## 3. Analysis of the rpc Package
+
+When it comes to the encapsulation of RPC by Seata, one need not delve into
the details. However, it's worth studying how transaction business is handled.
+
+The client-side RPC class is AbstractRpcRemotingClient:
+
+
+
+The important attributes and methods are depicted in the class diagram. The
methods for message sending and initialization are not shown in the diagram.
Let's analyze the class diagram in detail:
+
+clientBootstrap: This is a wrapper class for the netty startup class
Bootstrap. It holds an instance of Bootstrap and customizes the properties as
desired.
+
+clientChannelManager: Manages the correspondence between server addresses and
channels using a ConcurrentHashMap<serverAddress,channel> container.
+
+clientMessageListener: Handles messages. Depending on the message type, there
are three specific processing methods.
+
+
+```java
+public void onMessage(RpcMessage request, String serverAddress,
ClientMessageSender sender) {
+ Object msg = request.getBody();
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("onMessage:" + msg);
+ }
+ if (msg instanceof BranchCommitRequest) {
+ handleBranchCommit(request, serverAddress,
(BranchCommitRequest)msg, sender);
+ } else if (msg instanceof BranchRollbackRequest) {
+ handleBranchRollback(request, serverAddress,
(BranchRollbackRequest)msg, sender);
+ } else if (msg instanceof UndoLogDeleteRequest) {
+ handleUndoLogDelete((UndoLogDeleteRequest)msg);
+ }
+ }
+```
+
+## 4. Analysis of the rpc Package (Continued)
+
+Within the message class, the TransactionMessageHandler is responsible for
handling messages of different types. Eventually, based on the different
transaction types (AT, TCC, SAGE), specific handling classes, as mentioned in
the second part, exceptionHandleTemplate(), are invoked.
+
+mergeSendExecutorService: This is a thread pool with only one thread
responsible for merging and sending messages from different addresses. In the
sendAsyncRequest() method, messages are offered to the queue
LinkedBlockingQueue of the thread pool. The thread is then responsible for
polling and processing messages.
+
+
+channelRead(): Handles server-side HeartbeatMessage.PONG heartbeat messages.
Additionally, it processes MergeResultMessage, which are response messages for
asynchronous messages. It retrieves the corresponding MessageFuture based on
the msgId and sets the result of the asynchronous message.
+
+dispatch(): Invokes the clientMessageListener to handle messages sent by the
server. Different types of requests have different handling classes.
+
+In summary, when looking at Netty, one should focus on serialization methods
and message handling handler classes. Seata's RPC serialization method is
processed by finding the Codec implementation class through the factory class,
and the handler is the TransactionMessageHandler mentioned earlier.
+
+## 5. Conclusion
+
+The core module covers a wide range of functionalities, with most classes
serving as abstract classes for other modules. Business models are abstracted
out, and specific implementations are distributed across different modules. The
code in the core module is of high quality, with many classic design patterns
such as the template pattern discussed earlier. It is very practical and
well-crafted, deserving careful study.
+
+## 6. Seata Source Code Analysis Series Links
+
+[Series Links](https://blog.csdn.net/qq_37804737/category_9530078.html)
diff --git
a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-dubbo-transmit-xid.md
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-dubbo-transmit-xid.md
index 55e4ebc9b6..60cc902e96 100644
---
a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-dubbo-transmit-xid.md
+++
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-dubbo-transmit-xid.md
@@ -5,3 +5,143 @@ description: This article explores the propagation of XID in
Seata-Dubbo through
author: FUNKYE
date: 2020/01/01
---
+# Seata-XID Transmission Source Code Analysis: Dubbo Edition
+
+Author: FUNKYE (Chen Jianbin), Principal Engineer at a certain Internet
company in Hangzhou.
+
+# Preface
+
+1. Let's start by examining the package structure. Under seata-dubbo and
seata-dubbo-alibaba, there is a common class named
TransactionPropagationFilter, corresponding to Apache Dubbo and Alibaba Dubbo
respectively.
+
+
+
+## Source Code Analysis
+```java
+package io.seata.integration.dubbo;
+
+import io.seata.core.context.RootContext;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, order = 100)
+public class TransactionPropagationFilter implements Filter {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(TransactionPropagationFilter.class);
+
+ @Override
+ public Result invoke(Invoker<?> invoker, Invocation invocation) throws
RpcException {
+ // get local XID
+ String xid = RootContext.getXID();
+ String xidInterceptorType = RootContext.getXIDInterceptorType();
+ // get XID from dubbo param
+ String rpcXid = getRpcXid();
+ String rpcXidInterceptorType =
RpcContext.getContext().getAttachment(RootContext.KEY_XID_INTERCEPTOR_TYPE);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("xid in RootContext[{}] xid in RpcContext[{}]", xid,
rpcXid);
+ }
+ boolean bind = false;
+ if (xid != null) {
+ //transfer xid
+ RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid);
+
RpcContext.getContext().setAttachment(RootContext.KEY_XID_INTERCEPTOR_TYPE,
xidInterceptorType);
+ } else {
+ if (rpcXid != null) {
+ //bind XID
+ RootContext.bind(rpcXid);
+ RootContext.bindInterceptorType(rpcXidInterceptorType);
+ bind = true;
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("bind[{}] interceptorType[{}] to
RootContext", rpcXid, rpcXidInterceptorType);
+ }
+ }
+ }
+ try {
+ return invoker.invoke(invocation);
+ } finally {
+ if (bind) {
+ //remove xid which has finished
+ String unbindInterceptorType =
RootContext.unbindInterceptorType();
+ String unbindXid = RootContext.unbind();
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("unbind[{}] interceptorType[{}] from
RootContext", unbindXid, unbindInterceptorType);
+ }
+ // if unbind xid is not current rpc xid
+ if (!rpcXid.equalsIgnoreCase(unbindXid)) {
+ LOGGER.warn("xid in change during RPC from {} to {},
xidInterceptorType from {} to {} ", rpcXid, unbindXid, rpcXidInterceptorType,
unbindInterceptorType);
+ if (unbindXid != null) {
+ // bind xid
+ RootContext.bind(unbindXid);
+ RootContext.bindInterceptorType(unbindInterceptorType);
+ LOGGER.warn("bind [{}] interceptorType[{}] back to
RootContext", unbindXid, unbindInterceptorType);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * get rpc xid
+ * @return
+ */
+ private String getRpcXid() {
+ String rpcXid =
RpcContext.getContext().getAttachment(RootContext.KEY_XID);
+ if (rpcXid == null) {
+ rpcXid =
RpcContext.getContext().getAttachment(RootContext.KEY_XID.toLowerCase());
+ }
+ return rpcXid;
+ }
+
+}
+```
+
+ 1. Based on the source code, we can deduce the corresponding logic
processing.
+
+
+
+## Key Points
+
+1. Dubbo @Activate Annotation:
+
+
+```java
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Activate {
+
+ String[] group() default {};
+
+
+ String[] value() default {};
+
+
+ String[] before() default {};
+
+
+ String[] after() default {};
+
+
+ int order() default 0;
+}
+```
+It can be analyzed that the @Activate annotation on Seata's Dubbo filter, with
parameters @Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, order =
100), indicates that both the Dubbo service provider and consumer will trigger
this filter. Therefore, our Seata initiator will initiate an XID transmission.
The above flowchart and code have clearly represented this.
+
+2. Dubbo implicit parameter passing can be achieved through setAttachment and
getAttachment on RpcContext for implicit parameter transmission between service
consumers and providers.
+
+Fetching: RpcContext.getContext().getAttachment(RootContext.KEY_XID);
+
+Passing: RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid);
+
+# Conclusion
+
+For further source code reading, please visit the [Seata official
website](https://seata.apache.org/)
+
+
diff --git a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-go-server.md
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-go-server.md
index bc5b32b236..e886afde1f 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-go-server.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-go-server.md
@@ -4,3 +4,79 @@ author: fagongzi([email protected])
date: 2019/04/23
keywords: [seata, distributed transaction, high availability]
---
+# Seata High-Availability Server TaaS Officially Open Source
+
+### Preface
+TaaS is a high-availability implementation of the Seata server (TC,
Transaction Coordinator), written in `Golang`. Taas has been contributed to the
Seata open-source community by InfiniVision (http://infinivision.cn) and is now
officially open source.
+
+Before Seata was open-sourced, we began to reference GTS and some open-source
projects to implement the distributed transaction solution TaaS (Transaction as
a Service).
+
+After we completed the development of the TaaS server, Seata (then called
Fescar) was open-sourced and attracted widespread attention from the
open-source community. With Alibaba's platform influence and community
activity, we believe that Seata will become the standard for open-source
distributed transactions in the future. Therefore, we decided to make TaaS
compatible with Seata.
+
+Upon discovering that Seata's server implementation was single-node and lacked
high availability, we contacted the Seata community leaders and decided to
open-source TaaS to contribute to the open-source community. We will also
maintain it in the long term and keep it synchronized with Seata versions.
+
+Currently, the official Java high-availability version of Seata is also under
development. TaaS and this high-availability version have different design
philosophies and will coexist in the future.
+
+TaaS has been open-sourced on GitHub
(https://github.com/apache/incubator-seata-go-server). We welcome everyone to
try it out.
+
+### Design Principles
+1. High Performance: Performance scales linearly with the number of machines.
Adding new machines to the cluster can improve performance.
+2. High Availability: If a machine fails, the system can still provide
services externally, or the service can be restored externally in a short time
(the time it takes to switch leaders).
+3. Auto-Rebalance: When new machines are added to the cluster or machines are
offline, the system can automatically perform load balancing.
+4. Strong Consistency: The system's metadata is stored consistently in
multiple replicas.
+
+### Design
+
+
+#### High Performance
+TaaS's performance scales linearly with the number of machines. To support
this feature, TaaS handles the smallest unit of global transactions called a
`Fragment`. The system sets the maximum concurrency of active global
transactions supported by each Fragment upon startup. The system also samples
each Fragment, and when it becomes overloaded, it generates new Fragments to
handle more concurrency.
+
+#### High Availability
+Each `Fragment` has multiple replicas and one leader to handle requests. When
the leader fails, the system generates a new leader to handle requests. During
the election process of the new leader, the Fragment does not provide services
externally, typically for a few seconds.
+
+#### Strong Consistency
+TaaS itself does not store the metadata of global transactions. The metadata
is stored in Elasticell (https://github.com/deepfabric/elasticell), a
distributed KV storage compatible with the Redis protocol. Elasticell ensures
data consistency based on the Raft protocol.
+
+#### Auto-Rebalance
+As the system runs, there will be many `Fragments` and their replicas,
resulting in uneven distribution of Fragments on each machine, especially when
old machines are offline or new machines come online. When TaaS starts, it
selects three nodes as schedulers, responsible for scheduling these `Fragments`
to ensure that the number of Fragments and the number of leaders on each
machine are roughly equal. It also ensures that the number of replicas for each
Fragment remains at the specified number.
+
+##### Fragment Replication Creation
+
+
+1. At time t0, Fragment1 is created on machine Seata-TC1.
+2. At time t1, a replica of Fragment1, Fragment1', is created on machine
Seata-TC2.
+3. At time t2, another replica of Fragment1, Fragment1", is created on machine
Seata-TC3.
+
+By time t2, all three replicas of Fragment1 are created.
+
+##### Fragment Replication Migration
+
+
+1. At time t0, the system has four Fragments, each existing on machines
Seata-TC1, Seata-TC2, and Seata-TC3.
+2. At time t1, a new machine, Seata-TC4, is added.
+3. At time t2, replicas of three Fragments are migrated to machine Seata-TC4.
+
+### Online Quick Experience
+We have set up an experience environment on the public network:
+* Seata Server Address: 39.97.115.141:8091
+* UI: http://39.97.115.141:8084/ui/index.html
+
+### Local Quick Experience
+Quickly experience TaaS functionality using docker-compose.
+```bash
+git clone https://github.com/seata/taas.git
+docker-compse up -d
+```
+Due to the many component dependencies, the docker-compose takes about 30
seconds to start and become available for external services.
+
+#### Seata Server Address
+The service listens on the default port 8091. Modify the Seata server address
accordingly to experience.
+
+#### Seata UI
+Access the WEB UI at `http://127.0.0.1:8084/ui/index.html`
+
+### About InfiniVision
+InfiniVision is a technology-driven enterprise service provider dedicated to
assisting traditional enterprises in digital transformation and upgrading using
technologies such as artificial intelligence, cloud computing, blockchain, big
data, and IoT edge computing. InfiniVision actively embraces open source
culture and open sources core algorithms and architectures. Notable open-source
products include the facial recognition software InsightFace
(https://github.com/deepinsight/insightfac [...]
+
+### About the Author
+The author, Zhang Xu, is the creator of the open-source Gateway
(https://github.com/fagongzi/gateway) and currently works at InfiniVision,
focusing on infrastructure-related development.
diff --git
a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-java-server.md
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-java-server.md
index df726d7bba..2feab53243 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-java-server.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-java-server.md
@@ -4,3 +4,325 @@ author: zhao.li,min.ji
date: 2019/04/08
keywords: [fescar, seata, distributed transaction]
---
+# 1. About Seata
+Not long ago, I wrote an analysis of the distributed transaction middleware
Fescar. Shortly after, the Fescar team rebranded it as Seata (Simple Extensible
Autonomous Transaction Architecture), whereas the previous Fescar's English
full name was Fast & Easy Commit And Rollback. It can be seen that Fescar was
more limited to Commit and Rollback based on its name, while the new brand name
Seata aims to create a one-stop distributed transaction solution. With the name
change, I am more conf [...]
+
+Here, let's briefly recall the overall process model of Seata:
+
+
+
+- TM: Transaction initiator. Used to inform TC about the start, commit, and
rollback of global transactions.
+- RM: Specific transaction resource. Each RM is registered as a branch
transaction in TC.
+- TC: Transaction coordinator. Also known as Fescar-server, used to receive
registration, commit, and rollback of transactions.
+
+In previous articles, I provided a general introduction to the roles, and in
this article, I will focus on the core role TC, which is the transaction
coordinator.
+
+# 2. Transaction Coordinator
+Why has the emphasis been placed on TC as the core role? Because TC, like God,
manages the RM and TM of countless beings in the cloud. If TC fails to function
properly, even minor issues with RM and TM will lead to chaos. Therefore, to
understand Seata, one must understand its TC.
+
+So, what capabilities should an excellent transaction coordinator possess? I
think it should have the following:
+
+- Correct coordination: It should be able to properly coordinate what RM and
TM should do next, what to do if something goes wrong, and what to do if
everything goes right.
+- High availability: The transaction coordinator is crucial in distributed
transactions. If it cannot ensure high availability, it serves no purpose.
+- High performance: The performance of the transaction coordinator must be
high. If there are performance bottlenecks, it will frequently encounter
timeouts, leading to frequent rollbacks.
+- High scalability: This characteristic belongs to the code level. If it is an
excellent framework, it needs to provide many customizable extensions for
users, such as service registration/discovery, reading configuration, etc.
+
+Next, I will explain how Seata achieves the above four points.
+
+## 2.1 Seata-Server Design
+
+
+
+The overall module diagram of Seata-Server is shown above:
+- Coordinator Core: At the bottom is the core code of the transaction
coordinator, mainly used to handle transaction coordination logic, such as
whether to commit, rollback, etc.
+- Store: Storage module used to persist data to prevent data loss during
restarts or crashes.
+- Discovery: Service registration/discovery module used to expose server
addresses to clients.
+- Config: Used to store and retrieve server configurations.
+- Lock: Lock module used to provide global locking functionality to Seata.
+- RPC: Used for communication with other endpoints.
+- HA-Cluster: High availability cluster, currently not open-source, provides
reliable high availability services to Seata, expected to be open-sourced in
version 0.6.
+
+## 2.2 Discovery
+
+First, let's talk about the basic Discovery module, also known as the service
registration/discovery module. After starting Seata-Sever, we need to expose
our address to other users, which is the responsibility of this module.
+
+
+
+This module has a core interface `RegistryService`, as shown in the image
above:
+- register: Used by the server to register the service.
+- unregister: Used by the server, typically called in JVM shutdown hooks.
+- subscribe: Used by clients to register event listeners to listen for address
changes.
+- unsubscribe: Used by clients to cancel event listeners.
+- lookup: Used by clients to retrieve service address lists based on keys.
+- close: Used to close the Registry resource.
+
+If you need to add your own service registration/discovery, just implement
this interface. So far, with the continuous development and promotion in the
community, there are already five service registration/discovery
implementations, including redis, zk, nacos, eruka, and consul. Below is a
brief introduction to the Nacos implementation:
+
+### 2.2.1 register Interface:
+
+
+Step 1: Validate the address.
+Step 2: Get the Naming instance of Nacos and register the address with the
service name `serverAddr` (fixed service name) on the corresponding cluster
group (configured in registry.conf).
+
+The unregister interface is similar, and I won't go into detail here.
+
+### 2.2.2 lookup Interface:
+
+
+Step 1: Get the current cluster name.
+Step 2: Check if the service corresponding to the current cluster name has
been subscribed. If yes, directly retrieve the subscribed data from the map.
+
+Step 3: If not subscribed, actively query the service instance list once, then
add subscription and store the data returned by subscription in the map. After
that, retrieve the latest data directly from the map.
+
+### 2.2.3 subscribe Interface:
+
+
+This interface is relatively simple, divided into two steps:
+Step 1: Add the `cluster -> listener` to be subscribed to the map. Since Nacos
does not provide a single machine already subscribed list, it needs to be
implemented by itself.
+Step 2: Subscribe using the Nacos API.
+
+## 2.3 Config
+The configuration module is also a relatively basic and simple module. We need
to configure some common parameters such as the number of select and work
threads for Netty, the maximum allowed session, etc. Of course, these
parameters in Seata have their own default settings.
+
+Similarly, Seata also provides an interface `Configuration` for customizing
where we need to obtain configurations:
+
+
+
+- getInt/Long/Boolean/getConfig(): Retrieves the corresponding value based on
the dataId. If the configuration cannot be read, an exception occurs, or a
timeout occurs, it returns the default value specified in the parameters.
+- putConfig: Used to add configuration.
+- removeConfig: Deletes a configuration.
+- add/remove/get ConfigListener: Add/remove/get configuration listeners,
usually used to listen for configuration changes.
+
+Currently, there are four ways to obtain Config: File (file-based), Nacos,
Apollo, and ZK (not recommended). In Seata, you first need to configure
`registry.conf` to specify the `config.type`. Implementing Config is relatively
simple, and I won't delve into it here.
+
+## 2.4 Store
+The implementation of the storage layer is crucial for Seata's performance and
reliability.
+If the storage layer is not implemented well, data being processed by TC in
distributed transactions may be lost in the event of a crash. Since distributed
transactions cannot tolerate data loss, if the storage layer is implemented
well but has significant performance issues, RM may experience frequent
rollbacks, making it unable to cope with high-concurrency scenarios.
+
+In Seata, file storage is provided as the default method for storing data.
Here, we define the data to be stored as sessions. Sessions created by the TM
are referred to as GlobalSessions, while those created by RMs are called
BranchSessions. A GlobalSession can have multiple BranchSessions. Our objective
is to store all these sessions.
+
+the code of FileTransactionStoreManager:
+
+
+
+The code snippet above can be broken down into the following steps:
+
+- **Step 1**: Generate a TransactionWriteFuture.
+- **Step 2**: Put this futureRequest into a LinkedBlockingQueue. Why do we
need to put all the data into a queue? Well, in fact, we could also use locks
for this purpose. In another Alibaba open-source project, RocketMQ, locks are
used. Whether it's a queue or a lock, their purpose is to ensure
single-threaded writing. But why is that necessary? Some might explain that
it's to ensure sequential writing, which would improve speed. However, this
understanding is incorrect. The write method [...]
+- **Step 3**: Call future.get to wait for the completion notification of our
write logic.
+
+Once we submit the data to the queue, the next step is to consume it. The code
is as follows:
+
+
+
+Here, a WriteDataFileRunnable() is submitted to our thread pool, and the run()
method of this Runnable is as follows:
+
+
+
+It can be broken down into the following steps:
+
+- **Step 1**: Check if stopping is true. If so, return null.
+- **Step 2**: Get data from our queue.
+- **Step 3**: Check if the future has timed out. If so, set the result to
false. At this point, our producer's get() method will unblock.
+- **Step 4**: Write our data to the file. At this point, the data is still in
the pageCache layer and has not been flushed to the disk yet. If the write is
successful, flush it based on certain conditions.
+- **Step 5**: When the number of writes reaches a certain threshold, or when
the writing time exceeds a certain limit, the current file needs to be saved as
a historical file, the old historical files need to be deleted, and a new file
needs to be created. This step is to prevent unlimited growth of our files,
which would waste disk resources.
+
+In our writeDataFile method, we have the following code:
+
+
+
+- **Step 1**: First, get our ByteBuffer. If it exceeds the maximum loop
BufferSize, create a new one directly; otherwise, use our cached Buffer. This
step can greatly reduce garbage collection.
+- **Step 2**: Add the data to the ByteBuffer.
+- **Step 3**: Finally, write the ByteBuffer to our fileChannel. This will be
retried three times. At this point, the data is still in the pageCache layer
and is affected by two factors: the OS has its own flushing strategy, but this
business program cannot control it. To prevent events such as crashes from
causing a large amount of data loss, the business itself needs to control the
flush. Below is the flush code:
+
+
+
+Here, the flush condition is based on writing a certain number of data or
exceeding a certain time. This also presents a small issue: in the event of a
power failure, there may still be data in the pageCache that has not been
flushed to disk, resulting in a small amount of data loss. Currently,
synchronous mode is not supported, which means that each piece of data needs to
be flushed, ensuring that each message is written to disk. However, this would
greatly affect performance. Of course [...]
+
+Our store's core process mainly consists of the above methods, but there are
also some other processes such as session reconstruction, which are relatively
simple and readers can read them on their own.
+
+
+## 2.5 Lock
+As we know, the isolation level in databases is mainly implemented through
locks. Similarly, in the distributed transaction framework Seata, achieving
isolation levels also requires locks. Generally, there are four isolation
levels in databases: Read Uncommitted, Read Committed, Repeatable Read, and
Serializable. In Seata, it can ensure that the isolation level is Read
Committed but provides means to achieve Read Committed isolation.
+
+The Lock module is the core module of Seata for implementing isolation levels.
In the Lock module, an interface is provided for managing our locks:
+
+
+It has three methods:
+- acquireLock: Used to lock our BranchSession. Although a branch transaction
Session is passed here, it is actually locking the resources of the branch
transaction. Returns true upon successful locking.
+- isLockable: Queries whether the transaction ID, resource ID, and locked key
are already locked.
+- cleanAllLocks: Clears all locks.
+
+For locks, we can implement them locally or use Redis or MySQL to help us
implement them. The official default provides local global lock implementation:
+
+
+In the local lock implementation, there are two constants to pay attention to:
+- BUCKET_PER_TABLE: Defines how many buckets each table has, aiming to reduce
competition when locking the same table later.
+- LOCK_MAP: This map seems very complex from its definition, with many layers
of Maps nested inside and outside. Here's a table to explain it specifically:
+
+Layer | Key | Value
+---|---|---
+1-LOCK_MAP | resourceId (jdbcUrl) | dbLockMap
+2- dbLockMap | tableName (table name) | tableLockMap
+3- tableLockMap | PK.hashcode%Bucket (hashcode%bucket of the primary key
value) | bucketLockMap
+4- bucketLockMap | PK | transactionId
+
+It can be seen that the actual locking occurs in the bucketLockMap. The
specific locking method here is relatively simple and will not be detailed. The
main process is to gradually find the bucketLockMap and then insert the current
transactionId. If this primary key currently has a TransactionId, then it
checks if it is itself; if not, the locking fails.
+
+## 2.6 RPC
+One of the key factors in ensuring Seata's high performance is the use of
Netty as the RPC framework, with the default configuration of the thread model
as shown in the diagram below:
+
+
+
+If the default basic configuration is adopted, there will be one Acceptor
thread for handling client connections and a number of NIO-Threads equal to
cpu*2. In these threads, heavy business operations are not performed. They only
handle relatively fast tasks such as encoding and decoding, heartbeats, and TM
registration. Time-consuming business operations are delegated to the business
thread pool. By default, the business thread pool is configured with a minimum
of 100 threads and a maxi [...]
+
+Seata currently allows for configuration of transport layer settings, as shown
in the following diagram. Users can optimize Netty transport layer settings
according to their needs, and the configuration takes effect when loaded for
the first time.
+
+
+
+It's worth mentioning Seata's heartbeat mechanism, which is implemented using
Netty's IdleStateHandler, as shown below:
+
+
+
+On the server side, there is no maximum idle time set for writing, and for
reading, the maximum idle time is set to 15 seconds (the client's default write
idle time is 5 seconds, sending ping messages). If it exceeds 15 seconds, the
connection will be disconnected, and resources will be closed.
+
+
+
+- Step 1: Check if it is a read idle detection event.
+- Step 2: If it is, disconnect the connection and close the resources.
+
+Additionally, Seata has implemented features such as memory pools, batch
merging of small packets by the client for sending, and Netty connection pools
(reducing the service unavailable time when creating connections), one of which
is batch merging of small packets.
+
+
+
+
+The client's message sending process does not directly send messages. Instead,
it wraps the message into an RpcMessage through
AbstractRpcRemoting#sendAsyncRequest and stores it in the basket, then wakes up
the merge sending thread. The merge sending thread, through a while true loop,
waits for a maximum of 1ms to retrieve messages from the basket and wraps them
into merge messages for actual sending. If an exception occurs in the channel
during this process, it will quickly fail and ret [...]
+
+Seata's Netty Client consists of TMClient and RMClient, distinguished by their
transactional roles. Both inherit from AbstractRpcRemotingClient, which
implements RemotingService (service start and stop), RegisterMsgListener (Netty
connection pool connection creation callback), and ClientMessageSender (message
sending), further inheriting from AbstractRpcRemoting (the top-level message
sending and processing template for Client and Server).
+
+The class diagram for RMClient is depicted below:
+
+
+TMClient and RMClient interact with channel connections based on their
respective poolConfig and NettyPoolableFactory, which implements
KeyedPoolableObjectFactory<NettyPoolKey, Channel>. The channel connection pool
locates each connection pool based on the role key+IP, and manages channels
uniformly. During the sending process, TMClient and RMClient each use only one
long-lived connection per IP. However, if a connection becomes unavailable, it
is quickly retrieved from the connection po [...]
+
+## 2.7 HA-Cluster
+Currently, the official HA-Cluster design has not been publicly disclosed.
However, based on some hints from other middleware and the official channels,
HA-Cluster could be designed as follows:
+
+
+The specific process is as follows:
+
+**Step 1:** When clients publish information, they ensure that the same
transaction with the same transaction ID is handled on the same master. This is
achieved by horizontally scaling multiple masters to provide concurrent
processing performance.
+
+**Step 2:** On the server side, each master has multiple slaves. Data in the
master is nearly real-time synchronized to the slaves, ensuring that when the
master crashes, other slaves can take over.
+
+However, all of the above is speculation, and the actual design and
implementation will have to wait until version 0.5. Currently, there is a Go
version of Seata-Server donated to Seata (still in progress), which implements
replica consistency through Raft. However, other details are not clear.
+
+## 2.8 Metrics
+This module has not yet disclosed a specific implementation. However, it may
provide a plugin interface for integrating with other third-party metrics.
Recently, Apache SkyWalking has been discussing how to integrate with the Seata
team.
+
+# 3. Coordinator Core
+We have covered many foundational modules of the Seata server. I believe you
now have a general understanding of Seata's implementation. Next, I will
explain how the transaction coordinator's specific logic is implemented,
providing you with a deeper understanding of Seata's internal workings.
+
+## 3.1 Startup Process
+The startup method is defined in the Server class's main method, outlining our
startup process:
+
+
+
+
+step1: Create an RpcServer, which encapsulates network operations using Netty
to implement the server.
+
+step2: Parse the port number, local file address (for recovering incomplete
transactions if the server crashes), and IP address (optional, useful for
obtaining an external VIP registration service when crossing networks).
+
+step3: Initialize SessionHolder, wherein the crucial step is to recover data
from the dataDir folder and rebuild sessions.
+
+step4: Create a Coordinator, the core logic of the transaction coordinator,
and initialize it. The initialization process includes creating four scheduled
tasks:
+- retryRollbacking: Retry rollback task, used to retry failed rollbacks,
executed every 5ms.
+- retryCommitting: Retry commit task, used to retry failed commits, executed
every 5ms.
+- asyncCommitting: Asynchronous commit task, used to perform asynchronous
commits, executed every 10ms.
+- timeoutCheck: Timeout task check, used to detect timeout tasks and execute
timeout logic, executed every 2ms.
+
+step5: Initialize UUIDGenerator, a basic class used for generating various IDs
(transactionId, branchId).
+
+step6: Set the local IP and listening port in XID, initialize rpcServer, and
wait for client connections.
+
+The startup process is relatively straightforward. Next, I will describe how
Seata handles common business logic in distributed transaction frameworks.
+
+## 3.2 Begin - Start Global Transaction
+The starting point of a distributed transaction is always to start a global
transaction. Let's see how Seata implements global transactions:
+
+
+
+step1: Create a GloabSession based on the application ID, transaction group,
name, and timeout. As mentioned earlier, GloabSession and BranchSession
represent different aspects of the transaction.
+
+step2: Add a RootSessionManager to it for listening to some events. Currently,
Seata has four types of listeners (it's worth noting that all session managers
implement SessionLifecycleListener):
+- ROOT_SESSION_MANAGER: The largest, containing all sessions.
+- ASYNC_COMMITTING_SESSION_MANAGER: Manages sessions that need asynchronous
commit.
+- RETRY_COMMITTING_SESSION_MANAGER: Manages sessions for retrying commit.
+- RETRY_ROLLBACKING_SESSION_MANAGER: Manages sessions for retrying rollback.
+Since this is the beginning of a transaction, other SessionManagers are not
needed, so only add RootSessionManager.
+
+step3: Start GloabSession, which changes the state to Begin, records the start
time, and calls the onBegin method of RootSessionManager to save the session to
the map and write it to the file.
+
+step4: Finally, return the XID. This XID is composed of ip+port+transactionId,
which is crucial. When the TM acquires it, it needs to pass this ID to RM. RM
uses XID to determine which server to access.
+
+## 3.3 BranchRegister - Register Branch Transaction
+After the global transaction is initiated by TM, the branch transaction of our
RM also needs to be registered on top of our global transaction. Here's how
it's handled:
+
+
+
+step1: Retrieve and validate the global transaction's state based on the
transactionId.
+
+step2: Create a new branch transaction, which is our BranchSession.
+
+step3: Lock the branch transaction globally. Here, the logic uses the lock
module.
+
+step4: Add the branchSession, mainly by adding it to the globalSession object
and writing it to our file.
+
+step5: Return the branchId, which is also important. We will need it later to
roll back our transaction or update the status of our branch transaction.
+
+After registering the branch transaction, it is necessary to report whether
the local transaction execution of the branch transaction was successful or
failed. Currently, the server simply records this information. The purpose of
reporting is that even if this branch transaction fails, if the TM insists on
committing the global transaction (catches exceptions without throwing), then
when traversing to commit the branch transaction, this failed branch
transaction does not need to be commi [...]
+
+## 3.4 GlobalCommit - Global Commit
+
+When our branch transaction is completed, it's up to our TM - Transaction
Manager to decide whether to commit or rollback. If it's a commit, then the
following logic will be executed:
+
+
+
+step1: First, find our globalSession. If it's null, it means it has already
been committed, so perform idempotent operation and return success.
+
+step2: Close our GloabSession to prevent new branches from coming in (rollback
due to timeout in cross-service calls, provider continues execution).
+
+step3: If the status is Begin, it means it hasn't been committed yet, so
change its status to Committing, indicating that it's committing.
+
+step4: Determine if it can be asynchronously committed. Currently, only AT
mode can be asynchronously committed. In two-phase global commits, undolog is
only deleted without strict order. Here, a timer task is used, and the client
merges and deletes in batches after receiving it.
+
+step5: If it's an asynchronous commit, directly put it into our
ASYNC_COMMITTING_SESSION_MANAGER to let it asynchronously execute step6 in the
background. If it's synchronous, then execute step6 directly.
+
+step6: Traverse our BranchSessions for submission. If a branch transaction
fails, determine whether to retry based on different conditions. This
branchSession can be executed asynchronously, and if it fails, it can continue
with the next one because it remains in the manager and won't be deleted until
it succeeds. If it's a synchronous commit, it will be put into the retry queue
for scheduled retries and will block and submit in sequence.
+
+## 3.5 GlobalRollback - Global Rollback
+
+If our TM decides to globally rollback, it will follow the logic below:
+
+
+
+This logic is basically the same as the commit process but in reverse. I won't
delve into it here.
+
+# 4. Conclusion
+
+Finally, let's summarize how Seata solves the key points of distributed
transactions:
+
+- Correct coordination: Through background scheduled tasks, various retries
are performed correctly, and in the future, a monitoring platform may be
introduced, possibly allowing manual rollback.
+- High availability: Ensured by HA-Cluster.
+- High performance: Sequential file writing, RPC implemented through Netty,
and Seata can be horizontally scaled in the future to improve processing
performance.
+- High extensibility: Provides places where users can freely implement, such
as configuration, service discovery and registration, global lock, etc.
+
+In conclusion, I hope you can understand the core design principles of
Seata-Server from this article. Of course, you can also imagine how you would
design a distributed transaction server if you were to implement one yourself.
+
+Seata GitHub Repository:
[https://github.com/apache/incubator-seata](https://github.com/apache/incubator-seata)
+
+Article Authors:
+
+Li Zhao, GitHub ID @CoffeeLatte007, author of the public account "咖啡拿铁", Seata
community Committer, Java engineer at Yuanfudao, formerly employed at Meituan.
Has a strong interest in distributed middleware and distributed systems.
+Ji Min (Qingming), GitHub ID @slievrly, Seata open source project leader, core
R&D member of Alibaba middleware TXC/GTS, has long been engaged in core R&D
work of distributed middleware, and has rich technical accumulation in the
field of distributed transactions.
+
diff --git
a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-tcc-modular.md
b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-tcc-modular.md
index 59f9ec75cb..12b3834e74 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-analysis-tcc-modular.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-analysis-tcc-modular.md
@@ -4,3 +4,254 @@ author: runze.zhao
keywords: [Seata, distributed transaction]
date: 2019/12/25
---
+## 一. Introduction
+
+In the analysis of the Spring module, it is noted that Seata's Spring module
handles beans involved in distributed transactions. Upon project startup, when
the `GlobalTransactionalScanner` detects references to TCC services (i.e., TCC
transaction participants), it dynamically proxies them by weaving in the
implementation class of `MethodInterceptor` under the TCC mode. The initiator
of the TCC transaction still uses the `@GlobalTransactional` annotation to
initiate it, and a generic impl [...]
+
+The implementation class of `MethodInterceptor` under the TCC mode is referred
to as `TccActionInterceptor` (in the Spring module). This class invokes
`ActionInterceptorHandler` (in the TCC module) to handle the transaction
process under the TCC mode.
+
+The primary functions of TCC dynamic proxy are: generating the TCC runtime
context, propagating business parameters, and registering branch transaction
records.
+
+## 二. Introduction to TCC Mode
+
+In the Two-Phase Commit (2PC) protocol, the transaction manager coordinates
resource management in two phases. The resource manager provides three
operations: the prepare operation in the first phase, and the commit operation
and rollback operation in the second phase.
+
+
+```java
+public interface TccAction {
+
+ @TwoPhaseBusinessAction(name = "tccActionForTest" , commitMethod =
"commit", rollbackMethod = "rollback")
+ public boolean prepare(BusinessActionContext actionContext,
+ @BusinessActionContextParameter(paramName = "a")
int a,
+ @BusinessActionContextParameter(paramName = "b",
index = 0) List b,
+ @BusinessActionContextParameter(isParamInProperty =
true) TccParam tccParam);
+
+ public boolean commit(BusinessActionContext actionContext);
+
+ public boolean rollback(BusinessActionContext actionContext);
+}
+```
+
+This is a participant instance in TCC. Participants need to implement three
methods, where the first parameter must be BusinessActionContext, and the
return type of the methods is fixed. These methods are exposed as microservices
to be invoked by the transaction manager.
+
+- prepare: Checks and reserves resources. For example, deducting the account
balance and increasing the same frozen balance.
+- commit: Uses the reserved resources to complete the actual business
operation. For example, reducing the frozen balance to complete the fund
deduction business.
+- cancel: Releases the reserved resources. For example, adding back the frozen
balance to the account balance.
+
+The BusinessActionContext encapsulates the context environment of the current
transaction: xid, branchId, actionName, and parameters annotated with
@BusinessActionContextParam.
+
+There are several points to note in participant business:
+1. Ensure business idempotence, supporting duplicate submission and rollback
of the same transaction.
+2. Prevent hanging, i.e., the rollback of the second phase occurs before the
try phase.
+3. Relax consistency protocols, eventually consistent, so it is
read-after-write.
+
+## Three. Remoting package analysis
+
+
+
+All classes in the package serve DefaultRemotingParser. Dubbo, LocalTCC, and
SofaRpc are responsible for parsing classes under their respective RPC
protocols.
+
+Main methods of DefaultRemotingParser:
+1. Determine if the bean is a remoting bean, code:
+
+
+```java
+ @Override
+ public boolean isRemoting(Object bean, String beanName) throws
FrameworkException {
+ //判断是否是服务调用方或者是否是服务提供方
+ return isReference(bean, beanName) || isService(bean, beanName);
+ }
+```
+2. Remote bean parsing, parses rpc classes into RemotingDesc.
+
+Code:
+
+
+```java
+@Override
+ public boolean isRemoting(Object bean, String beanName) throws
FrameworkException {
+ //判断是否是服务调用方或者是否是服务提供方
+ return isReference(bean, beanName) || isService(bean, beanName);
+ }
+```
+
+Utilize allRemotingParsers to parse remote beans. allRemotingParsers is
dynamically loaded in initRemotingParser() by calling
EnhancedServiceLoader.loadAll(RemotingParser.class), which implements the SPI
loading mechanism for loading subclasses of RemotingParser.
+
+For extension purposes, such as implementing a parser for feign remote calls,
simply write the relevant implementation classes of RemotingParser in the SPI
configuration. This approach offers great extensibility.
+
+RemotingDesc contains specific information about remote beans required for the
transaction process, such as targetBean, interfaceClass, interfaceClassName,
protocol, isReference, and so on.
+
+3. TCC Resource Registration
+
+
+```java
+public RemotingDesc parserRemotingServiceInfo(Object bean, String beanName) {
+ RemotingDesc remotingBeanDesc = getServiceDesc(bean, beanName);
+ if (remotingBeanDesc == null) {
+ return null;
+ }
+ remotingServiceMap.put(beanName, remotingBeanDesc);
+
+ Class<?> interfaceClass = remotingBeanDesc.getInterfaceClass();
+ Method[] methods = interfaceClass.getMethods();
+ if (isService(bean, beanName)) {
+ try {
+ //service bean, registry resource
+ Object targetBean = remotingBeanDesc.getTargetBean();
+ for (Method m : methods) {
+ TwoPhaseBusinessAction twoPhaseBusinessAction =
m.getAnnotation(TwoPhaseBusinessAction.class);
+ if (twoPhaseBusinessAction != null) {
+ TCCResource tccResource = new TCCResource();
+
tccResource.setActionName(twoPhaseBusinessAction.name());
+ tccResource.setTargetBean(targetBean);
+ tccResource.setPrepareMethod(m);
+
tccResource.setCommitMethodName(twoPhaseBusinessAction.commitMethod());
+ tccResource.setCommitMethod(ReflectionUtil
+ .getMethod(interfaceClass,
twoPhaseBusinessAction.commitMethod(),
+ new Class[] {BusinessActionContext.class}));
+
tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod());
+ tccResource.setRollbackMethod(ReflectionUtil
+ .getMethod(interfaceClass,
twoPhaseBusinessAction.rollbackMethod(),
+ new Class[] {BusinessActionContext.class}));
+ //registry tcc resource
+
DefaultResourceManager.get().registerResource(tccResource);
+ }
+ }
+ } catch (Throwable t) {
+ throw new FrameworkException(t, "parser remoting service
error");
+ }
+ }
+ if (isReference(bean, beanName)) {
+ //reference bean, TCC proxy
+ remotingBeanDesc.setReference(true);
+ }
+ return remotingBeanDesc;
+ }
+```
+
+Firstly, determine if it is a transaction participant. If so, obtain the
interfaceClass from RemotingDesc, iterate through the methods in the interface,
and check if there is a @TwoParserBusinessAction annotation on the method. If
found, encapsulate the parameters into TCCResource and register the TCC
resource through DefaultResourceManager.
+
+Here, DefaultResourceManager will search for the corresponding resource
manager based on the BranchType of the Resource. The resource management class
under the TCC mode is in the tcc module.
+
+This RPC parsing class is mainly provided for use by the spring module.
parserRemotingServiceInfo() is encapsulated into the TCCBeanParserUtils utility
class in the spring module. During project startup, the
GlobalTransactionScanner in the spring module parses TCC beans through the
utility class. TCCBeanParserUtils calls TCCResourceManager to register
resources. If it is a global transaction service provider, it will weave in the
TccActionInterceptor proxy. These processes are functional [...]
+
+## Three. TCC Resource Manager
+
+TCCResourceManager is responsible for managing the registration, branching,
committing, and rolling back of resources under the TCC mode.
+
+1. During project startup, when the GlobalTransactionScanner in the spring
module detects that a bean is a tcc bean, it caches resources locally and
registers them with the server:
+
+
+```java
+ @Override
+ public void registerResource(Resource resource) {
+ TCCResource tccResource = (TCCResource)resource;
+ tccResourceCache.put(tccResource.getResourceId(), tccResource);
+ super.registerResource(tccResource);
+ }
+```
+
+The logic for communicating with the server is encapsulated in the parent
class AbstractResourceManager. Here, TCCResource is cached based on resourceId.
When registering resources in the parent class AbstractResourceManager,
resourceGroupId + actionName is used, where actionName is the name specified in
the @TwoParseBusinessAction annotation, and resourceGroupId defaults to DEFAULT.
+
+2. Transaction branch registration is handled in the rm-datasource package
under AbstractResourceManager. During registration, the parameter lockKeys is
null, which differs from the transaction branch registration under the AT mode.
+
+3. Committing or rolling back branches:
+
+
+```java
+ @Override
+ public BranchStatus branchCommit(BranchType branchType, String xid, long
branchId, String resourceId,
+ String applicationData) throws
TransactionException {
+ TCCResource tccResource =
(TCCResource)tccResourceCache.get(resourceId);
+ if (tccResource == null) {
+ throw new ShouldNeverHappenException("TCC resource is not exist,
resourceId:" + resourceId);
+ }
+ Object targetTCCBean = tccResource.getTargetBean();
+ Method commitMethod = tccResource.getCommitMethod();
+ if (targetTCCBean == null || commitMethod == null) {
+ throw new ShouldNeverHappenException("TCC resource is not
available, resourceId:" + resourceId);
+ }
+ try {
+ boolean result = false;
+ //BusinessActionContext
+ BusinessActionContext businessActionContext =
getBusinessActionContext(xid, branchId, resourceId,
+ applicationData);
+ Object ret = commitMethod.invoke(targetTCCBean,
businessActionContext);
+ if (ret != null) {
+ if (ret instanceof TwoPhaseResult) {
+ result = ((TwoPhaseResult)ret).isSuccess();
+ } else {
+ result = (boolean)ret;
+ }
+ }
+ return result ? BranchStatus.PhaseTwo_Committed :
BranchStatus.PhaseTwo_CommitFailed_Retryable;
+ } catch (Throwable t) {
+ LOGGER.error(msg, t);
+ throw new FrameworkException(t, msg);
+ }
+ }
+```
+Restore the business context using parameters xid, branchId, resourceId, and
applicationData.
+
+Execute the commit method through reflection based on the retrieved context
and return the execution result. The rollback method follows a similar approach.
+
+Here, branchCommit() and branchRollback() are provided for AbstractRMHandler,
an abstract class for resource processing in the rm module. This handler is a
further implementation class of the template method defined in the core module.
Unlike registerResource(), which actively registers resources during spring
scanning.
+
+## Four. Transaction Processing in TCC Mode
+
+The invoke() method of TccActionInterceptor in the spring module is executed
when the proxied rpc bean is called. This method first retrieves the global
transaction xid passed by the rpc interceptor, and then the transaction process
of global transaction participants under TCC mode is still handed over to the
ActionInterceptorHandler in the tcc module.
+
+In other words, transaction participants are proxied during project startup.
The actual business methods are executed through callbacks in
ActionInterceptorHandler.
+
+
+```java
+ public Map<String, Object> proceed(Method method, Object[] arguments,
String xid, TwoPhaseBusinessAction businessAction,
+ Callback<Object> targetCallback) throws
Throwable {
+ Map<String, Object> ret = new HashMap<String, Object>(4);
+
+ //TCC name
+ String actionName = businessAction.name();
+ BusinessActionContext actionContext = new BusinessActionContext();
+ actionContext.setXid(xid);
+ //set action anme
+ actionContext.setActionName(actionName);
+
+ //Creating Branch Record
+ String branchId = doTccActionLogStore(method, arguments,
businessAction, actionContext);
+ actionContext.setBranchId(branchId);
+
+ //set the parameter whose type is BusinessActionContext
+ Class<?>[] types = method.getParameterTypes();
+ int argIndex = 0;
+ for (Class<?> cls : types) {
+ if (cls.getName().equals(BusinessActionContext.class.getName())) {
+ arguments[argIndex] = actionContext;
+ break;
+ }
+ argIndex++;
+ }
+ //the final parameters of the try method
+ ret.put(Constants.TCC_METHOD_ARGUMENTS, arguments);
+ //the final result
+ ret.put(Constants.TCC_METHOD_RESULT, targetCallback.execute());
+ return ret;
+ }
+```
+
+Here are two important operations:
+
+1. In the doTccActionLogStore() method, two crucial methods are called:
+- fetchActionRequestContext(method, arguments): This method retrieves
parameters annotated with @BusinessActionContextParam and inserts them into
BusinessActionComtext along with transaction-related parameters in the init
method below.
+- DefaultResourceManager.get().branchRegister(BranchType.TCC, actionName,
null, xid, applicationContextStr, null): This method performs the registration
of transaction branches for transaction participants under TCC mode.
+
+2. Callback execution of targetCallback.execute(), which executes the specific
business logic of the proxied bean, i.e., the prepare() method.
+
+## Five. Summary
+The tcc module primarily provides the following functionalities:
+1. Defines annotations for two-phase protocols, providing attributes needed
for transaction processes under TCC mode.
+2. Provides implementations of ParserRemoting for parsing remoting beans of
different RPC frameworks, to be invoked by the spring module.
+3. Provides the TCC ResourceManager for resource registration, transaction
branch registration, submission, and rollback under TCC mode.
+4. Provides classes for handling transaction processes under TCC mode,
allowing MethodInterceptor proxy classes to delegate the execution of specific
mode transaction processes to the tcc module.
+
+## Related
+Author: Zhao Runze, [Series
Link](https://blog.csdn.net/qq_37804737/category_9530078.html).
diff --git a/i18n/en/docusaurus-plugin-content-blog/seata-at-lock.md
b/i18n/en/docusaurus-plugin-content-blog/seata-at-lock.md
index c671de6355..3a0f13f40a 100644
--- a/i18n/en/docusaurus-plugin-content-blog/seata-at-lock.md
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-at-lock.md
@@ -5,3 +5,181 @@ keywords: [Seata, distributed transaction, AT mode,
Transaction, GlobalLock]
description: The transaction isolation in Seata AT mode is built on the basis
of local isolation levels of supporting transactions. Assuming a database local
isolation level of Read Committed or higher, Seata designs a global
write-exclusive lock maintained by the transaction coordinator to ensure write
isolation between transactions. Meanwhile, the default isolation level for
global transactions is defined at Read Uncommitted.
date: 2022/01/12
---
+
+# Preface
+
+Seata AT mode is a non-intrusive distributed transaction solution. Seata
internally implements a proxy layer for database operations. When using Seata
AT mode, we actually use the built-in data source proxy DataSourceProxy
provided by Seata. Seata adds a lot of logic in this proxy layer, such as
inserting rollback undo_log records and checking global locks.
+
+Why check global locks? This is because the transaction isolation of Seata AT
mode is based on the local isolation level of supporting transactions. Under
the premise of database local isolation level of read committed or above, Seata
designs a global write exclusive lock maintained by the transaction coordinator
to ensure write isolation between transactions. At the same time, global
transactions are by default defined at the read uncommitted isolation level.
+
+# Understanding Seata Transaction Isolation Levels
+
+Before discussing Seata transaction isolation levels, let's review the
isolation levels of database transactions. Currently, there are four types of
database transaction isolation levels, from lowest to highest:
+
+1. Read uncommitted
+2. Read committed
+3. Repeatable read
+4. Serializable
+
+The default isolation level for databases is usually read committed, such as
Oracle, while some databases default to repeatable read, such as MySQL.
Generally, the read committed isolation level of databases can satisfy the
majority of business scenarios.
+
+We know that a Seata transaction is a global transaction, which includes
several local transaction branches. During the execution of a global
transaction (before the global transaction is completed), if a local
transaction commits and Seata does not take any measures, it may lead to
reading of committed local transactions, causing dirty reads. If a local
transaction that has been committed before the global transaction commits is
modified, it may cause dirty writes.
+
+From this, we can see that traditional dirty reads involve reading uncommitted
data, while Seata's dirty reads involve reading data that has not been
committed under the global transaction, where the global transaction may
include multiple local transactions. The fact that one local transaction
commits does not mean that the global transaction commits.
+
+Working under the read committed isolation level is fine for the vast majority
of applications. In fact, the majority of scenarios that work under the read
uncommitted isolation level also work fine.
+
+In extreme scenarios, if an application needs to achieve global read
committed, Seata also provides a global lock mechanism to implement global
transaction read committed. However, by default, Seata's global transactions
work under the read uncommitted isolation level to ensure efficiency in the
majority of scenarios.
+
+# Implementation of Global Locks
+
+In AT mode, Seata uses the internal data source proxy DataSourceProxy, and the
implementation of global locks is hidden within this proxy. Let's see what
happens during the execution and submission processes.
+
+## 1. Execution Process
+
+The execution process is in the StatementProxy class. During execution, if the
executed SQL is `select for update`, the SelectForUpdateExecutor class is used.
If the executed method is annotated with `@GlobalTransactional` or
`@GlobalLock`, it checks if there is a global lock. If a global lock exists, it
rolls back the local transaction and continuously competes to obtain local and
global locks through a while loop.
+
+
+io.seata.rm.datasource.exec.SelectForUpdateExecutor#doExecute
+
+```java
+public T doExecute(Object... args) throws Throwable {
+ Connection conn = statementProxy.getConnection();
+ // ... ...
+ try {
+ // ... ...
+ while (true) {
+ try {
+ // ... ...
+ if (RootContext.inGlobalTransaction() ||
RootContext.requireGlobalLock()) {
+ // Do the same thing under either @GlobalTransactional or
@GlobalLock,
+ // that only check the global lock here.
+ statementProxy.getConnectionProxy().checkLock(lockKeys);
+ } else {
+ throw new RuntimeException("Unknown situation!");
+ }
+ break;
+ } catch (LockConflictException lce) {
+ if (sp != null) {
+ conn.rollback(sp);
+ } else {
+ conn.rollback();
+ }
+ // trigger retry
+ lockRetryController.sleep(lce);
+ }
+ }
+ } finally {
+ // ...
+ }
+```
+
+## 2. Submission Process
+
+The submission process occurs in the doCommit method of ConnectionProxy.
+
+1) If the executed method is annotated with `@GlobalTransactional`, it will
acquire the global lock during branch registration:
+
+- Requesting TC to register a branch
+
+io.seata.rm.datasource.ConnectionProxy#register
+
+```java
+private void register() throws TransactionException {
+ if (!context.hasUndoLog() || !context.hasLockKey()) {
+ return;
+ }
+ Long branchId = DefaultResourceManager.get().branchRegister(BranchType.AT,
getDataSourceProxy().getResourceId(),
+ null,
context.getXid(), null, context.buildLockKeys());
+ context.setBranchId(branchId);
+}
+```
+
+- When a TC registers a branch, it obtains a global lock
+
+io.seata.server.transaction.at.ATCore#branchSessionLock
+
+```java
+protected void branchSessionLock(GlobalSession globalSession, BranchSession
branchSession) throws TransactionException {
+ if (!branchSession.lock()) {
+ throw new BranchTransactionException(LockKeyConflict, String
+ .format("Global lock acquire
failed xid = %s branchId = %s", globalSession.getXid(),
+
branchSession.getBranchId()));
+ }
+}
+```
+
+2)If the execution method has a '@GlobalLock' annotation, the global lock is
checked for existence before committing, and if it does, an exception is thrown:
+
+io.seata.rm.datasource.ConnectionProxy#processLocalCommitWithGlobalLocks
+
+```java
+private void processLocalCommitWithGlobalLocks() throws SQLException {
+ checkLock(context.buildLockKeys());
+ try {
+ targetConnection.commit();
+ } catch (Throwable ex) {
+ throw new SQLException(ex);
+ }
+ context.reset();
+}
+```
+
+## GlobalLock Annotation Explanation
+
+From the execution process and submission process, it can be seen that since
opening a global transaction with the `@GlobalTransactional` annotation can
check if the global lock exists before transaction submission, why does Seata
still provide a `@GlobalLock` annotation?
+
+This is because not all database operations require opening a global
transaction, and opening a global transaction is a relatively heavy operation
that involves initiating RPC processes to TC. The `@GlobalLock` annotation only
checks the existence of the global lock during the execution process and does
not initiate a global transaction. Therefore, when there is no need for a
global transaction but the global lock needs to be checked to avoid dirty reads
and writes, using the `@GlobalLoc [...]
+
+# How to Prevent Dirty Writes
+
+Let's first understand how dirty writes occur when using Seata AT mode:
+
+
+
+*Note: Other processes in the branch transaction execution are omitted.*
+
+When Business One starts a global transaction containing branch transaction A
(modifying A) and branch transaction B (modifying B), Business Two modifies A.
Business One's branch transaction A obtains a local lock before Business Two,
waiting for Business One to complete the execution of branch transaction A.
Business Two then obtains the local lock, modifies A, and commits it to the
database. However, Business One encounters an exception during the execution of
branch transaction A. Sin [...]
+
+How to prevent dirty writes?
+
+1. Business Two uses `@GlobalTransactional` annotation:
+
+
+
+*Note: Other processes in the branch transaction execution are omitted.*
+
+During the execution of the global transaction by Business Two, when
registering the branch transaction before the submission of branch transaction
A and acquiring the global lock, it finds that Business One's global lock has
not been released yet. Therefore, Business Two cannot commit and throws an
exception to roll back, thus preventing dirty writes.
+
+2. Business Two uses `@GlobalLock` annotation:
+
+
+
+*Note: Other processes in the branch transaction execution are omitted.*
+
+Similar to the effect of `@GlobalTransactional` annotation, but without the
need to open a global transaction, it only checks the existence of the global
lock before local transaction submission.
+
+3. Business Two uses `@GlobalLock` annotation + `select for update` statement:
+
+
+
+If a `select for update` statement is added, it checks the existence of the
global lock before the update operation. Business Two can only execute the
updateA operation after the global lock is released.
+
+If only `@Transactional` is used, there is a possibility of dirty writes. The
fundamental reason is that without the GlobalLock annotation, the global lock
is not checked, which may lead to another global transaction finding that a
branch transaction has been modified when rolling back. Therefore, adding
`select for update` also has a benefit, which is that it allows for retries.
+
+
+# How to Prevent Dirty Reads
+
+Dirty reads in Seata AT mode refer to the scenario where data from a branch
transaction that has been committed is read by another business before the
global transaction is committed. Essentially, this is because Seata's default
global transaction isolation level is read uncommitted.
+
+So how to prevent dirty reads?
+
+Business Two queries A with `@GlobalLock` annotation + `select for update`
statement:
+
+
+
+Adding the `select for update` statement checks the existence of the global
lock before executing the SQL. The SQL can only be executed after the global
lock is acquired, thus preventing dirty reads.
+
+# Author Bio:
+
+Zhang Chenghui currently works at Ant Group and is passionate about sharing
technology. He is the author of the WeChat public account "后端进阶" (Backend
Advancement) and the owner of the technical blog (https://objcoding.com/). He
is also a Seata Contributor with GitHub ID: objcoding.
diff --git a/i18n/en/docusaurus-plugin-content-blog/seata-meetup-hangzhou.md
b/i18n/en/docusaurus-plugin-content-blog/seata-meetup-hangzhou.md
new file mode 100644
index 0000000000..a787ad4b14
--- /dev/null
+++ b/i18n/en/docusaurus-plugin-content-blog/seata-meetup-hangzhou.md
@@ -0,0 +1,51 @@
+---
+title: Seata Community Meetup·Hangzhou Station
+keywords: [Seata, Hangzhou, meetup]
+date: 2019/12/01
+description: Seata Community Meetup·Hangzhou Station was successfully held at
Zhejiang Youth Innovation Space, Dream Town, Hangzhou on December 21st.
+---
+# Seata Meetup·Hangzhou Station Successfully Held
+
+
+
+### Event Introduction
+
+### Highlight Interpretation
+
+- Seata project founder presented "Seata Past, Present, and Future" along with
new features of Seata 1.0.
+- Seata core contributors elaborated on Seata AT, TCC, and Saga modes.
+- Implementation analysis of Seata in internet healthcare and Didi Chuxing.
+
+- [Replay benefits (Developer
Community)](https://developer.aliyun.com/live/1760)
+- [Join Seata thousand-member DingTalk group](http://w2wz.com/h2nb)
+
+### Guest Speakers
+
+- Ji Min (Qing Ming) "Seata Past, Present, and Future"
[slides](https://github.com/funky-eyes/awesome-seata/blob/master/slides/meetup/201912%40hangzhou/%E5%AD%A3%E6%95%8F%EF%BC%88%E6%B8%85%E9%93%AD%EF%BC%89%E3%80%8ASeata%20%E7%9A%84%E8%BF%87%E5%8E%BB%E3%80%81%E7%8E%B0%E5%9C%A8%E5%92%8C%E6%9C%AA%E6%9D%A5%E3%80%8B.pdf)
+
+ 
+
+- Wu Jiangke "My Open Source Journey with SEATA and SEATA's Application in
Internet Healthcare Systems"
[slides](https://github.com/seata/awesome-seata/blob/master/slides/meetup/201912%40hangzhou/%E5%AD%A3%E6%95%8F%EF%BC%88%E6%B8%85%E9%93%AD%EF%BC%89%E3%80%8ASeata%20%E7%9A%84%E8%BF%87%E5%8E%BB%E3%80%81%E7%8E%B0%E5%9C%A8%E5%92%8C%E6%9C%AA%E6%9D%A5%E3%80%8B.pdf)
+
+

+
+- Shen Haiqiang (Xuan Yi) "Essence of Seata AT Mode"
[slides](https://github.com/seata/awesome-seata/tree/master/slides/meetup/201912%40hangzhou)
+
+

+
+- Zhang Sen "Detailed Explanation of TCC Mode in Distributed Transaction Seata"
+
+

+
+- Chen Long (Yiyuan) "Seata Long Transaction Solution Saga Mode"
+
+

+
+- Chen Pengzhi "Seata Practice in Didi Chuxing's Motorcycle Business"
[slides](https://github.com/seata/awesome-seata/blob/master/slides/meetup/201912%40hangzhou/%E9%99%88%E9%B9%8F%E5%BF%97%E3%80%8ASeata%20%E5%9C%A8%E6%BB%B4%E6%BB%B4%E4%B8%A4%E8%BD%AE%E8%BD%A6%E4%B8%9A%E5%8A%A1%E7%9A%84%E5%AE%9E%E8%B7%B5%E3%80%8B.pdf)
+
+

+
+### Special Awards
+
+
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]