1概要


Apache Geode

は、キャッシングとデータ計算をサポートする分散型インメモリデータグリッドです。

このチュートリアルでは、Geodeの重要な概念をカバーし、そのJavaクライアントを使用していくつかのコードサンプルを実行します。


2セットアップ

まず、Apache Geodeをダウンロードしてインストールし、

__ gfsh


environmentを設定する必要があります。これを行うには、http://geode.apache.org/docs/guide/16/getting

started/15

minute

quickstart__gfsh.html[Geode’s official guide]の手順に従ってください。

そして第二に、このチュートリアルはいくつかのファイルシステムアーティファクトを作成します。そのため、一時ディレクトリを作成してそこから起動することでそれらを分離できます。


2.1. インストールと設定

一時ディレクトリから

Locator

インスタンスを起動する必要があります。

gfsh> start locator --name=locator --bind-address=localhost


  • ロケーター

    は、Geode

    Cluster

    の異なるメンバー間の調整を担当します。

次に、1つ以上のデータをホストする

Server

インスタンスを起動しましょう

__Region

__s:

gfsh> start server --name=server1 --server-port=0

Geodeが使用可能なポートを選択するように、

– server-port

オプションを0に設定します。省略した場合でも、サーバーはデフォルトのポート40404を使用します。

そして最後に、

Region

が必要です。

gfsh> create region --name=baeldung --type=REPLICATE


Region

は最終的にデータを保存する場所です。


2.2. 検証

先に進む前に、すべてがうまくいっていることを確認しましょう。

まず、

__ Server




Locator__があるかどうか確認しましょう。

gfsh> list members
 Name   | Id
------- | ----------------------------------------------------------
server1 | 192.168.0.105(server1:6119)<v1>:1024
locator | 127.0.0.1(locator:5996:locator)<ec><v0>:1024[Coordinator]----

そして次に、私たちには__Region__があります。

[source,text,gutter:,true]

gfsh> describe region –name=baeldung

Name            : baeldung
Data Policy     : replicate
Hosting Members : server1

Non-Default Attributes Shared By Hosting Members

 Type  |    Name     | Value
------ | ----------- | ---------------
Region | data-policy | REPLICATE
       | size        | 0
       | scope       | distributed-ack
----

また、「locator」および「server1」という名前の一時ディレクトリの下に、ファイルシステム上にいくつかのディレクトリがあるはずです。

この出力で、私たちは先に進む準備ができていることがわかります。

===  **  3 Mavenの依存関係**

実行中のGeodeができたので、クライアントコードを見てみましょう。

JavaコードでGeodeを使用するには、https://search.maven.org/search?q=a:geode-core[Apache Geode Javaクライアント]ライブラリを__pom__に追加する必要があります。

[source,text,gutter:,true]

----
<dependency>
     <groupId>org.apache.geode</groupId>
     <artifactId>geode-core</artifactId>
     <version>1.6.0</version>
</dependency>
----

まず、いくつかの地域にデータを保存して取得することから始めましょう。

[[hello-baeldung]]

===  **  4簡単な保管と検索**

単一の値、一連の値、カスタムオブジェクトを保存する方法を説明しましょう。

私たちの“ baeldung”地域にデータを保存し始めるために、ロケーターを使ってそれに接続しましょう:

[source,java,gutter:,true]

----
@Before
public void connect() {
    this.cache = new ClientCacheFactory()
      .addPoolLocator("localhost", 10334)
        .create();
    this.region = cache.<String, String>
      createClientRegionFactory(ClientRegionShortcut.CACHING__PROXY)
        .create("baeldung");
}
----

[[saving-single-value]]

====  **  4.1. 個別値の保存**

これで、地域内のデータを単純に格納および取得できます。

[source,java,gutter:,true]

----
@Test
public void whenSendMessageToRegion__thenMessageSavedSuccessfully() {

    this.region.put("A", "Hello");
    this.region.put("B", "Baeldung");

    assertEquals("Hello", region.get("A"));
    assertEquals("Baeldung", region.get("B"));
}
----

====  **  4.2. 一度に複数の値を保存する**

ネットワークの待ち時間を減らそうとしているときなど、一度に複数の値を保存することもできます。

[source,java,gutter:,true]

----
@Test
public void whenPutMultipleValuesAtOnce__thenValuesSavedSuccessfully() {

    Supplier<Stream<String>> keys = () -> Stream.of("A", "B", "C", "D", "E");
    Map<String, String> values = keys.get()
        .collect(Collectors.toMap(Function.identity(), String::toLowerCase));

    this.region.putAll(values);

    keys.get()
        .forEach(k -> assertEquals(k.toLowerCase(), this.region.get(k)));
}
----

====  **  4.3. カスタムオブジェクトを保存する**

文字列は便利ですが、後でではなく、すぐにカスタムオブジェクトを保存する必要があります。

次のキータイプを使用して保存したい顧客レコードがあるとしましょう。

[source,java,gutter:,true]

----
public class CustomerKey implements Serializable {
    private long id;
    private String country;

   //getters and setters
   //equals and hashcode
}
----

そして、次の値型

[source,java,gutter:,true]

