You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2023/03/15 13:17:01 UTC

[shardingsphere] branch master updated: Upload 2 Blogs to ShardingSphere (#24626)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 22ec2c8e67d Upload 2 Blogs to ShardingSphere (#24626)
22ec2c8e67d is described below

commit 22ec2c8e67da2068740c4e8b795f64b91a38e7cb
Author: FPokerFace <11...@users.noreply.github.com>
AuthorDate: Wed Mar 15 21:16:53 2023 +0800

    Upload 2 Blogs to ShardingSphere (#24626)
    
    * Upload 2 Blogs to ShardingSphere
    
    * Update 2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive.en.md
    
    * Update 2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case7.png
---
 ..._Based_on_ShardingSphere_Demo_&_User_Case.en.md | 405 +++++++++++++++++++
 ...ta_Masking_ShardingSphere_5.3.1_Deep_Dive.en.md | 440 +++++++++++++++++++++
 ...e_Based_on_ShardingSphere_Demo_&_User_Case1.png | Bin 0 -> 107409 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case2.png | Bin 0 -> 46115 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case3.png | Bin 0 -> 46115 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case4.png | Bin 0 -> 93045 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case5.png | Bin 0 -> 207208 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case6.png | Bin 0 -> 199072 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case7.png | Bin 0 -> 133359 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case8.png | Bin 0 -> 64803 bytes
 ...e_Based_on_ShardingSphere_Demo_&_User_Case9.png | Bin 0 -> 63127 bytes
 ...ata_Masking_ShardingSphere_5.3.1_Deep_Dive1.png | Bin 0 -> 178005 bytes
 ...ata_Masking_ShardingSphere_5.3.1_Deep_Dive2.png | Bin 0 -> 144376 bytes
 ...ata_Masking_ShardingSphere_5.3.1_Deep_Dive3.png | Bin 0 -> 140894 bytes
 14 files changed, 845 insertions(+)

diff --git a/docs/blog/content/material/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case.en.md b/docs/blog/content/material/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case.en.md
new file mode 100644
index 00000000000..99e18f42a73
--- /dev/null
+++ b/docs/blog/content/material/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case.en.md
@@ -0,0 +1,405 @@
++++
+title = "A Distributed Database Load Balancing Architecture Based on ShardingSphere: Demo and User Case"
+weight = 87
+chapter = true 
++++
+
+This post introduces how to build a distributed database load-balancing architecture based on ShardingSphere, and the impact of introducing load balancing with a user case.
+
+Finally, a one-stop solution for Apache ShardingSphere distributed databases on the cloud will be presented and demonstrated at the end.
+
+# ShardingSphere-based distributed database load balancing architecture
+
+## ShardingSphere Load Balancing Architecture Essentials
+
+As many of our readers may already know, Apache ShardingSphere is a distributed database ecosystem that transforms any database into a distributed database and enhances it with data sharding, elastic scaling, encryption, and other capabilities.
+
+It consists of two products, ShardingSphere-JDBC and ShardingSphere-Proxy, which can be deployed independently and support hybrid deployments for use with each other. The following figure illustrates the hybrid deployment architecture:
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case1.png)
+
+**ShardingSphere-JDBC Load Balancing Solution**
+
+ShardingSphere-JDBC is a lightweight Java framework with additional services provided in the JDBC layer. ShardingSphere-JDBC simply adds computational operations before the application performs database operations, and the application process still connects directly to the database via the database driver.
+
+As a result, users don’t have to worry about load balancing with ShardingSphere-JDBC, and can focus on how their application is load balanced.
+
+**SharidngSphere-Proxy Load Balancing Solution**
+
+***Deployment Structure***
+
+ShardingSphere-Proxy is a transparent database proxy that provides services to database clients via the database protocol. The following figure shows the for ShardingSphere-Proxy as a standalone deployed process with load balancing on top of it:
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case2.png)
+
+***Load Balancing Solution Essentials***
+
+Some of our community contributors have discussed in detail how to build a ShardingSphere-Proxy cluster, and some have asked about the inconsistent behavior of ShardingSphere-Proxy after load balancing:
+
+- How to build a ShardingSphere-Proxy cluster? https://github.com/apache/shardingsphere/discussions/12593
+- Requests sent by clients through HA-Proxy do not poll multiple instances of ShardingSphere-Proxy: https://github.com/apache/shardingsphere/issues/20016
+
+The key point of ShardingSphere-Proxy cluster load balancing is that the database protocol itself is designed to be stateful. For example, connection authentication status, transaction status, Prepared Statement, etc.
+
+If the load balancing on top of the ShardingSphere-Proxy is unable to understand the database protocol, the only option is to select a four-tier load balancing proxy ShardingSphere-Proxy cluster. In this case, the state of the database connection between the client and ShardingSphere-Proxy is maintained by a specific Proxy instance.
+
+Because the state of the connection itself is maintained in a specific Proxy instance, four-tier load balancing can only achieve connection-level load balancing. Multiple requests for the same database connection cannot be polled to multiple Proxy instances, i.e. request-level load balancing is not possible.
+
+**Note:** This article does not cover the details of four-tier load balancing and seven-tier load balancing.
+
+***Recommendations for the application layer***
+
+Theoretically, there is no functional difference between a client connecting directly to a single ShardingSphere-Proxy or to a ShardingSphere-Proxy cluster via a load-balancing portal. However, there are some differences in the technical implementation and configuration of the different load balancers.
+
+For example, in the case of a direct connection to ShardingSphere-Proxy with no limit on the maximum time a database connection session can be held, some ELB products have a maximum session hold time of 60 minutes at Layer 4. If an idle database connection is closed by a load balancing timeout, but the client is not aware of the passive TCP connection closure, this may cause the application to report an error.
+
+Therefore, in addition to considerations at the load balancing level, there are also measures that the client itself can consider to avoid the impact of introducing load balancing.
+
+***Consider on-demand connection creation for scenarios with long execution intervals***
+
+For example, if a connection’s single instance is created and used continuously, the database connection will be idle most of the time when executing a timed job with a 1-hour interval and a short execution time.
+
+If the client itself is not aware of changes in the connection state, the long idle time increases the uncertainty of the connection state.
+
+For scenarios with long execution intervals, consider creating connections on demand and releasing them after use.
+
+***Consider managing database connections through connection pooling***
+
+General database connection pools have the ability to maintain valid connections, reject failed connections, etc.
+
+Managing database connections through connection pools can reduce the cost of maintaining connections yourself.
+
+***The client considers enabling TCP KeepAlive***
+
+TCP `KeepAlive` configuration is generally supported by clients, e.g:
+
+- MySQL Connector/J supports the configuration of `autoReconnect` or `tcpKeepAlive`, which are not enabled by default.
+- The PostgreSQL JDBC Driver supports the configuration of `tcpKeepAlive`, which is not enabled by default.
+
+Nevertheless, there are some limitations to the way TCP `KeepAlive` can be enabled:
+
+- The client does not necessarily support the configuration of TCP `KeepAlive` or automatic reconnection.
+- The client does not intend to make any code or configuration adjustments.
+- TCP `KeepAlive` is dependent on the operating system implementation and configuration.
+
+# User Case: connection outage due to improper load balancing configuration
+
+A while back, a community user provided feedback that the ShardingSphere-Proxy cluster they deployed was providing services to the public via upper-layer load balancing, and in the process, they found problems with the stability of the connection between their application and ShardingSphere-Proxy.
+
+## Problem Description
+
+For the sake of our case, let’s consider that a user’s production environment uses a 3-node ShardingSphere-Proxy cluster, which serves applications through a cloud vendor’s ELB.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case3.png)
+
+One of the applications is a resident process that executes timed jobs, which are executed hourly and have database operations in the job logic. User feedback is that each time a timed job is triggered, an error is reported in the application log:
+
+```markdown
+send of 115 bytes failed with errno=104 Connection reset by peer
+```
+
+Checking the ShardingSphere-Proxy logs, there are no abnormal messages.
+
+The issue only occurs with timed jobs that execute on an hourly basis, and all other applications access ShardingSphere-Proxy normally.
+
+As the job logic has a retry mechanism, the job executes successfully after each retry, with no impact on the original business.
+
+## Problem Analysis
+
+The reason why the application shows an error is clear: the client is sending data to a closed TCP connection.
+
+Therefore, the troubleshooting goal is to identify the exact reason why the TCP connection was closed.
+
+If you encounter any of the three reasons listed below, we recommend that you perform a network packet capture on both the application and the ShardingSphere-Proxy side within a few minutes before and after the point at which the problem occurs:
+
+- The problem will recur on an hourly basis.
+- The issue is network related.
+- The issue does not affect the user’s real-time operations.
+
+**Packet Capture Phenomenon I**
+
+ShardingSphere-Proxy receives a TCP connection establishment request from the client every 15 seconds, but the client sends an RST to the Proxy immediately after the connection is established with three handshakes.
+
+The client sends an RST to the Proxy without any response after receiving the Server Greeting, or even before the Proxy has sent the Server Greeting.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case4.png)
+
+However, no traffic matching the above behavior was found in the application-side packet capture results.
+
+By consulting the documentation of the ELB used by the user, we found that the above network interaction is how the four-layer health check mechanism of that ELB is implemented. Therefore, this phenomenon is not relevant to the problem in this case.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case5.png)
+
+**Packet Capture Phenomenon II**
+
+The MySQL connection is established between the client and the ShardingSphere-Proxy and the client sends an RST to the Proxy during the TCP connection disconnection phase.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case6.png)
+
+The above packet capture results show that the client first initiated the `COM_QUIT` command to ShardingSphere-Proxy, i.e. the MySQL connection was disconnected by the client, including but not limited to the following possible scenarios:
+
+- The application has finished using the MySQL connection and closed the database connection normally.
+- The application’s database connection to ShardingSphere-Proxy is managed by a connection pool, which performs a release operation for idle connections that have timed out or have exceeded their maximum lifetime.
+
+As the connection is actively closed on the application side, it does not theoretically affect other business operations, unless there is a problem with the application’s logic.
+
+After several rounds of packet analysis, no RSTs were found to have been sent to the client by the ShardingSphere-Proxy in the minutes before and after the problem resurfaced.
+
+Based on the available information, it is possible that the connection between the client and ShardingSphere-Proxy was disconnected earlier, but the packet capture time was limited and did not capture the moment of disconnection.
+
+Since the ShardingSphere-Proxy itself does not have the logic to actively disconnect the client, the problem is being investigated at both the client and ELB levels.
+
+**Client application and ELB configuration check**
+
+Based on user feedback:
+
+- The application's timed jobs are executed hourly, the application does not use a database connection pool, and a database connection is manually maintained and provided for ongoing use by the timed jobs.
+- The ELB is configured with four levels of session hold and a session idle timeout of 40 minutes.
+
+Considering the frequency of execution of timed jobs, we recommend that users modify the ELB session idle timeout to be greater than the execution interval of timed jobs. After the user modifies the ELB timeout to 66 minutes, the Connection reset problem no longer occurs.
+
+If packet capturing is continued during troubleshooting, it is highly likely that the ELB will capture traffic that disconnects the TCP connection at the 40th minute of each hour.
+
+## **Problem Conclusion**
+
+The client reported an error Connection reset by peer Root cause:
+
+The ELB idle timeout was less than the timed task execution interval and the client was idle for longer than the ELB session hold timeout, resulting in the connection between the client and ShardingSphere-Proxy being disconnected by the ELB timeout.
+
+The client sends data to a TCP connection that has been closed by the ELB, resulting in the error Connection reset by peer.
+
+***Timeout simulation experiment***
+
+In this paper, we conduct a simple experiment to verify the performance of the client after a load balancing session timeout, and perform packet capture during the experiment to analyse network traffic to observe the behaviour of load balancing.
+
+***Build a load-balanced ShardingSphere-Proxy clustered environment***
+
+Theoretically, any four-tier load balancing implementation can be the subject of this article, so this article uses `nginx` as a four-tier load balancing technology implementation.
+
+***Configure nginx stream***
+
+The idle timeout is set to 1 minute, i.e. the TCP session is held for a maximum of 1 minute.
+
+```sql
+user  nginx;
+worker_processes  auto;
+
+error_log  /var/log/nginx/error.log notice;
+pid        /var/run/nginx.pid;
+
+events {
+    worker_connections  1024;
+}
+
+stream {
+    upstream shardingsphere {
+        hash $remote_addr consistent;
+
+        server proxy0:3307;
+        server proxy1:3307;
+    }
+
+    server {
+        listen 3306;
+        proxy_timeout 1m;
+        proxy_pass shardingsphere;
+    }
+}
+```
+
+***Construct Docker compose***
+
+```yaml
+version: "3.9"
+services:
+
+  nginx:
+    image: nginx:1.22.0
+    ports:
+      - 3306:3306
+    volumes:
+      - /path/to/nginx.conf:/etc/nginx/nginx.conf
+
+  proxy0:
+    image: apache/shardingsphere-proxy:5.3.0
+    hostname: proxy0
+    ports:
+      - 3307
+
+  proxy1:
+    image: apache/shardingsphere-proxy:5.3.0
+    hostname: proxy1
+    ports:
+      - 3307
+```
+
+***Startup environment***
+
+```bash
+ $ docker compose up -d 
+[+] Running 4/4
+ ⠿ Network lb_default     Created                                                                                                      0.0s
+ ⠿ Container lb-proxy1-1  Started                                                                                                      0.5s
+ ⠿ Container lb-proxy0-1  Started                                                                                                      0.6s
+ ⠿ Container lb-nginx-1   Started            
+```
+
+***Simulation of client-side same-connection based timed tasks***
+
+*Construct client-side deferred SQL execution*
+
+Here the ShardingSphere-Proxy is accessed via Java and MySQL Connector/J.
+
+The logic is roughly as follows:
+
+1. Establish a connection to the ShardingSphere-Proxy and execute a query to the Proxy.
+2. Wait 55 seconds and then execute another query to the Proxy.
+3. Wait 65 seconds and then execute another query to the Proxy.
+
+```java
+public static void main(String[] args) {
+    try (Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306?useSSL=false", "root", "root"); Statement statement = connection.createStatement()) {
+        log.info(getProxyVersion(statement));
+        TimeUnit.SECONDS.sleep(55);
+        log.info(getProxyVersion(statement));
+        TimeUnit.SECONDS.sleep(65);
+        log.info(getProxyVersion(statement));
+    } catch (Exception e) {
+        log.error(e.getMessage(), e);
+    }
+}
+
+private static String getProxyVersion(Statement statement) throws SQLException {
+    try (ResultSet resultSet = statement.executeQuery("select version()")) {
+        if (resultSet.next()) {
+            return resultSet.getString(1);
+        }
+    }
+    throw new UnsupportedOperationException();
+}
+```
+
+***Expected and client-side run results***
+
+Expected results:
+
+1. A client connection to the ShardingSphere-Proxy is established and the first query is successful.
+2. The client’s second query is successful.
+3. The client’s third query results in an error due to a broken TCP connection, as the nginx idle timeout is set to 1 minute.
+
+The execution results are as expected. Due to differences between the programming language and the database driver, the error messages behave differently, but the underlying cause is the same: both are TCP connections have been disconnected.
+
+The logs are shown below:
+
+```sql
+15:29:12.734 [main] INFO icu.wwj.hello.jdbc.ConnectToLBProxy - 5.7.22-ShardingSphere-Proxy 5.1.1
+15:30:07.745 [main] INFO icu.wwj.hello.jdbc.ConnectToLBProxy - 5.7.22-ShardingSphere-Proxy 5.1.1
+15:31:12.764 [main] ERROR icu.wwj.hello.jdbc.ConnectToLBProxy - Communications link failure
+The last packet successfully received from the server was 65,016 milliseconds ago. The last packet sent successfully to the server was 65,024 milliseconds ago.
+        at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
+        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
+        at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1201)
+        at icu.wwj.hello.jdbc.ConnectToLBProxy.getProxyVersion(ConnectToLBProxy.java:28)
+        at icu.wwj.hello.jdbc.ConnectToLBProxy.main(ConnectToLBProxy.java:21)
+Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
+
+The last packet successfully received from the server was 65,016 milliseconds ago. The last packet sent successfully to the server was 65,024 milliseconds ago.
+        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
+        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
+        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
+        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
+        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
+        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
+        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
+        at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
+        at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
+        at com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:581)
+        at com.mysql.cj.protocol.a.NativeProtocol.checkErrorMessage(NativeProtocol.java:761)
+        at com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:700)
+        at com.mysql.cj.protocol.a.NativeProtocol.sendQueryPacket(NativeProtocol.java:1051)
+        at com.mysql.cj.protocol.a.NativeProtocol.sendQueryString(NativeProtocol.java:997)
+        at com.mysql.cj.NativeSession.execSQL(NativeSession.java:663)
+        at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1169)
+        ... 2 common frames omitted
+Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
+        at com.mysql.cj.protocol.FullReadInputStream.readFully(FullReadInputStream.java:67)
+        at com.mysql.cj.protocol.a.SimplePacketReader.readHeaderLocal(SimplePacketReader.java:81)
+        at com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:63)
+        at com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:45)
+        at com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:52)
+        at com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:41)
+        at com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:54)
+        at com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:44)
+        at com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:575)
+        ... 8 common frames omitted
+```
+
+***Analysis of packet capture results***
+
+The packet capture results show that after the connection idle timeout, nginx simultaneously disconnects from the client and the Proxy over TCP. However, as the client is not aware of this, nginx returns an RST after sending the command.
+
+After the `nginx` connection idle timeout, the TCP disconnection process with the Proxy is completed normally, and the Proxy is completely unaware when the client sends subsequent requests using the disconnected connection.
+
+Analyze the following packet capture results:
+
+- Numbers 1–44 are the interaction between the client and the ShardingSphere-Proxy to establish a MySQL connection.
+- Numbers 45–50 are the first queries performed by the client.
+- Numbers 55–60 are the second query executed 55 seconds after the first query is executed by the client.
+- Numbers 73–77 are the TCP connection disconnection processes initiated by nginx to both the client and ShardingSphere-Proxy after the session times out.
+- Numbers 78–79 are the third query executed 65 seconds after the client executes the second query, and Connection Reset occurs.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case7.png)
+
+# ShardingSphere on Cloud One-Stop Solution
+
+Deploying and maintaining ShardingSphere-Proxy clusters and load balancing manually can be labor intensive and time consuming. To address this issue, Apache ShardingSphere has launched ShardingSphere on Cloud, a collection of cloud-based solutions.
+
+ShardingSphere-on-Cloud includes automated deployment scripts to virtual machines in cloud environments such as AWS, GCP and Alibaba Cloud, such as CloudFormation Stack templates, Terraform one-click deployment scripts, Helm Charts in Kubernetes cloud-native environments, Operator.
+
+ShardingSphere-on-Cloud includes the following tools: Helm Charts, Operator, automatic horizontal scaling, and other tools in a Kubernetes cloud-native environment, as well as a variety of hands-on content on high availability, observability, security compliance, and more.
+
+The new cloud project provides the following capabilities:
+
+- Helm Charts-based ShardingSphere-Proxy for one-click deployment in Kubernetes environments.
+- Operator-based ShardingSphere-Proxy for one-click deployment and automated maintenance in Kubernetes environments.
+- AWS CloudFormation-based ShardingSphere-Proxy for rapid deployment.
+- Terraform-based rapid deployment of ShardingSphere-Proxy in AWS environments.
+
+This post briefly demonstrates one of the fundamental capabilities of ShardingSphere on Cloud: one-click deployment of ShardingSphere-Proxy clusters in Kubernetes using Helm Charts.
+
+1. Use the following 3 line command to create a 3-node ShardingSphere-Proxy cluster within a Kubernetes cluster with the default configuration and serve it through the Service.
+
+```bash
+helm repo add shardingsphere https://apache.github.io/shardingsphere-on-cloud
+helm repo update
+helm install shardingsphere-proxy shardingsphere/apache-shardingsphere-proxy-charts -n shardingsphere
+```
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case8.png)
+
+2. The application can access the ShardingSphere-Proxy cluster via the svc domain.
+
+```bash
+kubectl run mysql-client --image=mysql:5.7.36 --image-pull-policy=IfNotPresent -- sleep 300
+kubectl exec -i -t mysql-client -- mysql -h shardingsphere-proxy-apache-shardingsphere-proxy.shardingsphere.svc.cluster.local -P3307 -uroot -proot
+```
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case9.png)
+
+This is just a demonstration of one of the basic capabilities of ShardingSphere on Cloud.
+
+For more advanced features that are available in production environments, please refer to the official ShardingSphere-on-Cloud [documentation](https://shardingsphere.apache.org/oncloud/current/cn/overview/).
+
+# Relevant Links
+
+**🔗** [**ShardingSphere Official Website**](https://shardingsphere.apache.org/)
+
+**🔗** [**ShardingSphere Official Project Repo**](https://github.com/apache/shardingsphere)
+
+**🔗** [**ShardingSphere-on-Cloud Official Website**](https://shardingsphere.apache.org/oncloud/)
+
+**🔗**[ **ShardingSphere-on-Cloud Project Repo**](https://github.com/apache/shardingsphere-on-cloud)
+
+**🔗** [**ShardingSphere Twitter**](https://twitter.com/ShardingSphere)
+
+**🔗** [**ShardingSphere Slack**](https://join.slack.com/t/apacheshardingsphere/shared_invite/zt-sbdde7ie-SjDqo9~I4rYcR18bq0SYTg)
diff --git a/docs/blog/content/material/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive.en.md b/docs/blog/content/material/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive.en.md
new file mode 100644
index 00000000000..e4e4092807a
--- /dev/null
+++ b/docs/blog/content/material/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive.en.md
@@ -0,0 +1,440 @@
++++
+title = "Dynamic Data Masking | ShardingSphere 5.3.1 Deep Dive"
+weight = 88
+chapter = true 
++++
+
+With increased focus placed on user data protection and the introduction of privacy laws or data protection regulations such as [GDPR](https://gdpr-info.eu/), being compliant in terms of digital personal privacy is now of paramount importance.
+
+Traditional applications generally lack personal data protection. Data masking enables data returned by production databases to be specially masked, encrypted, hidden, and audited according to the users' role, responsibility, and other defined rules without having to make any changes to the data.
+
+This allows you to ensure that employees, external users, operations, part-time employees, partners, data analysts, developers, testers, and consultants have the appropriate degree of access to sensitive data in production environments.
+
+Based on industry experience, there are two major types of data masking. One is static data masking and the other is dynamic data masking.
+
+Static data masking refers to masking, encrypting, or replacing sensitive data with a masking algorithm for database systems through the task. It saves the masked data to the target location.
+
+Dynamic data masking is more flexible. Dynamic data masking happens at runtime based on each query. This way, there doesn't need to be a second data source to store the masked data dynamically.
+
+[ShardingSphere 5.3.1 provides a dynamic data masking function](https://shardingsphere.apache.org/document/4.1.1/en/features/orchestration/encrypt/). Users query data through ShardingSphere, while ShardingSphere processes data with a masking algorithm before returning results.
+
+The whole process is based on masking rules configured by users. The masked data is then delivered to users.
+
+# Methods
+
+## Masking & Microkernel
+
+On account of the ShardingSphere microkernel and pluggable architecture, the data masking function only needs to implement SPI, the resulting merger, to achieve the flexible extension of functions.
+
+As shown in the figure below, the ShardingSphere microkernelalready includes core logic like `SQL Parser`, `SQL router`, `SQL executor`. The dynamic data masking function provided by ShardingSphere 5.3.1 is only an enhancement of the query results of the other ShardingSphere components.
+
+This means that users only need to implement `ResultDecoratorEngine` and `ResultDecorator` in the merger to achieve the function.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive1.png)
+
+In order to implement the data masking function, the `shardingsphere-mask` module is added to the features. This module contains `shardingsphere-mask-api`, `shardingsphere-mask-core` and `shardingsphere-mask-distsql`. The functions of each module are as follows:
+
+- `shardingsphere-mask-api`:data masking API module, including `Rule` configuration with data masking function and masking algorithm SPI interface.
+- `shardingsphere-mask-core`:the core data masking module, including `Rule` initialization logic, masking algorithm implementation, and resulting merger decorator implementation logic.
+- `shardingsphere-mask-distsql`:DistSQL module for data masking allowing users to dynamically modify masking rules through DistSQL.
+
+In addition to the kernel process, data masking's position in the ShardingSphere kernel also deserves mention.
+
+ShardingSphere's powerful pluggable architecture allows us to arbitrarily assemble kernel functions, including the newly added data masking function.
+
+Users can use the function alone, or with sharding, encryption, and other functions to achieve a more complete distributed database solution.
+
+The following figure shows the relationship between the current functions of the ShardingSphere kernel, which can be generally divided into three levels: Column Level, Table Level, and Database Level.
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive2.png)
+
+Column Level includes data encryption and data masking for improving columns. Table Level includes data sharding and built-in single table management.
+
+Functions at the Database Level represent the bulk of the ecosystem, including the dual write function provided by [SphereEx](https://www.sphere-ex.com/), as well as read/write splitting, high-availability database discovery, and shadow database provided by the open-source ShardingSphere. They're all related to database traffic governance.
+
+ShardingSphere processes according to the three levels levels, and within each level it processes according to the Order.
+
+For example: if you use both data encryption and data masking, the system preferentially processes the encryption logic, decrypts the ciphertext stored in the database, and then uses the masking algorithm to process data masking.
+
+## Masking YAML API & DistSQL
+
+After introducing the relationship between masking and microkernel, let's draw our eyes to the masking API and DistSQL. Users can configure masking rules based on YAML or using DistSQL.
+
+First, let's take a look at how the YAML API is configured. The user just needs to configure the data masking column and algorithm in tables under `- !MASK`. The name of the algorithm defined by `maskAlgorithm` must be the same as the name in it.
+
+- `maskAlgorithm`: specifies the masking algorithm, and the mask feature performs data processing according to the masking algorithm.
+
+The YAML API configuration of the mask feature is as follows:
+
+```yaml
+databaseName: mask_db
+
+dataSources:
+  ds_0:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 123456
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+  ds_1:
+    url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false
+    username: root
+    password: 123456
+    connectionTimeoutMilliseconds: 30000
+    idleTimeoutMilliseconds: 60000
+    maxLifetimeMilliseconds: 1800000
+    maxPoolSize: 50
+    minPoolSize: 1
+        
+# MASK rules configuration
+rules:
+- !MASK
+  tables:
+    t_user:
+      columns:
+        password:
+          maskAlgorithm: md5_mask
+        email:
+          maskAlgorithm: mask_before_special_chars_mask
+        telephone:
+          maskAlgorithm: keep_first_n_last_m_mask
+
+  maskAlgorithms:
+    md5_mask:
+      type: MD5
+    mask_before_special_chars_mask:
+      type: MASK_BEFORE_SPECIAL_CHARS
+      props:
+        special-chars: '@'
+        replace-char: '*'
+    keep_first_n_last_m_mask:
+      type: KEEP_FIRST_N_LAST_M
+      props:
+        first-n: 3
+        last-m: 4
+        replace-char: '*'
+```
+
+In addition, ShardingSphere 5.3.1 also provides DistSQL related masking rules to meet users' needs for dynamically updating masking rules during the running stage.
+
+The data masking DistSQL syntax is as follows, containing DistSQL statements that are commonly used to create, alter, drop, and show masking rules.
+
+```sql
+-- Create masking rules
+CREATE MASK RULE t_user (
+    COLUMNS(
+        (NAME=password, TYPE(NAME='MD5')),
+        (NAME=email, TYPE(NAME='MASK_BEFORE_SPECIAL_CHARS', PROPERTIES("special-chars"="@", "replace-char"="*"))),
+        (NAME=telephone, TYPE(NAME='KEEP_FIRST_N_LAST_M', PROPERTIES("first-n"=3, "last-m"=4, "replace-char"="*")))
+    )
+);
+
+-- Alter masking rules
+ALTER MASK RULE t_user (
+    COLUMNS(
+        (NAME=password, TYPE(NAME='MD5', PROPERTIES("salt"="123abc"))),
+        (NAME=email, TYPE(NAME='MASK_BEFORE_SPECIAL_CHARS', PROPERTIES("special-chars"="@", "replace-char"="*"))),
+        (NAME=telephone, TYPE(NAME='TELEPHONE_RANDOM_REPLACE', PROPERTIES("network-numbers"="123,180")))
+    )
+);
+
+-- Drop masking rule
+DROP MASK RULE t_user;
+
+-- Show masking rule
+SHOW MASK RULES FROM mask_db;
+```
+
+For detailed DistSQL syntax, see [DistSQL Documentation — Data Masking](https://shardingsphere.apache.org/document/5.3.1/en/user-manual/shardingsphere-proxy/distsql/syntax/rdl/rule-definition/mask/create-mask-rule/).
+
+## Built-in Masking Algorithm
+
+The ShardingSphere 5.3.1 release also includes a large number of built-in masking algorithms, which are implemented based on the `MaskAlgorithm` SPI interface, and users can flexibly extend the algorithm according to their business requirements.
+
+```java
+/**
+ * Mask algorithm.
+ * 
+ * @param <I> type of plain value
+ * @param <O> type of mask value
+ */
+public interface MaskAlgorithm<I, O> {
+    
+    /**
+     * Mask.
+     *
+     * @param plainValue plain value
+     * @return mask value
+     */
+    O mask(I plainValue);
+}
+```
+
+Built-in masking algorithms can be mainly divided into three types, hash mask, cover mask, and replace mask. The specific algorithms are listed as follows:
+
+![img](https://shardingsphere.apache.org/blog/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive3.png)
+
+The data masking algorithm is still in continuous improvement. For more about the algorithm parameters, please refer to [Data Masking Algorithm](https://shardingsphere.apache.org/document/5.3.1/en/user-manual/common-config/builtin-algorithm/mask/).
+
+We welcome everyone to participate and contribute to improving the data masking algorithm together.
+
+# Data Masking in Practice
+
+In the last section, we will take a practical look at data masking.
+
+For a company's internal sensitive data, data masking and data encryption are used together. The database stores data with data encryption to avoid security problems caused by loss of data.
+
+During the data query, data decryption and data masking are run according to the rules to avoid the direct display of sensitive data.
+
+This post showcases a scenario where data masking and data encryption are performed together and uses DistSQL for a dynamic update to show the actual effect of data masking.
+
+First, download ShardingSphere Proxy 5.3.1, and configure `server.yaml` for the first operation, and connect to the Proxy with `mysql -u root -h 127.0.0.1 -P 3307 -p c-A`, and run `CREATE DATABASE mask_db` to create a data masking logic database.
+
+```sql
+-- Create a data masking logic database
+CREATE DATABASE mask_db;
+-- Switch to mask_db
+USE mask_db;
+```
+
+After creating the logic database, DistSQL can be used to register the storage resource and initialize the masking and encryption rules.
+
+```sql
+-- Register storage resource
+REGISTER STORAGE UNIT ds_0 (
+    HOST="127.0.0.1",
+    PORT=3306,
+    DB="demo_ds_0",
+    USER="root",
+    PASSWORD="123456",
+    PROPERTIES("maximumPoolSize"=10)
+), ds_1 (
+    HOST="127.0.0.1",
+    PORT=3306,
+    DB="demo_ds_1",
+    USER="root",
+    PASSWORD="123456",
+    PROPERTIES("maximumPoolSize"=10)
+);
+
+-- Create masking rules
+CREATE MASK RULE t_user (
+    COLUMNS(
+        (NAME=password, TYPE(NAME='MD5')),
+        (NAME=email, TYPE(NAME='MASK_BEFORE_SPECIAL_CHARS', PROPERTIES("special-chars"="@", "replace-char"="*"))),
+        (NAME=telephone, TYPE(NAME='KEEP_FIRST_N_LAST_M', PROPERTIES("first-n"=3, "last-m"=4, "replace-char"="*")))
+    )
+);
+
+-- Create encryption rules
+CREATE ENCRYPT RULE t_user (
+    COLUMNS(
+        (NAME=user_name, CIPHER=user_name_cipher, ENCRYPT_ALGORITHM(TYPE(NAME='AES', PROPERTIES('aes-key-value'='123456abc')))),
+        (NAME=password, CIPHER =password_cipher, ENCRYPT_ALGORITHM(TYPE(NAME='AES', PROPERTIES('aes-key-value'='123456abc')))),
+        (NAME=email, CIPHER =email_cipher, ENCRYPT_ALGORITHM(TYPE(NAME='AES', PROPERTIES('aes-key-value'='123456abc')))),
+        (NAME=telephone, CIPHER =telephone_cipher, ENCRYPT_ALGORITHM(TYPE(NAME='AES', PROPERTIES('aes-key-value'='123456abc'))))
+    )
+);
+```
+
+After the masking and encryption rules are created, run the `SHOW` statement in DistSQL to view the masking and encryption rules:
+
+```mysql
+-- Show masking rules
+mysql> SHOW MASK RULES FROM mask_db;
++--------+-----------+---------------------------+-----------------------------------+
+| table  | column    | algorithm_type            | algorithm_props                   |
++--------+-----------+---------------------------+-----------------------------------+
+| t_user | password  | MD5                       |                                   |
+| t_user | email     | MASK_BEFORE_SPECIAL_CHARS | replace-char=*,special-chars=@    |
+| t_user | telephone | KEEP_FIRST_N_LAST_M       | first-n=3,replace-char=*,last-m=4 |
++--------+-----------+---------------------------+-----------------------------------+
+3 rows in set (0.01 sec)
+
+-- Show encryption rules
+mysql> SHOW ENCRYPT RULES FROM mask_db;
++--------+--------------+------------------+--------------+-----------------------+-------------------+----------------+-------------------------+---------------------+----------------------+-----------------+------------------+--------------------------+
+| table  | logic_column | cipher_column    | plain_column | assisted_query_column | like_query_column | encryptor_type | encryptor_props         | assisted_query_type | assisted_query_props | like_query_type | like_query_props | query_with_cipher_column |
++--------+--------------+------------------+--------------+-----------------------+-------------------+----------------+-------------------------+---------------------+----------------------+-----------------+------------------+--------------------------+
+| t_user | user_name    | user_name_cipher |              |                       |                   | AES            | aes-key-value=123456abc |                     |                      |                 |                  | true                     |
+| t_user | password     | password_cipher  |              |                       |                   | AES            | aes-key-value=123456abc |                     |                      |                 |                  | true                     |
+| t_user | email        | email_cipher     |              |                       |                   | AES            | aes-key-value=123456abc |                     |                      |                 |                  | true                     |
+| t_user | telephone    | telephone_cipher |              |                       |                   | AES            | aes-key-value=123456abc |                     |                      |                 |                  | true                     |
++--------+--------------+------------------+--------------+-----------------------+-------------------+----------------+-------------------------+---------------------+----------------------+-----------------+------------------+--------------------------+
+4 rows in set (0.01 sec)
+```
+
+After creating the rules, we create the following `t_user` table and perform data initialization:
+
+```sql
+DROP TABLE IF EXISTS t_user;
+
+CREATE TABLE t_user (user_id INT PRIMARY KEY, user_name VARCHAR(50) NOT NULL, password VARCHAR(50) NOT NULL, email VARCHAR(50) NOT NULL, telephone CHAR(50) NOT NULL, creation_date DATE NOT NULL);
+
+INSERT INTO t_user(user_id, user_name, password, email, telephone, creation_date) values(10, 'zhangsan', '111111', 'zhangsan@gmail.com', '12345678900', '2017-08-08'),
+(11, 'lisi', '222222', 'lisi@gmail.com', '12345678901', '2017-08-08'),
+(12, 'wangwu', '333333', 'wangwu@gmail.com', '12345678902', '2017-08-08'),
+(13, 'zhaoliu', '444444', 'zhaoliu@gmail.com', '12345678903', '2017-08-08'),
+(14, 'zhuqi', '555555', 'zhuqi@gmail.com', '12345678904', '2017-08-08'),
+(15, 'liba', '666666', 'liba@gmail.com', '12345678905', '2017-08-08'),
+(16, 'wangjiu', '777777', 'wangjiu@gmail.com', '12345678906', '2017-08-08'),
+(17, 'zhuda', '888888', 'zhuda@gmail.com', '12345678907', '2017-08-08'),
+(18, 'suner', '999999', 'suner@gmail.com', '12345678908', '2017-08-08'),
+(19, 'zhousan', '123456', 'zhousan@gmail.com', '12345678909', '2017-08-08'),
+(20, 'tom', '234567', 'tom@gmail.com', '12345678910', '2017-08-08'),
+(21, 'kobe', '345678', 'kobe@gmail.com', '12345678911', '2017-08-08'),
+(22, 'jerry', '456789', 'jerry@gmail.com', '12345678912', '2017-08-08'),
+(23, 'james', '567890', 'james@gmail.com', '12345678913', '2017-08-08'),
+(24, 'wade', '012345', 'wade@gmail.com', '12345678914', '2017-08-08'),
+(25, 'rose', '000000', 'rose@gmail.com', '12345678915', '2017-08-08'),
+(26, 'bosh', '111222', 'bosh@gmail.com', '12345678916', '2017-08-08'),
+(27, 'jack', '222333', 'jack@gmail.com', '12345678917', '2017-08-08'),
+(28, 'jordan', '333444', 'jordan@gmail.com', '12345678918', '2017-08-08'),
+(29, 'julie', '444555', 'julie@gmail.com', '12345678919', '2017-08-08');
+```
+
+After data initialization, we can directly connect to the MySQL database through `MySQL -u root -h 127.0.0.1 -P 3306 -p c-A` to check the data stored in the table `t_user` of the underlying database.
+
+It can be seen that MySQL stores encrypted data, and sensitive data is effectively protected in the database storage layer.
+
+```mysql
+mysql> SELECT * FROM t_user;
++---------+--------------------------+--------------------------+----------------------------------------------+--------------------------+---------------+
+| user_id | user_name_cipher         | password_cipher          | email_cipher                                 | telephone_cipher         | creation_date |
++---------+--------------------------+--------------------------+----------------------------------------------+--------------------------+---------------+
+|      10 | sVq8Lmm+j6bZE5EKSilJEQ== | aQol0b6th65d0aXe+zFPsQ== | WM0fHOH91JNWnHTkiqBdyNmzk4uJ7CCz4mB1va9Ya1M= | kLjLJIMnfyHT2nA+viaoaQ== | 2017-08-08    |
+|      11 | fQ7IzBxKVuNHtUF6h6WSBg== | wuhmEKgdgrWQYt+Ev0hgGA== | svATu3uWv9KfiloWJeWx3A==                     | 0kDFxndQdzauFwL/wyCsNQ== | 2017-08-08    |
+|      12 | AQRWSlufQPog/b64YRhu6Q== | x7A+2jq9B6DSOSFtSOibdA== | nHJv9e6NiClIuGHOjHLvCAq2ZLhWcqfQ8/EQnIqMx+g= | a/SzSJLapt5iBXvF2c9ycw== | 2017-08-08    |
+|      13 | 5NqS4YvpT+mHBFqZOZ3QDA== | zi6b4xYRjjV+bBk2R4wB+w== | MLBZczLjriUXvg3aM5QPTxMJbLjNh8yeNrSNBek/VTw= | b6VVhG+F6ujG8IMUZJAIFg== | 2017-08-08    |
+|      14 | qeIY9od3u1KwhjihzLQUTQ== | 51UmlLAC+tUvdOAj8CjWfQ== | JCmeNdPyrKO5BW5zvhAA+g==                     | f995xinpZdKMVU5J5/yv3w== | 2017-08-08    |
+|      15 | VbNUtguwtpeGhHGnPJ3aXg== | +3/5CVbqoKhg3sqznKTFFQ== | T+X+e3Q3+ZNIXXmg/80uxg==                     | GETj+S6DrO042E7NuBXLBQ== | 2017-08-08    |
+|      16 | U0/Ao/w1u7L5avR3fAH2Og== | jFfFMYxv02DjaFRuAoCDGw== | RNW/KRq5HeL2YTfAdXSyARMJbLjNh8yeNrSNBek/VTw= | +lbvjJwO7VO4HUKc0Mw0NA== | 2017-08-08    |
+|      17 | zb1sgBigoMi7JPSoY4bAVw== | VFIjocgjujJCJc6waWXqJA== | 1vF/ET3nBxt7T7vVfAndZQ==                     | wFvs5BH6OikgveBeTEBwsQ== | 2017-08-08    |
+|      18 | rJzNIrFEnx296kW+N1YmMw== | LaODSKGyR7vZ1IvmBOe9vA== | 5u4GIQkJsWRmnJHWaHNSjg==                     | uwqm2O1Lv2tNTraJX1ym7Q== | 2017-08-08    |
+|      19 | qHwpQ9kteL8VX6iTUhNdbQ== | MyOShk4kjRnds7CZfU5NCw== | HmYCo7QBfJ2E0EvaGHBCOBMJbLjNh8yeNrSNBek/VTw= | YLNQuuUPMGA21nhKWPzzsg== | 2017-08-08    |
+|      20 | qCCmvf7OWRxbVbtLb0az1g== | fzdTMkzpBvgNYmKSQAp8Fg== | gOoP4Mf0P4ISOJp6A4sRmg==                     | l4xa4HwOfs/jusoJon9Wzw== | 2017-08-08    |
+|      21 | IYJ1COaRQ0gSjWMC/UAeMg== | 1uEDMeYh2jstbOf6kx/cqw== | tikMAFiQ37u2VgWqUT38Eg==                     | rGpr30UXfczXjCjdvPN+BA== | 2017-08-08    |
+|      22 | 7wvZZ7NVHgk6m1vB/sTC1Q== | OirN3gvz9uBnrq88nfa1wQ== | T7K/Uz1O2m+3xvB0+c4nGQ==                     | 7+fCU+VbQZKgLJXZPTTegA== | 2017-08-08    |
+|      23 | SbVQWl8JbnxflCfGJ7KZdA== | hWVVYdkdTUTgm08haeq+tw== | Uk3ju6GteCD1qEHns5ZhKA==                     | DpnV86FZefwBRmIAVBh2gg== | 2017-08-08    |
+|      24 | fx7OfSAYqVpjNa7LoKhXvw== | N2W9ijAXNkBxhkvJiIwp0A== | lAAGItVLmb1H69++1MDrIA==                     | QrE62wAb8B+2cEPcs4Lm1Q== | 2017-08-08    |
+|      25 | wH3/LdWShD9aCb8eCIm3Tg== | GDixtt6NzPOVv6H0dmov5g== | T1yfJSyVxumZUfkDnmUQxA==                     | iU+AsGczboCRfU+Zr7mcpw== | 2017-08-08    |
+|      26 | GgJQTndbxyBZ2tECS8SmqQ== | gLgVFLFIyyKwdQCXaw78Ag== | O+JIn9XZ3yq6RnKElHuqlA==                     | kwYlbu9aF7ndvMTcj8QBSg== | 2017-08-08    |
+|      27 | lv8w8g32kuTXNvSUUypOig== | 8i0YH2mn6kXSyvBjM5p+Yg== | gqRoJF5S66SvBalc2RCo1A==                     | 2ob/3UYqRsZA5VdScnaWxQ== | 2017-08-08    |
+|      28 | P9YCbFvWCIhcS99KyKH2zA== | PRrI4z4FrWwLvcHPx9g4og== | y8q31Jj4PFSyZHiLVIxKEQq2ZLhWcqfQ8/EQnIqMx+g= | kDF2za26uOerlNYWYHRT2Q== | 2017-08-08    |
+|      29 | 5wu9XvlJAVtjKijhxt6SQQ== | O4pgkLgz34N+C4bIUOQVnA== | UH7ihg16J61Np/EYMQnXIA==                     | z2hbJQD4dRkVVITNxAac5Q== | 2017-08-08    |
++---------+--------------------------+--------------------------+----------------------------------------------+--------------------------+---------------+
+20 rows in set (0.00 sec)
+```
+
+After confirming the effect of data encryption, we conduct a simple test on the data masking function.
+
+The following `CASE` includes `simple SELECT query`, `join query`, `subquery` and other daily used operation statements. It can be seen that the password is masked with MD5 hash, email is masked with `MASK_BEFORE_SPECIAL_CHARS` and telephone is masked with `KEEP_FIRST_N_LAST_M`.
+
+```mysql
+-- Simple SELECT query
+mysql> SELECT * FROM t_user WHERE user_id = 10;
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+| user_id | user_name | password                         | email              | telephone   | creation_date |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+|      10 | zhangsan  | 96e79218965eb72c92a549dd5a330112 | ********@gmail.com | 123****8900 | 2017-08-08    |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+1 row in set (0.01 sec)
+
+-- Join query
+mysql> SELECT u1.* FROM t_user u1 INNER JOIN t_user u2 ON u1.user_id = u2.user_id WHERE u1.user_id = 10;
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+| user_id | user_name | password                         | email              | telephone   | creation_date |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+|      10 | zhangsan  | 96e79218965eb72c92a549dd5a330112 | ********@gmail.com | 123****8900 | 2017-08-08    |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+1 row in set (0.05 sec)
+
+-- Subquery
+mysql> SELECT * FROM (SELECT * FROM t_user) temp WHERE temp.user_id = 10;
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+| user_id | user_name | password                         | email              | telephone   | creation_date |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+|      10 | zhangsan  | 96e79218965eb72c92a549dd5a330112 | ********@gmail.com | 123****8900 | 2017-08-08    |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+1 row in set (0.03 sec)
+
+-- Subquery with join
+mysql> SELECT * FROM (SELECT u1.* FROM t_user u1 INNER JOIN t_user u2 ON u1.user_id = u2.user_id) temp WHERE temp.user_id < 15;
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+| user_id | user_name | password                         | email              | telephone   | creation_date |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+|      10 | zhangsan  | 96e79218965eb72c92a549dd5a330112 | ********@gmail.com | 123****8900 | 2017-08-08    |
+|      11 | lisi      | e3ceb5881a0a1fdaad01296d7554868d | ****@gmail.com     | 123****8901 | 2017-08-08    |
+|      12 | wangwu    | 1a100d2c0dab19c4430e7d73762b3423 | ******@gmail.com   | 123****8902 | 2017-08-08    |
+|      13 | zhaoliu   | 73882ab1fa529d7273da0db6b49cc4f3 | *******@gmail.com  | 123****8903 | 2017-08-08    |
+|      14 | zhuqi     | 5b1b68a9abf4d2cd155c81a9225fd158 | *****@gmail.com    | 123****8904 | 2017-08-08    |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+5 rows in set (0.03 sec)
+```
+
+We modify the masking rules using DistSQL, adding the optional parameter salt to the MD5 hash masking used for the password, and changing the algorithm for the telephone field to the `TELEPHONE_RANDOM_REPLACE` data masking algorithm.
+
+```sql
+ALTER MASK RULE t_user (
+    COLUMNS(
+        (NAME=password, TYPE(NAME='MD5', PROPERTIES("salt"="123abc"))),
+        (NAME=email, TYPE(NAME='MASK_BEFORE_SPECIAL_CHARS', PROPERTIES("special-chars"="@", "replace-char"="*"))),
+        (NAME=telephone, TYPE(NAME='TELEPHONE_RANDOM_REPLACE', PROPERTIES("network-numbers"="123,180")))
+    )
+);
+```
+
+After the modification, we conduct the query again. We can see that due to the change of password salting, the result of the MD5 hash masking of the password field was changed.
+
+While the telephone random replace data masking algorithm is used in the telephone field, the masking result is also randomly generated after the number segment.
+
+```mysql
+mysql> SELECT * FROM t_user WHERE user_id = 10;
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+| user_id | user_name | password                         | email              | telephone   | creation_date |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+|      10 | zhangsan  | 554555c0eaca7aeecada758122efd640 | ********@gmail.com | 12383015546 | 2017-08-08    |
++---------+-----------+----------------------------------+--------------------+-------------+---------------+
+1 row in set (0.01 sec)
+```
+
+Finally, we run `DROP MASK RULE t_user;` to delete the masking rule. The original plaintext can be seen if we query again.
+
+```mysql
+mysql> SELECT * FROM t_user WHERE user_id = 10;
++---------+-----------+----------+--------------------+-------------+---------------+
+| user_id | user_name | password | email              | telephone   | creation_date |
++---------+-----------+----------+--------------------+-------------+---------------+
+|      10 | zhangsan  | 111111   | zhangsan@gmail.com | 12345678900 | 2017-08-08    |
++---------+-----------+----------+--------------------+-------------+---------------+
+1 row in set (0.00 sec)
+```
+
+# Conclusion
+
+The newly added dynamic data masking function of Apache ShardingSphere 5.3.1 is a further enhancement to ShardingSphere's data security approach.
+
+In the future, our community data masking is considering combining data masking with user rights, SQL audit, and other functions.
+
+We welcome interested readers to join our community to contribute to improving the data masking function of Apache ShardingSphere.
+
+## Author
+
+Duan Zhengqiang, is a senior middleware engineer at SphereEx & Apache ShardingSphere PMC.
+
+Zhengqiang started to contribute to Apache ShardingSphere middleware in 2018 and played a leading role in sharding practices dealing with massive amounts data.
+
+With rich practical experience, he loves open-source and is willing to contribute to a variety of projects. He currently focuses on the development of Apache ShardingSphere kernel module.
+
+## Relevant Links
+
+🔗 [ShardingSphere Official Website](https://shardingsphere.apache.org/)
+
+🔗 [ShardingSphere Official Project Repo](https://github.com/apache/shardingsphere)
+
+🔗 [ShardingSphere Twitter](https://twitter.com/ShardingSphere)
+
+🔗 [ShardingSphere Slack](https://join.slack.com/t/apacheshardingsphere/shared_invite/zt-sbdde7ie-SjDqo9~I4rYcR18bq0SYTg)
\ No newline at end of file
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case1.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case1.png
new file mode 100644
index 00000000000..088791199ed
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case1.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case2.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case2.png
new file mode 100644
index 00000000000..435a257fcdb
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case2.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case3.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case3.png
new file mode 100644
index 00000000000..435a257fcdb
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case3.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case4.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case4.png
new file mode 100644
index 00000000000..061fe7e133b
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case4.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case5.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case5.png
new file mode 100644
index 00000000000..af86f29ebea
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case5.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case6.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case6.png
new file mode 100644
index 00000000000..c556483fe17
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case6.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case7.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case7.png
new file mode 100644
index 00000000000..e9cf9069ab4
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case7.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case8.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case8.png
new file mode 100644
index 00000000000..cc735adcce6
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case8.png differ
diff --git a/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case9.png b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case9.png
new file mode 100644
index 00000000000..71b777b3c09
Binary files /dev/null and b/docs/blog/static/img/2023_02_15_A_Distributed_Database_Load_Balancing_Architecture_Based_on_ShardingSphere_Demo_&_User_Case9.png differ
diff --git a/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive1.png b/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive1.png
new file mode 100644
index 00000000000..b7d0902756a
Binary files /dev/null and b/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive1.png differ
diff --git a/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive2.png b/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive2.png
new file mode 100644
index 00000000000..539df316314
Binary files /dev/null and b/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive2.png differ
diff --git a/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive3.png b/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive3.png
new file mode 100644
index 00000000000..467b8ea5c81
Binary files /dev/null and b/docs/blog/static/img/2023_02_17_Dynamic_Data_Masking_ShardingSphere_5.3.1_Deep_Dive3.png differ