Apache Geodeでちょっと気になっていることのひとつとして、Partitioned Regionを使った時にMemberが
増減した際の挙動があります。
前に少し試したことがあるのですが、
Apache GeodeでのBucketとキーの配置について(概要/API編) - CLOVER
Apache GeodeでのBucketとキーの配置について(クラスタ動作確認編) - CLOVER
クラスタ内のMemberが増えたり減ったりした時の挙動がちょっと気になるので、もうちょっと落ち着いて
見てみたいと思います。
前提と準備
基本的には、Client/Server構成で確認します。
- Apache Geodeのクラスタ環境は、Docker Composeで簡単に実現する
- Locatorはひとつ(172.19.0.2:10334)
- Serverは1〜3の間で増減させる
- 上記のLocatorとServerはgfshから起動する
- Clientからデータの登録を行う
- データを持たないEmbeddedなServerをひとつ追加し、データの配置状況を確認する
Docker Composeでクラスタを構成すると書きましたが、
docker-compose.yml
version: "3" services: locator: image: apachegeode/geode:1.1.1 container_name: geodelocator hostname: geodelocator ports: - "10334:10334" - "40404:40404" - "1099:1099" - "7070:7070" command: sh -c "gfsh start locator --name=locator-`hostname` && tail -f /locator-`hostname`/locator-`hostname`.log" server: image: apachegeode/geode:1.1.1 depends_on: - locator links: - locator volumes: - ./cache.xml:/cache.xml:ro command: > bash -c 'until gfsh start server --name=server-`hostname` --bind-address=`hostname -i` --locators=geodelocator[10334] --cache-xml-file=/cache.xml;\ do \ sleep 3; \ done && \ tail -f /server-`hostname`/server-`hostname`.log'
なお、こちらのDocker Composeの内容については、別エントリで書いているので興味があれば参照してください。
Docker Composeで、Apache Geodeの簡単なクラスタ環境を構築する - CLOVER
Cacheの設定は、最初はこのようにします。
cache.xml
<?xml version="1.0" encoding="UTF-8"?> <cache xmlns="http://geode.apache.org/schema/cache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://geode.apache.org/schema/cache http://geode.apache.org/schema/cache/cache-1.0.xsd" version="1.0"> <region name="myRegion" refid="PARTITION"> <region-attributes> <partition-attributes redundant-copies="1"/> </region-attributes> </region> </cache>
「PARTITION」ではなく「PARTITION_REDUNDANT」にしても意味は同じなのですが、このあとでpartition-attributesを
変えていくので、あらかじめわけておくことにします。
「redundant-copies」について
と、こう書くと「redundant-copies」について触れないわけにはいかない気がします。
Set the Number of Redundant Copies | Geode Docs
要するに、バックアップをいくつ持つか?という話になります。「PARTITION_REDUNDANT」を選択すると「redundant-copies」を
1にしたことを同じになるので、バックアップがひとつ確保されます。
「redundant-copies」に特に設定のない「PARTITION」であれば、バックアップがないためServerがダウンすると、該当のServerが
持っていたデータは失われることになります。
ただ、このエントリの後の方で出てくる「リバランス」はバックアップ数が0でも行うことができます。
Locatorと最初のServerを起動
では、Cacheの設定をこちらでいってみます。
<region name="myRegion" refid="PARTITION"> <region-attributes> <partition-attributes redundant-copies="1"/> </region-attributes> </region>
まず、Locatorと最初のServerを起動します。
$ docker-compose up
これで、Apache Geodeのクラスタが起動しました。
Serverのgfshから、クラスタのMemberを見てみましょう。
$ docker exec -it geodecluster_server_1 bash [root@a978e278d01c /]# gfsh _________________________ __ / _____/ ______/ ______/ /____/ / / / __/ /___ /_____ / _____ / / /__/ / ____/ _____/ / / / / /______/_/ /______/_/ /_/ 1.1.1 Monitor and Manage Apache Geode gfsh>connect --jmx-manager=geodelocator[1099] Connecting to Manager at [host=geodelocator, port=1099] .. Successfully connected to: [host=geodelocator, port=1099] gfsh>list members Name | Id -------------------- | -------------------------------------------------------- locator-geodelocator | 172.19.0.2(locator-geodelocator:37:locator)<ec><v0>:1024 server-a978e278d01c | 172.19.0.3(server-a978e278d01c:139)<v3>:1024
LocatorとServerがひとつですね。
データの登録と確認
続いて、データを登録します。ここでは、Clientから登録しましょう。
Maven依存関係。
<dependency> <groupId>org.apache.geode</groupId> <artifactId>geode-core</artifactId> <version>1.1.1</version> </dependency>
作成したプログラムはこちら。
src/main/java/org/littlewings/geode/rebalancing/GeodeClient.java
package org.littlewings.geode.rebalancing; import java.util.stream.IntStream; import org.apache.geode.cache.Region; import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.ClientCacheFactory; import org.apache.geode.cache.client.ClientRegionShortcut; public class GeodeClient { public static void main(String... args) { String mode = args[0]; try (ClientCache clientCache = new ClientCacheFactory().addPoolLocator("172.19.0.2", 10334).create()) { Region<String, String> region = clientCache .<String, String>createClientRegionFactory(ClientRegionShortcut.PROXY).create("myRegion"); switch (mode) { case "show-all-keyvalues": showAllKeyValues(clientCache, region); break; case "register-data": registerData(clientCache, region); break; default: System.out.printf("Unknown Mode[%s]%n", mode); break; } } } static void showAllKeyValues(ClientCache clientCache, Region<String, String> region) { int size = 10; IntStream .rangeClosed(1, size) .forEach(i -> System.out.printf("key: %s, value: %s%n", "key" + i, region.get("key" + i))); } static void registerData(ClientCache clientCache, Region<String, String> region) { int size = 10; IntStream.rangeClosed(1, size).forEach(i -> region.put("key" + i, "value" + i)); } }
形式は固定的ですが、エントリを10個登録、参照する処理を書いています。
引数「register-data」でデータ登録。
$ mvn compile exec:java -Dexec.mainClass=org.littlewings.geode.rebalancing.GeodeClient -Dexec.args=register-data
「show-all-keyvalues」で確認。
$ mvn compile exec:java -Dexec.mainClass=org.littlewings.geode.rebalancing.GeodeClient -Dexec.args=show-all-keyvalues key: key1, value: value1 key: key2, value: value2 key: key3, value: value3 key: key4, value: value4 key: key5, value: value5 key: key6, value: value6 key: key7, value: value7 key: key8, value: value8 key: key9, value: value9 key: key10, value: value10
まあ、データが入ったことがわかるだけですね。
データのServer上の配置状況を確認したい
で、このあとでServerを追加していきたいわけですが、データの配置状況を確認できないとなにが起こっているかわかりません。
というわけで、クラスタには参加するけれども、データは持たないServerを書いてみたいと思います。
作成したのはこちら。
src/main/java/org/littlewings/geode/rebalancing/NoDataServer.java
package org.littlewings.geode.rebalancing; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheFactory; import org.apache.geode.cache.PartitionAttributesFactory; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionShortcut; import org.apache.geode.cache.control.RebalanceOperation; import org.apache.geode.cache.control.RebalanceResults; import org.apache.geode.cache.control.ResourceManager; import org.apache.geode.cache.partition.PartitionRegionHelper; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.cache.PartitionedRegion; public class NoDataServer { public static void main(String... args) { String mode = args[0]; try (Cache cache = new CacheFactory().set("name", "no-data-server").set("locators", "172.19.0.2[10334]").create()) { Region<String, String> region = cache .<String, String>createRegionFactory(RegionShortcut.PARTITION_PROXY) .setPartitionAttributes(new PartitionAttributesFactory<>().setRedundantCopies(1).create()) .create("myRegion"); switch (mode) { case "show-members": showMembers(cache, region); break; case "show-locate": showLocate(cache, region); break; case "rebalance": rebalance(cache, region); break; default: System.out.printf("Unknown Mode[%s]%n", mode); break; } } } static void showMembers(Cache cache, Region<String, String> region) { DistributedMember self = cache.getDistributedSystem().getDistributedMember(); Set<DistributedMember> otherMembers = cache.getDistributedSystem().getAllOtherMembers(); System.out.printf("self: %s%n", self.getName()); otherMembers.forEach(member -> System.out.printf("other: %s%n", member.getName())); } static void showLocate(Cache cache, Region<String, String> region) { region .entrySet() .stream() .sorted(Comparator.comparing(e -> Integer.parseInt(e.getKey().substring(3)))) .forEach(entry -> { System.out.printf("key = %s, value = %s%n", entry.getKey(), entry.getValue()); if (region instanceof PartitionedRegion) { DistributedMember primary = PartitionRegionHelper.getPrimaryMemberForKey(region, entry.getKey()); Set<DistributedMember> allMembers = PartitionRegionHelper.getAllMembersForKey(region, entry.getKey()); Set<DistributedMember> backups = new LinkedHashSet<>(allMembers); backups.remove(primary); // System.out.printf(" bucket id = %d%n", // PartitionedRegionHelper.getHashKey((PartitionedRegion) region, null, entry.getKey(), null, null)); System.out.printf(" primary = %s%n", primary.getName()); System.out.printf(" backup = %s%n", backups.stream().map(m -> m.getName()).collect(Collectors.joining(", ", "[", "]"))); } }); } static void rebalance(Cache cache, Region<String, String> region) { try { ResourceManager resourceManager = cache.getResourceManager(); RebalanceOperation operation = resourceManager.createRebalanceFactory().start(); RebalanceResults results = operation.getResults(); System.out.printf("Region[%s] Rebalance Results: totalBucketTransferBytes = %d, totalBucketCreatesCompleted = %d%n", region.getName(), results.getTotalBucketTransferBytes(), results.getTotalBucketCreatesCompleted()); } catch (InterruptedException e) { // ignore } } }
3つのことができるようにしてあります。
現在のクラスタ内のMember確認。
static void showMembers(Cache cache, Region<String, String> region) { DistributedMember self = cache.getDistributedSystem().getDistributedMember(); Set<DistributedMember> otherMembers = cache.getDistributedSystem().getAllOtherMembers(); System.out.printf("self: %s%n", self.getName()); otherMembers.forEach(member -> System.out.printf("other: %s%n", member.getName())); }
データの配置状況の確認。PrimaryのServerと、バックアップの持ち主がわかるようにしています。
static void showLocate(Cache cache, Region<String, String> region) { region .entrySet() .stream() .sorted(Comparator.comparing(e -> Integer.parseInt(e.getKey().substring(3)))) .forEach(entry -> { System.out.printf("key = %s, value = %s%n", entry.getKey(), entry.getValue()); if (region instanceof PartitionedRegion) { DistributedMember primary = PartitionRegionHelper.getPrimaryMemberForKey(region, entry.getKey()); Set<DistributedMember> allMembers = PartitionRegionHelper.getAllMembersForKey(region, entry.getKey()); Set<DistributedMember> backups = new LinkedHashSet<>(allMembers); backups.remove(primary); System.out.printf(" primary = %s%n", primary.getName()); System.out.printf(" backup = %s%n", backups.stream().map(m -> m.getName()).collect(Collectors.joining(", ", "[", "]"))); } }); }
最後にリバランスです。
static void rebalance(Cache cache, Region<String, String> region) { try { ResourceManager resourceManager = cache.getResourceManager(); RebalanceOperation operation = resourceManager.createRebalanceFactory().start(); RebalanceResults results = operation.getResults(); System.out.printf("Region[%s] Rebalance Results: totalBucketTransferBytes = %d, totalBucketCreatesCompleted = %d%n", region.getName(), results.getTotalBucketTransferBytes(), results.getTotalBucketCreatesCompleted()); } catch (InterruptedException e) { // ignore } }
このServerの名前は、わかりやすいように「no-data-server」としました。
try (Cache cache = new CacheFactory().set("name", "no-data-server").set("locators", "172.19.0.2[10334]").create()) {
また、Regionの定義は「PARTITION_PROXY」を指定して、Serverではあるもののデータを持たないようにしています。
Region<String, String> region = cache .<String, String>createRegionFactory(RegionShortcut.PARTITION_PROXY) .setPartitionAttributes(new PartitionAttributesFactory<>().setRedundantCopies(1).create()) .create("myRegion");
ただ、「redundant-copies」の値は合わせておかないとクラスタに入れないようなので、こちらは同じ値を指定しておきます。
仮に指定しなかった場合は、今回のServer側の設定(redundant-copies=1)だとこうなります。
[warn 2017/04/20 23:15:57.648 JST <main> tid=0x1] Initialization failed for Region /myRegion java.lang.IllegalStateException: Requested redundancy 0 is incompatible with existing redundancy 1 at org.apache.geode.internal.cache.PartitionRegionConfigValidator.validatePartitionAttrsFromPRConfig(PartitionRegionConfigValidator.java:82) at org.apache.geode.internal.cache.PartitionedRegion.registerPartitionedRegion(PartitionedRegion.java:1240) at org.apache.geode.internal.cache.PartitionedRegion.initPRInternals(PartitionedRegion.java:885) at org.apache.geode.internal.cache.PartitionedRegion.initialize(PartitionedRegion.java:1058) at org.apache.geode.internal.cache.GemFireCacheImpl.createVMRegion(GemFireCacheImpl.java:3308) at org.apache.geode.internal.cache.GemFireCacheImpl.basicCreateRegion(GemFireCacheImpl.java:3203) at org.apache.geode.internal.cache.GemFireCacheImpl.createRegion(GemFireCacheImpl.java:3191) at org.apache.geode.cache.RegionFactory.create(RegionFactory.java:762)
というわけで、合わせておきましょう、と。
では、とりあえずMember一覧を見てみましょう。
$ mvn compile exec:java -Dexec.mainClass=org.littlewings.geode.rebalancing.NoDataServer -Dexec.args=show-members self: no-data-server other: server-a978e278d01c other: locator-geodelocator
はい、一瞬だけですが3つになります。
データの配置状況を見てみます。
$ mvn compile exec:java -Dexec.mainClass=org.littlewings.geode.rebalancing.NoDataServer -Dexec.args=show-locate key = key1, value = value1 primary = server-a978e278d01c backup = [] key = key2, value = value2 primary = server-a978e278d01c backup = [] key = key3, value = value3 primary = server-a978e278d01c backup = [] key = key4, value = value4 primary = server-a978e278d01c backup = [] key = key5, value = value5 primary = server-a978e278d01c backup = [] key = key6, value = value6 primary = server-a978e278d01c backup = [] key = key7, value = value7 primary = server-a978e278d01c backup = [] key = key8, value = value8 primary = server-a978e278d01c backup = [] key = key9, value = value9 primary = server-a978e278d01c backup = [] key = key10, value = value10 primary = server-a978e278d01c backup = []
データが「server-a978e278d01c」にあることが確認できますね。「no-data-server」には割り当てられていません。
よって、実質Serverがひとつということになるので、バックアップは作られていません。
ここで、Serverをひとつ増やしてみます。
$ docker-compose scale server=2 Creating and starting geodecluster_server_2 ... done
gfshで見ると、このようになります。「server-8a580ed2f3f6」が追加Serverですね。
gfsh>list members Name | Id -------------------- | -------------------------------------------------------- locator-geodelocator | 172.19.0.2(locator-geodelocator:37:locator)<ec><v0>:1024 server-a978e278d01c | 172.19.0.3(server-a978e278d01c:139)<v3>:1024 server-8a580ed2f3f6 | 172.19.0.4(server-8a580ed2f3f6:39)<v18>:1024
データの配置状況を見ると、バックアップに追加したServerが割り当てられています。
key = key1, value = value1 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key2, value = value2 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key3, value = value3 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key4, value = value4 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key5, value = value5 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key6, value = value6 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key7, value = value7 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key8, value = value8 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key9, value = value9 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key10, value = value10 primary = server-a978e278d01c backup = [server-8a580ed2f3f6]
この挙動なんですけど、こちらのドキュメントに内容が書かれています。
Configure Member Join Redundancy Recovery for a Partitioned Region | Geode Docs
「startup-recovery-delay」という属性で、Regionにバックアップ数が満たされていなかった場合の挙動を設定することが
できます。
「startup-recovery-delay」はデフォルトでは「0」になっていて、つまり以下と同じです。
<region name="myRegion" refid="PARTITION"> <region-attributes> <partition-attributes redundant-copies="1" startup-recovery-delay="0"/> </region-attributes> </region>
この挙動を変える場合は「startup-recovery-delay」の値を変更するわけですが、「-1」にした場合はそもそもこの挙動が無効になります。
新しいServerが追加されても、リカバリは行われないと。0以上の値を指定した場合は、Serverが追加されてから指定した値(ミリ秒)が
経過した後にリカバリが行われます。デフォルトは0なので、Serverが追加されたら即時、ですね。
なお、これはリバランスではなくてリカバリなので、バックアップ数が満たされたこの状態でServerが増えても、実はなにも
変わらなかったりします。
3つ目のServerを追加してみましょう。
$ docker-compose scale server=3 Creating and starting geodecluster_server_3 ... done
「server-b5af22a32b74」が追加されました。
gfsh>list members Name | Id -------------------- | -------------------------------------------------------- locator-geodelocator | 172.19.0.2(locator-geodelocator:37:locator)<ec><v0>:1024 server-a978e278d01c | 172.19.0.3(server-a978e278d01c:139)<v3>:1024 server-8a580ed2f3f6 | 172.19.0.4(server-8a580ed2f3f6:39)<v18>:1024 server-b5af22a32b74 | 172.19.0.5(server-b5af22a32b74:39)<v21>:1024
データの配置状況を見てみます。
key = key1, value = value1 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key2, value = value2 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key3, value = value3 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key4, value = value4 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key5, value = value5 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key6, value = value6 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key7, value = value7 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key8, value = value8 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key9, value = value9 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key10, value = value10 primary = server-a978e278d01c backup = [server-8a580ed2f3f6]
「server-b5af22a32b74」は登場しません。つまり、Serverが増えたはいいですが、なにも変わっていないわけですね。
この状態を変えるには、リバランスします。
リバランス
リバランスは、gfshまたはAPIから可能です。というか、APIは先に載せてしまいましたが…。
ドキュメントは、こちら。
Rebalancing Partitioned Region Data | Geode Docs
リバランスを行うと、バックアップ数が満たされていない時に補充するとともに、Server間でのデータ量をバランシングし直します。
リバランスを行う…前に、シミュレーションをしてみましょう。
gfsh>rebalance --simulate Simulated partition regions /myRegion Rebalanced Stats | Value ----------------------------------------------------------------------------------------------- | ----- Total bytes in all redundant bucket copies created during this rebalance | 0 Total time (in milliseconds) spent creating redundant bucket copies during this rebalance | 0 Total number of redundant copies created during this rebalance | 0 Total bytes in buckets moved during this rebalance | 222 Total time (in milliseconds) spent moving buckets during this rebalance | 0 Total number of buckets moved during this rebalance | 140 Total time (in milliseconds) spent switching the primary state of buckets during this rebalance | 0 Total primaries transferred during this rebalance | 17 Total time (in milliseconds) for this rebalance | 0
こんな感じになるみたいです。
では、実行。
gfsh>rebalance Rebalanced partition regions /myRegion Rebalanced Stats | Value ----------------------------------------------------------------------------------------------- | ----- Total bytes in all redundant bucket copies created during this rebalance | 0 Total time (in milliseconds) spent creating redundant bucket copies during this rebalance | 0 Total number of redundant copies created during this rebalance | 0 Total bytes in buckets moved during this rebalance | 222 Total time (in milliseconds) spent moving buckets during this rebalance | 3806 Total number of buckets moved during this rebalance | 140 Total time (in milliseconds) spent switching the primary state of buckets during this rebalance | 482 Total primaries transferred during this rebalance | 17 Total time (in milliseconds) for this rebalance | 4357 gfsh>
4秒くらいかかりました…。
データの配置状況を見てみましょう。
key = key1, value = value1 primary = server-a978e278d01c backup = [server-b5af22a32b74] key = key2, value = value2 primary = server-b5af22a32b74 backup = [server-8a580ed2f3f6] key = key3, value = value3 primary = server-a978e278d01c backup = [server-b5af22a32b74] key = key4, value = value4 primary = server-b5af22a32b74 backup = [server-8a580ed2f3f6] key = key5, value = value5 primary = server-a978e278d01c backup = [server-b5af22a32b74] key = key6, value = value6 primary = server-b5af22a32b74 backup = [server-8a580ed2f3f6] key = key7, value = value7 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key8, value = value8 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key9, value = value9 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key10, value = value10 primary = server-a978e278d01c backup = [server-8a580ed2f3f6]
リバランスされたみたいですね。
APIの場合は、こうなります。
ResourceManager resourceManager = cache.getResourceManager();
RebalanceOperation operation = resourceManager.createRebalanceFactory().start();
RebalanceResults results = operation.getResults();
System.out.printf("Region[%s] Rebalance Results: totalBucketTransferBytes = %d, totalBucketCreatesCompleted = %d%n",
region.getName(),
results.getTotalBucketTransferBytes(),
results.getTotalBucketCreatesCompleted());
シミュレーションする場合は、startをsimulateに変えるのだとか。
RebalanceOperation operation = resourceManager.createRebalanceFactory().simulate();
で、リバランスについてもう少しドキュメントを見てみましょう。デフォルトでかからないあたり、なにかありそうですね?
Rebalancing Partitioned Region Data | Geode Docs
注意点として、リバランスの実行時はトランザクションが失敗するようになるらしいです。TransactionDataRebalancedExceptionがスローされると。
また、複数のRegionを並列にリバランスするには、「gemfire.resource.manager.threads」でスレッド数を調整することになるそうです。
リバランス中は、Read、Write操作は実行可能ですが、Functionの実行中にデータが移動した場合はパフォーマンスが低下する可能性があると。
各Serverのデータ保持量を調整する場合は、「partition-attributes」の「local-max-memory」で行いますと。
Serverがダウンした場合
最後に、Serverをダウンさせてみます。
scaleを2へ。
$ docker-compose scale server=2 Stopping and removing geodecluster_server_3 ...
1台いなくなりました。
gfsh>list members Name | Id -------------------- | -------------------------------------------------------- locator-geodelocator | 172.19.0.2(locator-geodelocator:37:locator)<ec><v0>:1024 server-a978e278d01c | 172.19.0.3(server-a978e278d01c:139)<v3>:1024 server-8a580ed2f3f6 | 172.19.0.4(server-8a580ed2f3f6:39)<v18>:1024
データの配置状況を見てみましょう。
key = key1, value = value1 primary = server-a978e278d01c backup = [] key = key2, value = value2 primary = server-8a580ed2f3f6 backup = [] key = key3, value = value3 primary = server-a978e278d01c backup = [] key = key4, value = value4 primary = server-8a580ed2f3f6 backup = [] key = key5, value = value5 primary = server-a978e278d01c backup = [] key = key6, value = value6 primary = server-8a580ed2f3f6 backup = [] key = key7, value = value7 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key8, value = value8 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key9, value = value9 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key10, value = value10 primary = server-a978e278d01c backup = [server-8a580ed2f3f6]
なんと、穴空きになります。バックアップが欠損した場合も補填されません。
リバランスすれば、バックアップも補填されたうえでバランシングされます。
gfsh>rebalance Rebalanced partition regions /myRegion Rebalanced Stats | Value ----------------------------------------------------------------------------------------------- | ----- Total bytes in all redundant bucket copies created during this rebalance | 222 Total time (in milliseconds) spent creating redundant bucket copies during this rebalance | 2431 Total number of redundant copies created during this rebalance | 100 Total bytes in buckets moved during this rebalance | 0 Total time (in milliseconds) spent moving buckets during this rebalance | 0 Total number of buckets moved during this rebalance | 0 Total time (in milliseconds) spent switching the primary state of buckets during this rebalance | 52 Total primaries transferred during this rebalance | 2 Total time (in milliseconds) for this rebalance | 391
結果。
key = key1, value = value1 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key2, value = value2 primary = server-8a580ed2f3f6 backup = [server-a978e278d01c] key = key3, value = value3 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key4, value = value4 primary = server-8a580ed2f3f6 backup = [server-a978e278d01c] key = key5, value = value5 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key6, value = value6 primary = server-8a580ed2f3f6 backup = [server-a978e278d01c] key = key7, value = value7 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key8, value = value8 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key9, value = value9 primary = server-a978e278d01c backup = [server-8a580ed2f3f6] key = key10, value = value10 primary = server-a978e278d01c backup = [server-8a580ed2f3f6]
この挙動についてですが、以下のドキュメントに記載があります。
Configure Member Crash Redundancy Recovery for a Partitioned Region | Geode Docs
「partition-attributes」の「recovery-delay」で調整します。デフォルトは、「recovery-delay」が「-1」となっており
Serverがダウンしてもなにも起こりません。
0以上を指定すると、Serverがダウンした時にバックアップを補填するようになります。
試してみましょう。例えば、次のような設定にします。
<region name="myRegion" refid="PARTITION"> <region-attributes> <partition-attributes redundant-copies="1" recovery-delay="1000"/> </region-attributes> </region>
1度クラスタを停止して、再度構成し直します。
クラスタのMember。
gfsh>list members Name | Id -------------------- | -------------------------------------------------------- locator-geodelocator | 172.19.0.2(locator-geodelocator:37:locator)<ec><v0>:1024 server-f300ccfee8dc | 172.19.0.3(server-f300ccfee8dc:138)<v3>:1024 server-a1eaffc17622 | 172.19.0.4(server-a1eaffc17622:39)<v4>:1024 server-803b5706988b | 172.19.0.5(server-803b5706988b:39)<v4>:1024
データの配置状況。
key = key1, value = value1 primary = server-a1eaffc17622 backup = [server-803b5706988b] key = key2, value = value2 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key3, value = value3 primary = server-803b5706988b backup = [server-a1eaffc17622] key = key4, value = value4 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key5, value = value5 primary = server-803b5706988b backup = [server-a1eaffc17622] key = key6, value = value6 primary = server-f300ccfee8dc backup = [server-a1eaffc17622] key = key7, value = value7 primary = server-f300ccfee8dc backup = [server-803b5706988b] key = key8, value = value8 primary = server-f300ccfee8dc backup = [server-a1eaffc17622] key = key9, value = value9 primary = server-f300ccfee8dc backup = [server-803b5706988b] key = key10, value = value10 primary = server-803b5706988b backup = [server-f300ccfee8dc]
1台停止。
$ docker-compose scale server=2 Stopping and removing geodecluster_server_3 ...
「server-803b5706988b」がいなくなりました。
gfsh>list members Name | Id -------------------- | -------------------------------------------------------- locator-geodelocator | 172.19.0.2(locator-geodelocator:37:locator)<ec><v0>:1024 server-f300ccfee8dc | 172.19.0.3(server-f300ccfee8dc:138)<v3>:1024 server-a1eaffc17622 | 172.19.0.4(server-a1eaffc17622:39)<v4>:1024
データの配置状況を見てみましょう。
key = key1, value = value1 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key2, value = value2 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key3, value = value3 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key4, value = value4 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key5, value = value5 primary = server-a1eaffc17622 backup = [server-f300ccfee8dc] key = key6, value = value6 primary = server-f300ccfee8dc backup = [server-a1eaffc17622] key = key7, value = value7 primary = server-f300ccfee8dc backup = [server-a1eaffc17622] key = key8, value = value8 primary = server-f300ccfee8dc backup = [server-a1eaffc17622] key = key9, value = value9 primary = server-f300ccfee8dc backup = [server-a1eaffc17622] key = key10, value = value10 primary = server-f300ccfee8dc backup = [server-a1eaffc17622]
バックアップが補填されていますね。