# Efficient Sync Solutions: Cluster-to-Cluster Sync and Live Migration to Atlas

The challenges that are raised in modern business contexts are increasingly complex. These challenges range from the ability to minimize downtime during migrations to adopting efficient tools for transitioning from relational to non-relational databases, and from implementing resilient architectures that ensure high availability to the ability to scale horizontally, allowing large amounts of data to be efficiently managed and queried.

Two of the main challenges, which will be covered in this article, are:

-   The need to create resilient IT infrastructures that can ensure business continuity or minimal downtime even in critical situations, such as the loss of a data center.

-   Conducting migrations from one infrastructure to another without compromising operations.

It is in this context that MongoDB stands out by offering innovative solutions such as MongoSync and live migrate.

Ensuring business continuity with MongoSync: an approach to disaster recovery
-----------------------------------------------------------------------------

MongoDB Atlas, with its capabilities and remarkable flexibility, offers two distinct approaches to implementing business continuity strategies. These two strategies are:

-   Creating a cluster with a geographic distribution of nodes.

-   The implementation of two clusters in different regions synchronized via MongoSync.

In this section, we will explore the second point (i.e., the implementation of two clusters in different regions synchronized via MongoSync) in more detail.

What exactly is MongoSync? For a correct definition, we can refer to the official documentation:

"The `mongosync` binary is the primary process used in Cluster-to-Cluster Sync. `mongosync` migrates data from one cluster to another and can keep the clusters in continuous sync."

This tool performs the following operations:

-   It migrates data from one cluster to another.

-   It keeps the clusters in continuous sync.

Let's make this more concrete with an example:

-   Initially, the situation looks like this for the production cluster and the disaster recovery cluster:

. The commands described below have been tested in the CentOS 7 operating system.

Let's proceed with the configuration of `mongosync` by defining a configuration file and a service:

```
vi /etc/mongosync.conf
```

You can copy and paste the current configuration into this file using the appropriate connection strings. You can also test with two Atlas clusters, which must be M10 level or higher. For more details on how to get the connection strings from your Atlas cluster, you can consult the documentation.

```
cluster0:  "mongodb+srv://test_u:test_p@cluster0.*****.mongodb.net/?retryWrites=true&w=majority"
cluster1:  "mongodb+srv://test_u:test_p@cluster1.*****.mongodb.net/?retryWrites=true&w=majority"
logPath:  "/data/log/mongosync"
verbosity:  "INFO"
```

>Generally, this step is performed on a Linux machine by system administrators. Although the step is optional, it is recommended to implement it in a production environment.

Next, you will be able to create a service named mongosync.service.

```
vi /usr/lib/systemd/system/mongosync.service
```

This is what your service file should look like.

```
 Unit]
Description=Cluster-to-Cluster Sync
Documentation=https://www.mongodb.com/docs/cluster-to-cluster-sync/
[Service]
User=root
Group=root
ExecStart=/usr/local/bin/mongosync --config /etc/mongosync.conf
[Install]
WantedBy=multi-user.target
```

Reload all unit files:

```
systemctl daemon-reload
```

Now, we can start the service: 

```
systemctl start mongosync
```

We can also check whether the service has been started correctly:

```
systemctl status mongosync
```

Output:

```
mongosync.service - Cluster-to-Cluster Sync
    Loaded: loaded (/usr/lib/systemd/system/mongosync.service; disabled; vendor preset: disabled)
Active: active (running) since dom 2024-04-14  21:45:45 CEST; 4s ago
 Docs: https://www.mongodb.com/docs/cluster-to-cluster-sync/
Main PID: 1573 (mongosync)
    CGroup: /system.slice/mongosync.service
 └─1573 /usr/local/bin/mongosync --config /etc/mongosync.conf

apr 14  21:45:45 mongosync.mongodb.int systemd[1]: Started Cluster-to-Cluster Sync.
```

> If a service is not created and executed, in a more general way, you can start the process in the following way: 
> `mongosync --config mongosync.conf `

After starting the service, verify that it is in the idle state:

```
curl localhost:27182/api/v1/progress -XGET | jq
```

Output:

```
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
100  191 100  191 0  0 14384 0 --:--:-- --:--:-- --:--:--  14692
{
 "progress": {
 "state": "IDLE",
 "canCommit": false,
 "canWrite": false,
 "info": null,
 "lagTimeSeconds": null,
 "collectionCopy": null,
 "directionMapping": null,
 "mongosyncID": "coordinator",
 "coordinatorID": ""
  }
}
```
We can run the synchronization:

