Hazelcast

Hazelcast

# Hazelcast

# goal

Hazelcastをjavaで動かす.

# What Hazelcast

  • インメモリ・データグリッドのフレームワーク
  • オープンソース
  • javaで動く.

# What in-memory data grid

  • キーと値の1対1でデータを管理
  • 極めて単純なデータ構造であり, メモリ上で動かすので, データ参照, 更新が速い
  • 検索やトランザクション管理には向いていない(というか, そんな機能ない?)
  • メモリーにデータを分散して管理する.
  • パーティションもできる.

# GetStarted

Get Started with Hazelcast IMDG

# IntelliJの設定

  • ここからHazelcast IMDGのzipをダウンロード, 解凍

  • intelliJで, プロジェクトを作成.

  • プロジェクト作成後, クラスパスを指定

    • Project Structure -> Platform Setting -> SDKs -> 9.0 -> Classpathから「+」ボタンを押す.
    • ダウンロードし, 解答した「hazelcast-3.9.x」フォルダの「lib/hazelcast-3.9.1.jar」ファイルを指定し, 追加.

# サーバーのたて方

  • 新しいjavaファイルを作成. javaのファイル名を「GettingStarted.java」にし, 以下のコードを追加
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.hazelcast.core.*;
import com.hazelcast.config.*;

import java.util.Map;
import java.util.Queue;

public class GettingStarted {
    public static void main(String[] args) {
        Config cfg = new Config();
        HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
        Map<Integer, String> mapCustomers = instance.getMap("customers");
        mapCustomers.put(1, "Joe");
        mapCustomers.put(2, "Ali");
        mapCustomers.put(3, "Avi");
 
        System.out.println("Customer with key 1: "+ mapCustomers.get(1));
        System.out.println("Map Size:" + mapCustomers.size());
 
        Queue<String> queueCustomers = instance.getQueue("customers");
        queueCustomers.offer("Tom");
        queueCustomers.offer("Mary");
        queueCustomers.offer("Jane");
        System.out.println("First customer: " + queueCustomers.poll());
        System.out.println("Second customer: "+ queueCustomers.peek());
        System.out.println("Queue size: " + queueCustomers.size());
    }
}

実行結果

1
2
3
4
5
6
7
8
9
Members {size:1, ver:1} [
	Member [192.168.0.5]:5701 - f2eb4e2f-028e-4cf4-af5a-005c27591655 this
]

Customer with key 1: Joe
Map Size:3
First customer: Tom
Second customer: Mary
Queue size: 2

2台目

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Members {size:2, ver:2} [
	Member [192.168.0.5]:5701 - f2eb4e2f-028e-4cf4-af5a-005c27591655
	Member [192.168.0.5]:5702 - dc880f43-e9d4-4ad4-8428-2ca2d9732aa7 this
]

12月 29, 2017 5:09:32 午後 com.hazelcast.core.LifecycleService
情報: [192.168.0.5]:5702 [dev] [3.9.1] [192.168.0.5]:5702 is STARTED
Customer with key 1: Joe
Map Size:3
First customer: Mary
Second customer: Jane
Queue size: 4

mapは, <Integer, String>である. そのため, 2台目の場合は上書きしているだけなので, MapSizeは変わらない.

Queueはpushしているので, 2台目のデータの数と同じである.

# クライアントの動かし方

  • 新しいjavaファイルを作成. javaのファイル名を「GettingStartedClient.java」にし, 以下のコードを追加
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package com.hazelcast.test;
 
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
 
public class GettingStartedClient {
    public static void main(String[] args) {
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.addAddress("127.0.0.1:5701");
        HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
        IMap map = client.getMap("customers");
        IQueue queue = client.getQueue("customers");
        System.out.println("Map Size : " + map.size());
        System.out.println("mapCustomers 1 : " + map.get(1));
        System.out.println("Queue Size : " + queue.size());
        System.out.println("queueCustomers poll : " + queue.poll());
    }
}

実行結果

1
2
3
4
5
6
7
8
9
Members [3] {
	Member [192.168.0.5]:5701 - f2eb4e2f-028e-4cf4-af5a-005c27591655
	Member [192.168.0.5]:5702 - dc880f43-e9d4-4ad4-8428-2ca2d9732aa7
}

Map Size : 3
mapCustomers 1 : Joe
Queue Size : 4
queueCustomers poll : Mary

とりあえず, サーバーで指定したgetMap(String)のStringと同じ名前でgetMap(String)すれば, 同じMapが取れる.

# 内部について

この2サイトに詳しい説明が書いてある.