----
public class Customer implements Serializable {
    private CustomerKey key;
    private String firstName;
    private String lastName;
    private Integer age;

   //getters and setters
}
----

これらを保存できるようにするには、いくつかの追加ステップがあります。

まず、** ** 彼らは__Serializable__を実装するべきです。 ** ** これは厳密な要件ではありませんが、__Serializableにすることで__ https://geode.apache.org/docs/guide/16/developing/data__serialization/data__serialization__options.html[Geodeはそれらをより堅牢に格納できます]。

次に、** これらはアプリケーションのクラスパスと、Geode __Server__ ** のクラスパスに存在する必要があります。

それらをサーバーのクラスパスに到達させるために、それらをパッケージ化しましょう。

そして、新しい__start server__コマンドで結果のjarを参照できます。

[source,text,gutter:,true]

----
gfsh> stop server --name=server1
gfsh> start server --name=server1 --classpath=../lib/apache-geode-1.0-SNAPSHOT.jar --server-port=0
----

繰り返しますが、これらのコマンドは一時ディレクトリから実行する必要があります。

最後に、「baeldung」リージョンの作成に使用したのと同じコマンドを使用して、__Server__に「baeldung-customers」という名前の新しい__Region__を作成しましょう。

[source,bash,gutter:,true]

----
gfsh> create region --name=baeldung-customers --type=REPLICATE
----

コードでは、以前と同様にカスタムタイプを指定してロケータにアクセスします。

[source,java,gutter:,true]

----
@Before
public void connect() {
   //... connect through the locator
    this.customerRegion = this.cache.<CustomerKey, Customer>
      createClientRegionFactory(ClientRegionShortcut.CACHING__PROXY)
        .create("baeldung-customers");
}
----

そしてそれから、私たちは以前と同じように顧客を保管することができます。

[source,java,gutter:,true]

----
@Test
public void whenPutCustomKey__thenValuesSavedSuccessfully() {
    CustomerKey key = new CustomerKey(123);
    Customer customer = new Customer(key, "William", "Russell", 35);

    this.customerRegion.put(key, customer);

    Customer storedCustomer = this.customerRegion.get(key);
    assertEquals("William", storedCustomer.getFirstName());
    assertEquals("Russell", storedCustomer.getLastName());
}
----

===  **  5地域タイプ**

ほとんどの環境では、読み取りおよび書き込みのスループット要件に応じて、リージョンのコピーを1つ以上、またはパーティションを複数作成します。

これまでは、メモリ内の複製領域を使用してきました。詳しく見てみましょう。

====  **  5.1. 複製領域**

その名前が示すように、** **  __複製領域__はそのデータのコピーを複数の__サーバー__に保持します。 ** ** これをテストしましょう。

作業ディレクトリの____gfsh ____consoleから、クラスタに__server2__という名前の__Server__をもう1つ追加します。

[source,text,gutter:,true]

----
gfsh> start server --name=server2 --classpath=../lib/apache-geode-1.0-SNAPSHOT.jar --server-port=0
----

“ baeldung”を作ったとき、私たちは__ – type = REPLICATE__を使ったことを思い出してください。

このため、Geodeは自動的にデータを新しいサーバーに複製します。

__server1を停止してこれを確認しましょう。

[source,text,gutter:,true]

----
gfsh> stop server --name=server1
----

それから、「baeldung」地域で簡単なクエリを実行しましょう。

データが正常に複製されたら、結果が返されます。

[source,text,gutter:,true]

----
gfsh> query --query='select e.key from/baeldung.entries e'
Result : true
Limit  : 100
Rows   : 5

Result
------
C
B
A
E
D
----

つまり、複製は成功したようです。

この地域にレプリカを追加すると、データの可用性が向上します。また、複数のサーバーがクエリに応答できるため、読み取りのスループットも向上します。

しかし、** ** 両方がクラッシュした場合はどうなりますか?これらはメモリ内の領域なので、データは失われます____.____ ** ** これの代わりに、複製中にデータをディスクに格納する__ – type = REPLICATE__PERSISTENT__を代わりに使用できます。

====  **  5.2. 分割領域**

大規模なデータセットでは、地域を別々のパーティション、つまりバケットに分割するようにGeodeを設定することで、システムをより良く拡張できます。

“ baeldung-partition”という名前のパーティション化された__Region__を1つ作成しましょう。

[source,text,gutter:,true]

----
gfsh> create region --name=baeldung-partitioned --type=PARTITION
----

データを追加してください。

[source,text,gutter:,true]

----
gfsh> put --region=baeldung-partitioned --key="1" --value="one"
gfsh> put --region=baeldung-partitioned --key="2" --value="two"
gfsh> put --region=baeldung-partitioned --key="3" --value="three"
----

そしてすぐに確認:

[source,text,gutter:,true]

----
gfsh> query --query='select e.key, e.value from/baeldung-partitioned.entries e'
Result : true
Limit  : 100
Rows   : 3

key | value
--- | -----
2   | two
1   | one
3   | three
----

次に、データがパーティション分割されたことを確認するために、もう一度__server1__を停止して、クエリをやり直します。