```
curl localhost:27182/api/v1/start -XPOST \
--data '
    {
 "source": "cluster0",
 "destination": "cluster1",
 "reversible": true,
 "enableUserWriteBlocking": true
    } '
```

Output:

```
{"success":true}
```

We can also keep track of the synchronization status:

```
curl localhost:27182/api/v1/progress -XGET | jq
```

Output:

```
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
100  502 100  502 0  0 36001 0 --:--:-- --:--:-- --:--:--  38615
{
 "progress": {
 "state": "RUNNING",
 "canCommit": false,
 "canWrite": false,
 "info": "collection copy",
 "lagTimeSeconds": 54,
 "collectionCopy": {
 "estimatedTotalBytes": 390696597,
 "estimatedCopiedBytes": 390696597
    },
 "directionMapping": {
 "Source": "cluster0: cluster0.*****.mongodb.net",
 "Destination": "cluster1: cluster1.*****.mongodb.net"
    },
 "mongosyncID": "coordinator",
 "coordinatorID": "coordinator"
  }
}

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
100  510 100  510 0  0 44270 0 --:--:-- --:--:-- --:--:--  46363
{
 "progress": {
 "state": "RUNNING",
 "canCommit": true,
 "canWrite": false,
 "info": "change event application",
 "lagTimeSeconds": 64,
 "collectionCopy": {
 "estimatedTotalBytes": 390696597,
 "estimatedCopiedBytes": 390696597
    },
 "directionMapping": {
 "Source": "cluster0: cluster0.*****.mongodb.net",
 "Destination": "cluster1: cluster1.*****.mongodb.net"
    },
 "mongosyncID": "coordinator",
 "coordinatorID": "coordinator"
  }
}
```

At this time, the DR environment is aligned with the production environment and will also maintain synchronization for the next operations: 

![Image of two clusters located in different datacenters, aligned and remained synchronized via mongosync. Mongosync runs on an on-premises server.][2]

```
Atlas atlas-qsd40w-shard-0 [primary] test> show dbs
admin               140.00 KiB
config              276.00 KiB
local               524.00 KiB
sample_airbnb        52.09 MiB
sample_analytics      9.44 MiB
sample_geospatial     1.02 MiB
sample_guides        40.00 KiB
sample_mflix        109.01 MiB
sample_restaurants    5.73 MiB
sample_supplies     976.00 KiB
sample_training      41.20 MiB
sample_weatherdata    2.39 MiB
```

And our second cluster is now in sync with the following data.

```
Atlas atlas-lcu71y-shard-0 [primary] test> show dbs
admin                                172.00 KiB
config                               380.00 KiB
local                                427.22 MiB
mongosync_reserved_for_internal_use  420.00 KiB
sample_airbnb                         53.06 MiB
sample_analytics                       9.55 MiB
sample_geospatial                      1.40 MiB
sample_guides                         40.00 KiB
sample_mflix                         128.38 MiB
sample_restaurants                     6.47 MiB
sample_supplies                        1.03 MiB
sample_training                       47.21 MiB
sample_weatherdata                     2.61 MiB
````

Armed with what we've discussed so far, we could ask a last question like:

*Is it possible to take advantage of the disaster recovery environment in some way, or should we just let it synchronize?*

By making the appropriate `mongosync` configurations --- for example, by setting the "buildIndexes" option to false and omitting the "enableUserWriteBlocking" parameter (which is set to false by default) --- we can take advantage of the [limitation regarding non-synchronization of users and roles to create read-only users. We do this in such a way that no entries can be entered, thereby ensuring consistency between the origin and destination clusters and allowing us to use the disaster recovery environment to create the appropriate indexes that will go into optimizing slow queries identified in the production environment.

Live migrate to Atlas: minimizing downtime
------------------------------------------

Live migrate is a tool that allows users to perform migrations to MongoDB Atlas and more specifically, as mentioned by the official documentation, is a process that uses `mongosync` as the underlying data migration tool, enabling faster live migrations with less downtime if both the source and destination clusters are running MongoDB 6.0.8 or later.

So, what is the added value of this tool compared to `mongosync`?

It brings two advantages:

-   You can avoid the need to provision and configure a server to host `mongosync`.

-   You have the ability to migrate from previous versions, as indicated in the migration path.

!

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltf8bd745448a43713/663e5cdea2616e0474ff1789/Screenshot_2024-05-10_at_1.40.54_PM.png
  [2]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltd0c6cb1fbf15ed87/663e5d0fa2616e5e82ff178f/Screenshot_2024-05-10_at_1.41.09_PM.png
  [3]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt9ace7dcef1c2e7e9/663e67322ff97d34907049ac/Screenshot_2024-05-10_at_2.24.24_PM.png