-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create doc: Synchronize between two clusters #1204
Merged
whitewum
merged 4 commits into
vesoft-inc:master
from
randomJoe211:create-cluster-replication-doc
Apr 1, 2022
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
4f71117
Create doc: Synchronize between two clusters
randomJoe211 ed1843e
Update replication-between-clusters.md
randomJoe211 2049fe2
Add instruction about synchronization topology
randomJoe211 bdd655f
Update replication-between-clusters.md
randomJoe211 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
378 changes: 378 additions & 0 deletions
378
docs-2.0/synchronization-and-migration/replication-between-clusters.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,378 @@ | ||
# Synchronize between two clusters | ||
|
||
Nebula Graph supports data synchronization from a primary to a secondary cluster in almost real-time. It applies to scenarios such as disaster recovery and load balancing, and helps reduce the risk of data loss and enhance data security. | ||
|
||
!!! enterpriseonly | ||
|
||
This feature applies to the Enterprise Edition only. | ||
|
||
## Synchronization workflow | ||
|
||
The synchronization works as follows: | ||
|
||
![replication between clusters](https://docs-cdn.nebula-graph.com.cn/figures/replication-between-clusters.png) | ||
|
||
1. The primary cluster sends any data written into it to the Meta listener or the Storage listener. | ||
2. The listener sends the data to the drainer. | ||
3. The drainer sends the data to the partitions of the secondary cluster through the Meta client or the Storage client. | ||
|
||
## Applicable Scenarios | ||
|
||
- Remote disaster recovery: Data synchronization enables cross-room or cross-city disaster recovery. | ||
|
||
- Data migration: The migration can be implemented by synchronizing data and then switching cluster roles, without stopping the service. | ||
|
||
- Read/Write splitting: Enable only writing on the primary cluster and only reading on the secondary cluster to lower the system load, and improve stability and usability. | ||
|
||
## Precautions | ||
|
||
- The synchronization is based on graph spaces, i.e., from one graph space in the primary cluster to another in the secondary cluster. | ||
|
||
- About the synchronization topology, Nebula Graph: | ||
|
||
- Supports synchronizing from one primary cluster to one secondary cluster, but not multiple primary clusters to one secondary cluster. | ||
|
||
- Supports chained synchronization but not synchronization from one primary cluster to multiple secondary clusters directly. An example of chained synchronization is from cluster A to cluster B, and then cluster B to cluster C. | ||
|
||
- The synchronization is implemented asynchronously, but with low latency. | ||
|
||
## Prerequisites | ||
|
||
- Prepare at least two machines to deploy the primary and secondary clusters, the listeners, and the drainer. | ||
|
||
The listener and drainer can be deployed in a standalone way, or on the machines hosting the primary and secondary clusters. The latter way can increase the machine load and decrease the service performance. | ||
|
||
- Prepare the license file for the Nebula Graph Enterprise Edition. | ||
|
||
## Test environment | ||
|
||
The test environment for the operation example in this topic is as follows: | ||
|
||
- The primary cluster runs on the machine with the IP address 192.168.10.101. The cluster has one nebula-graphd process, one nebula-metad process, and one nebula-storaged process. | ||
|
||
- The secondary cluster runs on the machine with the IP address 192.168.10.102. The cluster has one nebula-graphd process, one nebula-metad process, and one nebula-storaged process. | ||
|
||
!!! note | ||
The primary and secondary clusters can have different cluster specifications, such as different numbers of machines, service processes, and data partitions. | ||
|
||
- The processes for the Meta and Storage listeners run on the machine with the IP address 192.168.10.103. | ||
|
||
- The process for the drainer runs on the machine with the IP address 192.168.10.104. | ||
|
||
## Steps | ||
|
||
### Step 1: Set up the clusters, listeners, and drainer | ||
|
||
1. Install Nebula Graph on all the machines. | ||
|
||
For installing Nebula Graph, see the instructions in the [Compile and install Nebula directory](../4.deployment-and-installation/2.compile-and-install-nebula-graph/2.install-nebula-graph-by-rpm-or-deb.md). | ||
|
||
2. Modify the configuration files on all the machines. | ||
|
||
!!! note | ||
For newly installed services, remove the suffix `.default` or `.production` of a configuration template file in the `conf` directory to make it take effect. | ||
|
||
- On the primary and secondary cluster machines, modify `nebula-graphd.conf`, `nebula-metad.conf`, and `nebula-storaged.conf`. In all three files, set real IP addresses for `local_ip` instead of `127.0.0.1`, and set the IP addresses and ports for their own nebula-metad processes as the `meta_server_addrs` values. In `nebula-graphd.conf`, set `enable_authorize=true`. | ||
|
||
- On the Meta listener machine, modify `nebula-metad-listener.conf`. Set the IP addresses and ports of the **primary cluster's** nebula-metad processes for `meta_server_addrs`, and those of the listener process for `meta_sync_listener`. | ||
|
||
- On the Storage listener machine, modify `nebula-storaged-listener.conf`. Set the IP addresses and ports of the **primary cluster's** nebula-metad processes for `meta_server_addrs`. | ||
|
||
- On the drainer machine, modify `nebula-drainerd.conf`. Set the IP addresses and ports of the **secondary cluster's** nebula-metad processes for `meta_server_addrs`. | ||
|
||
For more information about the configurations, see [Configurations](../5.configurations-and-logs/1.configurations/1.configurations.md). | ||
|
||
3. On the machines of the primary cluster, secondary cluster, and listeners, upload the license files into the `share/resources/` directories in the Nebula Graph installation directories. | ||
|
||
4. Go to the Nebula Graph installation directories on the machines and start the needed services. | ||
|
||
- On the primary and secondary machines, run `sudo scripts/nebula.service start all`. | ||
|
||
- On the Meta listener machine, run `sudo bin/nebula-metad --flagfile etc/nebula-metad-listener.conf`. | ||
|
||
- On the Storage listener machine, run `sudo bin/nebula-storaged --flagfile etc/nebula-storaged-listener.conf`. | ||
|
||
- On the drainer machine, run `sudo scripts/nebula-drainerd.service start`. | ||
|
||
5. Log into the primary cluster, add the Storage hosts, and check the status of the listeners. | ||
|
||
```bash | ||
# Add the Storage hosts first. | ||
nebula> ADD HOSTS 192.168.10.101:9779; | ||
nebula> SHOW HOSTS STORAGE; | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
| Host | Port | Status | Role | Git Info Sha | Version | | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
| "192.168.10.101" | 9779 | "ONLINE" | "STORAGE" | "xxxxxxx" | "ent-3.1.0" | | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
|
||
# Check the status of the Storage listener. | ||
nebula> SHOW HOSTS STORAGE LISTENER; | ||
+------------------+------+----------+--------------------+--------------+----------------------+ | ||
| Host | Port | Status | Role | Git Info Sha | Version | | ||
+------------------+------+----------+--------------------+--------------+----------------------+ | ||
| "192.168.10.103" | 9789 | "ONLINE" | "STORAGE_LISTENER" | "xxxxxxx" | "ent-3.1.0" | | ||
+------------------+------+----------+--------------------+--------------+----------------------+ | ||
|
||
# Check the status of the Meta listener. | ||
nebula> SHOW HOSTS META LISTENER; | ||
+------------------+------+----------+-----------------+--------------+----------------------+ | ||
| Host | Port | Status | Role | Git Info Sha | Version | | ||
+------------------+------+----------+-----------------+--------------+----------------------+ | ||
| "192.168.10.103" | 9559 | "ONLINE" | "META_LISTENER" | "xxxxxxx" | "ent-3.1.0" | | ||
+------------------+------+----------+-----------------+--------------+----------------------+ | ||
``` | ||
|
||
6. Log into the secondary cluster, add the Storage hosts, and check the status of the drainer. | ||
|
||
```bash | ||
nebula> ADD HOSTS 192.168.10.102:9779; | ||
nebula> SHOW HOSTS STORAGE; | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
| Host | Port | Status | Role | Git Info Sha | Version | | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
| "192.168.10.102" | 9779 | "ONLINE" | "STORAGE" | "xxxxxxx" | "ent-3.1.0" | | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
|
||
nebula> SHOW HOSTS DRAINER; | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
| Host | Port | Status | Role | Git Info Sha | Version | | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
| "192.168.10.104" | 9889 | "ONLINE" | "DRAINER" | "xxxxxxx" | "ent-3.1.0" | | ||
+------------------+------+----------+-----------+--------------+----------------------+ | ||
``` | ||
|
||
### Step 2: Set up the synchronization | ||
|
||
1. Log into the primary cluster and create a graph space `basketballplayer`. | ||
|
||
``` | ||
nebula> CREATE SPACE basketballplayer(partition_num=15, \ | ||
replica_factor=1, \ | ||
vid_type=fixed_string(30)); | ||
``` | ||
|
||
2. Use the graph space `basketballplayer` and register the drainer service. | ||
|
||
```bash | ||
nebula> USE basketballplayer; | ||
|
||
# Register the drainer service. | ||
nebula> SIGN IN DRAINER SERVICE(192.168.10.104:9889); | ||
|
||
# Check if the drainer service is successfully signed in. | ||
nebula> SHOW DRAINER CLIENTS; | ||
+-----------+------------------+------+ | ||
| Type | Host | Port | | ||
+-----------+------------------+------+ | ||
| "DRAINER" | "192.168.10.104" | 9889 | | ||
+-----------+------------------+------+ | ||
``` | ||
|
||
3. Configure the listener service. | ||
|
||
```bash | ||
# replication_basketballplayer is the synchronization target. It will be created in the following steps. | ||
nebula> ADD LISTENER SYNC \ | ||
META 192.168.10.103:9559 \ | ||
STORAGE 192.168.10.103:9789 \ | ||
TO SPACE replication_basketballplayer; | ||
|
||
# Check the listener status. | ||
nebula> SHOW LISTENER SYNC; | ||
+--------+--------+------------------------+--------------------------------+----------+ | ||
| PartId | Type | Host | SpaceName | Status | | ||
+--------+--------+------------------------+--------------------------------+----------+ | ||
| 0 | "SYNC" | ""192.168.10.103":9559" | "replication_basketballplayer" | "ONLINE" | | ||
| 1 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 2 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 3 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 4 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 5 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 6 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 7 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 8 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 9 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 10 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 11 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 12 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 13 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 14 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
| 15 | "SYNC" | ""192.168.10.103":9789" | "replication_basketballplayer" | "ONLINE" | | ||
+--------+--------+------------------------+--------------------------------+----------+ | ||
``` | ||
|
||
4. Log into the secondary cluster and create graph space `replication_basketballplayer`. | ||
|
||
```bash | ||
nebula> CREATE SPACE replication_basketballplayer(partition_num=15, \ | ||
replica_factor=1, \ | ||
vid_type=fixed_string(30)); | ||
``` | ||
|
||
5. Use `replication_basketballplayer` and configure the drainer service. | ||
|
||
```bash | ||
# Configure the drainer service. | ||
nebula> ADD DRAINER 192.168.10.104:9889; | ||
|
||
# Check the drainer status. | ||
nebula> SHOW DRAINERS; | ||
+-------------------------+----------+ | ||
| Host | Status | | ||
+-------------------------+----------+ | ||
| ""192.168.10.104":9889" | "ONLINE" | | ||
+-------------------------+----------+ | ||
``` | ||
|
||
6. Set the target graph space as read-only to avoid data inconsistency. | ||
|
||
!!! note | ||
|
||
This step only sets the target graph space, not other graph spaces. | ||
|
||
```bash | ||
nebula> USE replication_basketballplayer; | ||
|
||
# Set the working graph space as read-only. | ||
nebula> SET VARIABLES read_only=true; | ||
|
||
# Check the read_only status of the working graph space. | ||
nebula> GET VARIABLES read_only; | ||
+-------------+--------+-------+ | ||
| name | type | value | | ||
+-------------+--------+-------+ | ||
| "read_only" | "bool" | true | | ||
+-------------+--------+-------+ | ||
``` | ||
|
||
### Step 3: Validate the data | ||
|
||
1. Log into the primary cluster, create the schema, and insert data. | ||
|
||
```bash | ||
nebula> USE basketballplayer; | ||
nebula> CREATE TAG player(name string, age int); | ||
nebula> CREATE EDGE follow(degree int); | ||
nebula> INSERT VERTEX player(name, age) VALUES "player100":("Tim Duncan", 42); | ||
nebula> INSERT VERTEX player(name, age) VALUES "player101":("Tony Parker", 36); | ||
nebula> INSERT EDGE follow(degree) VALUES "player101" -> "player100":(95); | ||
``` | ||
|
||
2. Log into the secondary cluster and validate the data. | ||
|
||
```bash | ||
nebula> USE replication_basketballplayer; | ||
nebula> SUBMIT JOB STATS; | ||
nebula> SHOW STATS; | ||
+---------+------------+-------+ | ||
| Type | Name | Count | | ||
+---------+------------+-------+ | ||
| "Tag" | "player" | 2 | | ||
| "Edge" | "follow" | 1 | | ||
| "Space" | "vertices" | 2 | | ||
| "Space" | "edges" | 1 | | ||
+---------+------------+-------+ | ||
|
||
nebula> FETCH PROP ON player "player100" \ | ||
YIELD properties(vertex); | ||
+-------------------------------+ | ||
| properties(VERTEX) | | ||
+-------------------------------+ | ||
| {age: 42, name: "Tim Duncan"} | | ||
+-------------------------------+ | ||
|
||
nebula> GO FROM "player101" OVER follow \ | ||
YIELD dst(edge); | ||
+-------------+ | ||
| dst(EDGE) | | ||
+-------------+ | ||
| "player100" | | ||
+-------------+ | ||
``` | ||
|
||
## Switch between primary and secondary clusters | ||
|
||
To migrate data or implement disaster recovery, manually switch between the primary and secondary clusters. | ||
|
||
!!! note | ||
|
||
Before the switching, set up a listener for the new primary cluster, and a drainer for the new secondary cluster. In the following example, the listener has IP address 192.168.10.105 and drainer 192.168.10.106. | ||
|
||
1. Log into the primary cluster and remove the old drainer and listener. | ||
|
||
```bash | ||
nebula> USE basketballplayer; | ||
nebula> SIGN OUT DRAINER SERVICE; | ||
nebula> REMOVE LISTENER SYNC; | ||
``` | ||
|
||
2. Set the working graph space as read-only to avoid data inconsistency. | ||
|
||
```bash | ||
nebula> SET VARIABLES read_only=true; | ||
``` | ||
|
||
3. Log into the secondary cluster, disable read-only, and remove the old drainer. | ||
|
||
```bash | ||
nebula> USE replication_basketballplayer; | ||
nebula> SET VARIABLES read_only=false; | ||
nebula> REMOVE DRAINER; | ||
``` | ||
|
||
4. Change the secondary cluster to the new primary cluster. | ||
|
||
```bash | ||
nebula> SIGN IN DRAINER SERVICE(192.168.10.106:9889); | ||
nebula> ADD LISTENER SYNC META 192.168.10.105:9559 STORAGE 192.168.10.105:9789 TO SPACE basketballplayer; | ||
nebula> REMOVE DRAINER; | ||
``` | ||
|
||
5. Log into the old primary cluster and change it to the new secondary cluster. | ||
|
||
```bash | ||
nebula> USE basketballplayer; | ||
# Disable read-only for the working graph space, otherwise adding drainer fails. | ||
nebula> SET VARIABLES read_only=false; | ||
nebula> ADD DRAINER 192.168.10.106:9889; | ||
nebula> SET VARIABLES read_only=true; | ||
``` | ||
|
||
## FAQ | ||
|
||
### Can the pre-existent data in the primary cluster be synchronized to the secondary cluster? | ||
|
||
Yes. After receiving the WAL from the listener, if the drainer finds that the data to be updated does not exist in the secondary cluster, it starts the synchronization of the complete data set. | ||
|
||
### Will the pre-existent data in the secondary cluster affect the synchronization? | ||
|
||
If the pre-existent data in the secondary cluster is a subset of the data in the primary cluster, the data in the primary and secondary clusters will eventually become consistent through synchronization. | ||
|
||
The pre-existent data that is not in the primary cluster will stay in the secondary cluster until manually deleted. | ||
|
||
### Will the pre-existent schema information in the secondary cluster affect the synchronization? | ||
|
||
The pre-existent schema information must not conflict with the schema of the primary cluster. Otherwise, it will be overwritten, and related data in the secondary cluster might become invalid. | ||
|
||
### Should the number of machines, replicas, and partitions in the primary and secondary clusters be the same? | ||
|
||
No. The synchronization is based on graph spaces, not other elements such as partitions and replicas. The primary and secondary clusters do not need to have the exact specifications. | ||
|
||
### Does altering the schema in the primary cluster affect the synchronization? | ||
|
||
Altering the schema may increase the synchronization latency. | ||
|
||
The schema data is synchronized through the Meta listener, while the vertex/edge data is through the Storage listener. When synchronizing the vertex/edge data, the system checks the schema version of the data. If the system finds that the version number of the schema is greater than that in the secondary cluster, it pauses the vertex/edge data update, and updates the schema data first. | ||
|
||
### How to check the data synchronization status and progress? | ||
|
||
<!--show sync | ||
Find the WALs that has just been synchronized, and that has most recently been generated, then: | ||
|
||
- Compare their timestamps to see if the synchronization is working correctly. | ||
|
||
- Compare the log ID to view the synchronization gap. | ||
--> | ||
|
||
There is no tool specially designed to do this for now. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cross-data centers