パーティションでデータを保存しているため, 例えば4つサーバー(Node)をたて, そのうちのサーバー(Node)が1つなくなったとしても, map, queueに入れたデータは残る.

HazelcastはNodeを起動すると、指定された方法に沿って他のNodeを見つけ出し、クラスタを構成します。 <略> デフォルトで選択されているのは、マルチキャストです。

#ref(http://cdn-ak.f.st-hatena.com/images/fotolife/K/Kazuhira/20160928/20160928233825.jpg,left,nowrap,画像)

# 教えてもらったもの

このリンク先の記事がとっても役に立つらしい

# goal2 先輩の手伝い

1.以下のテストを書いてほしいです。

 ・1つのローカル内で2つのノードに見立てて立ち上げ、データをやりとりします  ・相手ノードのノード名と相手側のデータの2つの入力が揃ったらそれを表示します  ・データをインクリメントしてそれを繰り返します     インプット:     1     アウトプット:     A : 1     B: 2     A : 3     B: 4     A : 5     B : 6     A: 7     B : 8     A: 9

2.調査:ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?

3.調査:送信するデータを圧縮したいとき、それをサポートする機能はあるか?

# 1 コード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package jp.ac.uryukyu.ie.aka;
import com.hazelcast.core.*;
import com.hazelcast.config.*;

public class Incrementer {


    public static void main(String[] args){
        int initData = 0; // dataの初期値
        int maxData = 10; // dataの最大値
        int nodeNum = 2; // 最終的なnodeの数
        char nodeBaseName = 'A';

         // nodeの生成
         Config config = new Config();
         HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);

         // 名前の生成とアウトプット
         int memberSize = instance.getCluster().getMembers().size();
         String localName = String.valueOf((char)(nodeBaseName + memberSize - 1));
         String remoteName = String.valueOf((char)(nodeBaseName + memberSize % nodeNum));

         System.out.println("local  : " + localName);
         System.out.println("remote : " + remoteName);

         // 自分と相手のデータ構造体Topicの作成, get
        ITopic<Integer> localTopic = instance.getTopic(localName);
        ITopic<Integer> remoteTopic = instance.getTopic(remoteName);

        // 自分のTopicはリッスンする.
        localTopic.addMessageListener(message -> {

            // 送られてきたデータを受け取る
            int data = message.getMessageObject();
            System.out.println("from : " + remoteTopic.getName());
            System.out.println("data : " + data);

            // maxDataに到達するまで, 相手にdata + 1を送り, 到達したら全てのnodeをshutdownする.
            if(data < maxData) {
                remoteTopic.publish(data + 1);
            }else{
                //instance.getLifecycleService().terminate();
                Hazelcast.shutdownAll();
            }
        });

        // 相手のTopicにデータを送る.
        remoteTopic.publish(initData);
    }

}

# 実行結果

Node A

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
local  : A
remote : B

Members {size:2, ver:2} [
	Member [10.10.10.167]:5701 - 30098b8c-ebaf-479a-85ed-6ff96389151a this
	Member [10.10.10.167]:5702 - d7d30c33-ee10-43d8-aab4-b90f8a9fa513
]

from : B 
data : 0
from : B
data : 2
from : B
data : 4
from : B
data : 6
from : B
data : 8
from : B
data : 10

Node B

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Members {size:2, ver:2} [
	Member [10.10.10.167]:5701 - 30098b8c-ebaf-479a-85ed-6ff96389151a
	Member [10.10.10.167]:5702 - d7d30c33-ee10-43d8-aab4-b90f8a9fa513 this
]

local  : B
remote : A
from : A
data : 1
from : A
data : 3
from : A
data : 5
from : A
data : 7
from : A
data : 9

# 2. ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?

Q: ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?

A: 読めてないけど解説はありました.

http://docs.hazelcast.org/docs/latest-development/manual/html/Hazelcast_Overview/Hazelcast_Topology.html

ただ, AliceのTopologyManagerみたいなものはなく, プログラムで指定するっぽい…多分.

http://docs.hazelcast.org/docs/latest-development/manual/html/Setting_Up_Clusters/Creating_Cluster_Groups.html

# 3. 送信するデータを圧縮したいとき、それをサポートする機能はあるか?

Q: 送信するデータを圧縮したいとき、それをサポートする機能はあるか?

A: あるっぽいです.

https://blog.hazelcast.com/kryo-serializer/

Kryoというシリアライズ + 圧縮をするフレームワーク? 的なものがJavaの外部フレームワークにあるらしく, それを用いるそうです.

# 参考サイト

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy