blob: e37dca248573df1a32b8230c61eb99868abacb73 [file]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= Multi Data Center Deployment
== Overview
Ignite can run a single cluster across multiple data centers.
In this mode, every server node is assigned a data center ID.
Ignite uses this ID to group nodes by data center, reduce cross-data-center traffic when possible,
choose local data copies for reads, and validate cache topology during data center failures.
[NOTE]
====
Multi data center support is an experimental feature.
APIs and behavior can change in later releases.
====
The feature is based on the following components:
* `IGNITE_DATA_CENTER_ID` - system property or user attribute that assigns a node to a data center.
* `ClusterNode#dataCenterId()` - node API that exposes the configured data center ID.
* `MdcTopologyValidator` - cache topology validator that can block updates when not enough data centers are visible.
* `MdcAffinityBackupFilter` - affinity backup filter that spreads partition copies evenly across data centers.
* Thin client data center awareness - routing that prefers nodes from the client's data center.
== Configuring Data Center ID
Set the same data center ID on all server nodes located in the same data center.
Nodes from different data centers must use different IDs.
You can set the ID with the `IGNITE_DATA_CENTER_ID` system property:
[source,shell]
----
bin/ignite.sh -J-DIGNITE_DATA_CENTER_ID=DC1
----
You can also set the same value as a user attribute in `IgniteConfiguration`:
[source,java]
----
IgniteConfiguration cfg = new IgniteConfiguration();
cfg.setUserAttributes(Collections.singletonMap(
IgniteSystemProperties.IGNITE_DATA_CENTER_ID, "DC1"));
----
Server nodes in the same cluster must be configured consistently:
* If one server node has a data center ID, all server nodes must have a data center ID.
* Server nodes without a data center ID cannot join a cluster where server nodes have data center IDs.
* Server nodes with a data center ID cannot join a cluster where server nodes do not have data center IDs.
* Client nodes can join with or without a data center ID.
== Discovery
`TcpDiscoverySpi` uses data center IDs to keep nodes from the same data center close to each other in
the discovery ring.
When a data center becomes unavailable, discovery can check remote data centers in parallel and close the ring
through the local data center if the remote data center does not respond.
Client nodes also use the data center ID during discovery.
If a client has a data center ID, it tries to connect through a server node from the same data center.
If no server node from the same data center is available, the client connects through any available server node.
== Cache Topology Validation
Use `MdcTopologyValidator` to protect caches from updates when the visible topology does not contain enough data centers.
The validator ignores client nodes and checks only server nodes.
The validator supports two modes:
* Majority-based validation - for an odd number of data centers, specify the full set of data centers.
Updates are allowed only when the visible topology contains a majority of the configured data centers.
* Main data center validation - for an even number of data centers, specify the main data center.
Updates are allowed while the main data center is visible.
[tabs]
--
tab:XML[]
[source,xml]
----
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="accounts"/>
<property name="topologyValidator">
<bean class="org.apache.ignite.topology.MdcTopologyValidator">
<property name="datacenters">
<set>
<value>DC1</value>
<value>DC2</value>
<value>DC3</value>
</set>
</property>
</bean>
</property>
</bean>
----
tab:Java[]
[source,java]
----
MdcTopologyValidator validator = new MdcTopologyValidator();
validator.setDatacenters(Set.of("DC1", "DC2", "DC3"));
CacheConfiguration<Integer, Account> cacheCfg =
new CacheConfiguration<Integer, Account>("accounts")
.setTopologyValidator(validator);
----
--
For an even number of data centers, configure a main data center:
[tabs]
--
tab:XML[]
[source,xml]
----
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="accounts"/>
<property name="topologyValidator">
<bean class="org.apache.ignite.topology.MdcTopologyValidator">
<property name="mainDatacenter" value="DC1"/>
</bean>
</property>
</bean>
----
tab:Java[]
[source,java]
----
MdcTopologyValidator validator = new MdcTopologyValidator();
validator.setMainDatacenter("DC1");
CacheConfiguration<Integer, Account> cacheCfg =
new CacheConfiguration<Integer, Account>("accounts")
.setTopologyValidator(validator);
----
--
The validator configuration is checked when the cache is created.
The following configurations are invalid:
* Neither `datacenters` nor `mainDatacenter` is specified.
* `datacenters` is specified as an empty set.
* `mainDatacenter` is specified together with an odd number of data centers.
== Placing Backup Copies Across Data Centers
Use `MdcAffinityBackupFilter` with `RendezvousAffinityFunction` to distribute partition copies across data centers.
The filter ensures that each partition has the same number of copies in each data center.
For example, a cache with `backups=3` has four partition copies: one primary and three backups.
In a two-data-center cluster, `MdcAffinityBackupFilter(2, 3)` places two copies in each data center.
[tabs]
--
tab:XML[]
[source,xml]
----
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="accounts"/>
<property name="backups" value="3"/>
<property name="affinity">
<bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction">
<property name="affinityBackupFilter">
<bean class="org.apache.ignite.cache.affinity.rendezvous.MdcAffinityBackupFilter">
<constructor-arg value="2"/>
<constructor-arg value="3"/>
</bean>
</property>
</bean>
</property>
</bean>
----
tab:Java[]
[source,java]
----
CacheConfiguration<Integer, Account> cacheCfg =
new CacheConfiguration<Integer, Account>("accounts")
.setBackups(3)
.setAffinity(new RendezvousAffinityFunction()
.setAffinityBackupFilter(new MdcAffinityBackupFilter(2, 3)));
----
--
`MdcAffinityBackupFilter` has the following requirements:
* The number of data centers must be at least 2.
* `(backups + 1)` must be evenly divisible by the number of data centers.
* All server nodes must have a data center ID.
If these requirements are not met, the filter either rejects the configuration or cannot place copies predictably.
For other backup placement strategies, see link:configuring-caches/configuring-backups#affinity-backup-filters[Affinity Backup Filters].
== Reading from Local Data Center
When `CacheConfiguration#readFromBackup` is `true`, Ignite can read from a backup copy instead of the primary copy.
In a multi data center topology, this allows Ignite to use a backup located in the same data center as the
requester when such a backup is available.
The Java thin client also uses the data center ID for partition awareness.
Set the client's data center ID with the `IGNITE_DATA_CENTER_ID` system property or in
`ClientConfiguration#setUserAttributes(...)`.
If both are configured, the system property takes precedence.
For partition-aware read operations, the client sends requests to a node from its own data center when the cache has
`readFromBackup=true`, its write synchronization mode is not `PRIMARY_SYNC`, and the local data center has a
partition copy.
Writes are still routed to the primary node.
[source,java]
----
ClientConfiguration cfg = new ClientConfiguration()
.setAddresses("dc1-node1:10800", "dc1-node2:10800", "dc2-node1:10800")
.setUserAttributes(Collections.singletonMap(
IgniteSystemProperties.IGNITE_DATA_CENTER_ID, "DC1"));
----
The same value can be set with the JVM system property:
[source,shell]
----
java -DIGNITE_DATA_CENTER_ID=DC1 ...
----
If no nodes are available in the client's data center, the client uses other available nodes.
== Rebalancing
During rebalancing, Ignite prefers nodes from the same data center when such suppliers are available.
If the required partition data cannot be obtained from the same data center, Ignite can rebalance from a
remote data center.
This behavior applies to both full and historical rebalance.
== Monitoring
The data center ID is exposed in the `NODES` system view as part of node information.
For client nodes, the `io.discovery.ClientRouterNodeId` metric exposes the ID of the server node used as
the discovery router.