[source,text,gutter:,true]

----
gfsh> stop server --name=server1
gfsh> query --query='select e.key, e.value from/baeldung-partitioned.entries e'
Result : true
Limit  : 100
Rows   : 1

key | value
--- | -----
2   | two
----

このサーバーにはデータのパーティションが1つしかないため、今回は一部のデータエントリしか取得できませんでした。したがって、__server1__が削除されると、そのデータは失われました。

** しかし、パーティション化と冗長性の両方が必要な場合はどうなりますか?**  Geodeはhttps://geode.apache.org/docs/guide/11/reference/topics/region__shortcuts__reference.html[その他の多くの種類]もサポートします。次の3つが便利です。

**  __PARTITION__REDUNDANT__パーティション__および__は、データを複製します。

クラスタの異なるメンバー
**  __PARTITION__PERSISTENT__は__PARTITION__のようにデータを分割しますが、

ディスク
**  ____PARTITION__REDUNDANT__PERSISTENT ____は3つすべての動作を示します。

===  **  6. オブジェクト照会言語**

Geodeはまた、Object Query Language(OQL)もサポートしています。これは、単純なキー検索よりも強力です。 SQLに少し似ています。

この例では、先ほど作成した「baeldung-customer」地域を使用しましょう。

さらに2、3人の顧客を追加すると、

[source,java,gutter:,true]

----
Map<CustomerKey, Customer> data = new HashMap<>();
data.put(new CustomerKey(1), new Customer("Gheorge", "Manuc", 36));
data.put(new CustomerKey(2), new Customer("Allan", "McDowell", 43));
this.customerRegion.putAll(data);
----

次に、__QueryService__を使用して、名前が「Allan」の顧客を見つけます。

[source,java,gutter:,true]

----
QueryService queryService = this.cache.getQueryService();
String query =
  "select **  from/baeldung-customers c where c.firstName = 'Allan'";
SelectResults<Customer> results =
  (SelectResults<Customer>) queryService.newQuery(query).execute();
assertEquals(1, results.size());
----

===  **  7. 関数**

インメモリデータグリッドのより強力な概念の1つは、「データを計算する」という考え方です。

簡単に言えば、Geodeは純粋なJavaなので、データを送信するだけでなく、そのデータに対して実行するロジックも簡単に作成できます。

これは、PL-SQLやTransact-SQLのようなSQL拡張の考え方を思い出させるかもしれません。

====  **  7.1. 関数を定義する**

Geodeが行うべき作業単位を定義するために、Geodeの__Function__インターフェースを実装します。

たとえば、顧客の名前をすべて大文字に変更する必要があるとします。

データを照会してアプリケーションに処理を任せる代わりに、__Function__を実装することができます。

[source,java,gutter:,true]

----
public class UpperCaseNames implements Function<Boolean> {
    @Override
    public void execute(FunctionContext<Boolean> context) {
        RegionFunctionContext regionContext = (RegionFunctionContext) context;
        Region<CustomerKey, Customer> region = regionContext.getDataSet();

        for ( Map.Entry<CustomerKey, Customer> entry : region.entrySet() ) {
            Customer customer = entry.getValue();
            customer.setFirstName(customer.getFirstName().toUpperCase());
        }
        context.getResultSender().lastResult(true);
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}
----

**  ____getId ____は一意の値を返さなければならないので、通常はクラス名が適切です。

__FunctionContext__にはすべての地域データが含まれているので、そこからより洗練されたクエリを実行することも、ここで行ったようにそれを変更することもできます。

そして__Function__にはこれ以上の力があるので、https://gemfire.docs.pivotal.io/95/geode/developing/function__exec/function__execution.html[公式マニュアル]、特にhttps://geode.apacheを調べてください。 org/release/latest/javadoc/org/apache/geode/cache/execute/FunctionContext.html#getResultSender  - [__getResultSender__メソッド]。

====  **  7.2. 機能のデプロイ**

実行できるようにするには、Geodeに自分の機能を認識させる必要があります。カスタムデータ型で行ったように、jarをパッケージ化します。

しかし今回は、__deploy__コマンドを使用することができます。

[source,text,gutter:,true]

----
gfsh> deploy --jar=./lib/apache-geode-1.0-SNAPSHOT.jar
----

====  **  7.3. 実行機能**

これで、__FunctionServiceを使用してアプリケーションから__Function__を実行できます。

[source,java,gutter:,true]

----
@Test
public void whenExecuteUppercaseNames__thenCustomerNamesAreUppercased() {
    Execution execution = FunctionService.onRegion(this.customerRegion);
    execution.execute(UpperCaseNames.class.getName());
    Customer customer = this.customerRegion.get(new CustomerKey(1));
    assertEquals("GHEORGE", customer.getFirstName());
}
----

===  **  8結論**

この記事では、Apache Geodeエコシステムの基本概念を学びました。私たちは標準的な型とカスタム型、複製されパーティション化された領域、そしてoqlと関数のサポートによる単純なgetとputを調べました。

そしていつものように、これらのサンプルはすべてhttps://github.com/eugenp/tutorials/tree/master/apache-geode[GitHubで利用可能]です。