|
| 1 | +// Licensed to the Apache Software Foundation (ASF) under one or more |
| 2 | +// contributor license agreements. See the NOTICE file distributed with |
| 3 | +// this work for additional information regarding copyright ownership. |
| 4 | +// The ASF licenses this file to You under the Apache License, Version 2.0 |
| 5 | +// (the "License"); you may not use this file except in compliance with |
| 6 | +// the License. You may obtain a copy of the License at |
| 7 | +// |
| 8 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +// |
| 10 | +// Unless required by applicable law or agreed to in writing, software |
| 11 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +// See the License for the specific language governing permissions and |
| 14 | +// limitations under the License. |
| 15 | += Multi Data Center Deployment |
| 16 | + |
| 17 | +== Overview |
| 18 | + |
| 19 | +Ignite can run a single cluster across multiple data centers. |
| 20 | +In this mode, every server node is assigned a data center ID. |
| 21 | +Ignite uses this ID to group nodes by data center, reduce cross-data-center traffic when possible, |
| 22 | +choose local data copies for reads, and validate cache topology during data center failures. |
| 23 | + |
| 24 | +[NOTE] |
| 25 | +==== |
| 26 | +Multi data center support is an experimental feature. |
| 27 | +APIs and behavior can change in later releases. |
| 28 | +==== |
| 29 | + |
| 30 | +The feature is based on the following components: |
| 31 | + |
| 32 | +* `IGNITE_DATA_CENTER_ID` - system property or user attribute that assigns a node to a data center. |
| 33 | +* `ClusterNode#dataCenterId()` - node API that exposes the configured data center ID. |
| 34 | +* `MdcTopologyValidator` - cache topology validator that can block updates when not enough data centers are visible. |
| 35 | +* `MdcAffinityBackupFilter` - affinity backup filter that spreads partition copies evenly across data centers. |
| 36 | +* Thin client data center awareness - routing that prefers nodes from the client's data center. |
| 37 | + |
| 38 | +== Configuring Data Center ID |
| 39 | + |
| 40 | +Set the same data center ID on all server nodes located in the same data center. |
| 41 | +Nodes from different data centers must use different IDs. |
| 42 | + |
| 43 | +You can set the ID with the `IGNITE_DATA_CENTER_ID` system property: |
| 44 | + |
| 45 | +[source,shell] |
| 46 | +---- |
| 47 | +bin/ignite.sh -J-DIGNITE_DATA_CENTER_ID=DC1 |
| 48 | +---- |
| 49 | + |
| 50 | +You can also set the same value as a user attribute in `IgniteConfiguration`: |
| 51 | + |
| 52 | +[source,java] |
| 53 | +---- |
| 54 | +IgniteConfiguration cfg = new IgniteConfiguration(); |
| 55 | +
|
| 56 | +cfg.setUserAttributes(Collections.singletonMap( |
| 57 | + IgniteSystemProperties.IGNITE_DATA_CENTER_ID, "DC1")); |
| 58 | +---- |
| 59 | + |
| 60 | +Server nodes in the same cluster must be configured consistently: |
| 61 | + |
| 62 | +* If one server node has a data center ID, all server nodes must have a data center ID. |
| 63 | +* Server nodes without a data center ID cannot join a cluster where server nodes have data center IDs. |
| 64 | +* Server nodes with a data center ID cannot join a cluster where server nodes do not have data center IDs. |
| 65 | +* Client nodes can join with or without a data center ID. |
| 66 | + |
| 67 | +== Discovery |
| 68 | + |
| 69 | +`TcpDiscoverySpi` uses data center IDs to keep nodes from the same data center close to each other in |
| 70 | +the discovery ring. |
| 71 | +When a data center becomes unavailable, discovery can check remote data centers in parallel and close the ring |
| 72 | +through the local data center if the remote data center does not respond. |
| 73 | + |
| 74 | +Client nodes also use the data center ID during discovery. |
| 75 | +If a client has a data center ID, it tries to connect through a server node from the same data center. |
| 76 | +If no server node from the same data center is available, the client connects through any available server node. |
| 77 | + |
| 78 | +== Cache Topology Validation |
| 79 | + |
| 80 | +Use `MdcTopologyValidator` to protect caches from updates when the visible topology does not contain enough data centers. |
| 81 | +The validator ignores client nodes and checks only server nodes. |
| 82 | + |
| 83 | +The validator supports two modes: |
| 84 | + |
| 85 | +* Majority-based validation - for an odd number of data centers, specify the full set of data centers. |
| 86 | +Updates are allowed only when the visible topology contains a majority of the configured data centers. |
| 87 | +* Main data center validation - for an even number of data centers, specify the main data center. |
| 88 | +Updates are allowed while the main data center is visible. |
| 89 | + |
| 90 | +[tabs] |
| 91 | +-- |
| 92 | +tab:XML[] |
| 93 | +[source,xml] |
| 94 | +---- |
| 95 | +<bean class="org.apache.ignite.configuration.CacheConfiguration"> |
| 96 | + <property name="name" value="accounts"/> |
| 97 | + <property name="topologyValidator"> |
| 98 | + <bean class="org.apache.ignite.topology.MdcTopologyValidator"> |
| 99 | + <property name="datacenters"> |
| 100 | + <set> |
| 101 | + <value>DC1</value> |
| 102 | + <value>DC2</value> |
| 103 | + <value>DC3</value> |
| 104 | + </set> |
| 105 | + </property> |
| 106 | + </bean> |
| 107 | + </property> |
| 108 | +</bean> |
| 109 | +---- |
| 110 | + |
| 111 | +tab:Java[] |
| 112 | +[source,java] |
| 113 | +---- |
| 114 | +MdcTopologyValidator validator = new MdcTopologyValidator(); |
| 115 | +
|
| 116 | +validator.setDatacenters(Set.of("DC1", "DC2", "DC3")); |
| 117 | +
|
| 118 | +CacheConfiguration<Integer, Account> cacheCfg = |
| 119 | + new CacheConfiguration<Integer, Account>("accounts") |
| 120 | + .setTopologyValidator(validator); |
| 121 | +---- |
| 122 | +-- |
| 123 | + |
| 124 | +For an even number of data centers, configure a main data center: |
| 125 | + |
| 126 | +[tabs] |
| 127 | +-- |
| 128 | +tab:XML[] |
| 129 | +[source,xml] |
| 130 | +---- |
| 131 | +<bean class="org.apache.ignite.configuration.CacheConfiguration"> |
| 132 | + <property name="name" value="accounts"/> |
| 133 | + <property name="topologyValidator"> |
| 134 | + <bean class="org.apache.ignite.topology.MdcTopologyValidator"> |
| 135 | + <property name="mainDatacenter" value="DC1"/> |
| 136 | + </bean> |
| 137 | + </property> |
| 138 | +</bean> |
| 139 | +---- |
| 140 | + |
| 141 | +tab:Java[] |
| 142 | +[source,java] |
| 143 | +---- |
| 144 | +MdcTopologyValidator validator = new MdcTopologyValidator(); |
| 145 | +
|
| 146 | +validator.setMainDatacenter("DC1"); |
| 147 | +
|
| 148 | +CacheConfiguration<Integer, Account> cacheCfg = |
| 149 | + new CacheConfiguration<Integer, Account>("accounts") |
| 150 | + .setTopologyValidator(validator); |
| 151 | +---- |
| 152 | +-- |
| 153 | + |
| 154 | +The validator configuration is checked when the cache is created. |
| 155 | +The following configurations are invalid: |
| 156 | + |
| 157 | +* Neither `datacenters` nor `mainDatacenter` is specified. |
| 158 | +* `datacenters` is specified as an empty set. |
| 159 | +* `mainDatacenter` is specified together with an odd number of data centers. |
| 160 | + |
| 161 | +== Placing Backup Copies Across Data Centers |
| 162 | + |
| 163 | +Use `MdcAffinityBackupFilter` with `RendezvousAffinityFunction` to distribute partition copies across data centers. |
| 164 | +The filter ensures that each partition has the same number of copies in each data center. |
| 165 | + |
| 166 | +For example, a cache with `backups=3` has four partition copies: one primary and three backups. |
| 167 | +In a two-data-center cluster, `MdcAffinityBackupFilter(2, 3)` places two copies in each data center. |
| 168 | + |
| 169 | +[tabs] |
| 170 | +-- |
| 171 | +tab:XML[] |
| 172 | +[source,xml] |
| 173 | +---- |
| 174 | +<bean class="org.apache.ignite.configuration.CacheConfiguration"> |
| 175 | + <property name="name" value="accounts"/> |
| 176 | + <property name="backups" value="3"/> |
| 177 | + <property name="affinity"> |
| 178 | + <bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction"> |
| 179 | + <property name="affinityBackupFilter"> |
| 180 | + <bean class="org.apache.ignite.cache.affinity.rendezvous.MdcAffinityBackupFilter"> |
| 181 | + <constructor-arg value="2"/> |
| 182 | + <constructor-arg value="3"/> |
| 183 | + </bean> |
| 184 | + </property> |
| 185 | + </bean> |
| 186 | + </property> |
| 187 | +</bean> |
| 188 | +---- |
| 189 | + |
| 190 | +tab:Java[] |
| 191 | +[source,java] |
| 192 | +---- |
| 193 | +CacheConfiguration<Integer, Account> cacheCfg = |
| 194 | + new CacheConfiguration<Integer, Account>("accounts") |
| 195 | + .setBackups(3) |
| 196 | + .setAffinity(new RendezvousAffinityFunction() |
| 197 | + .setAffinityBackupFilter(new MdcAffinityBackupFilter(2, 3))); |
| 198 | +---- |
| 199 | +-- |
| 200 | + |
| 201 | +`MdcAffinityBackupFilter` has the following requirements: |
| 202 | + |
| 203 | +* The number of data centers must be at least 2. |
| 204 | +* `(backups + 1)` must be evenly divisible by the number of data centers. |
| 205 | +* All server nodes must have a data center ID. |
| 206 | + |
| 207 | +If these requirements are not met, the filter either rejects the configuration or cannot place copies predictably. |
| 208 | + |
| 209 | +For other backup placement strategies, see link:configuring-caches/configuring-backups#affinity-backup-filters[Affinity Backup Filters]. |
| 210 | + |
| 211 | +== Reading from Local Data Center |
| 212 | + |
| 213 | +When `CacheConfiguration#readFromBackup` is `true`, Ignite can read from a backup copy instead of the primary copy. |
| 214 | +In a multi data center topology, this allows Ignite to use a backup located in the same data center as the |
| 215 | +requester when such a backup is available. |
| 216 | + |
| 217 | +The Java thin client also uses the data center ID for partition awareness. |
| 218 | +Set the client's data center ID with the `IGNITE_DATA_CENTER_ID` system property or in |
| 219 | +`ClientConfiguration#setUserAttributes(...)`. |
| 220 | +If both are configured, the system property takes precedence. |
| 221 | +For partition-aware read operations, the client sends requests to a node from its own data center when the cache has |
| 222 | +`readFromBackup=true`, its write synchronization mode is not `PRIMARY_SYNC`, and the local data center has a |
| 223 | +partition copy. |
| 224 | +Writes are still routed to the primary node. |
| 225 | + |
| 226 | +[source,java] |
| 227 | +---- |
| 228 | +ClientConfiguration cfg = new ClientConfiguration() |
| 229 | + .setAddresses("dc1-node1:10800", "dc1-node2:10800", "dc2-node1:10800") |
| 230 | + .setUserAttributes(Collections.singletonMap( |
| 231 | + IgniteSystemProperties.IGNITE_DATA_CENTER_ID, "DC1")); |
| 232 | +---- |
| 233 | + |
| 234 | +The same value can be set with the JVM system property: |
| 235 | + |
| 236 | +[source,shell] |
| 237 | +---- |
| 238 | +java -DIGNITE_DATA_CENTER_ID=DC1 ... |
| 239 | +---- |
| 240 | + |
| 241 | +If no nodes are available in the client's data center, the client uses other available nodes. |
| 242 | + |
| 243 | +== Rebalancing |
| 244 | + |
| 245 | +During rebalancing, Ignite prefers nodes from the same data center when such suppliers are available. |
| 246 | +If the required partition data cannot be obtained from the same data center, Ignite can rebalance from a |
| 247 | +remote data center. |
| 248 | +This behavior applies to both full and historical rebalance. |
| 249 | + |
| 250 | +== Monitoring |
| 251 | + |
| 252 | +The data center ID is exposed in the `NODES` system view as part of node information. |
| 253 | +For client nodes, the `io.discovery.ClientRouterNodeId` metric exposes the ID of the server node used as |
| 254 | +the discovery router. |
0 commit comments