0
|
1 # Hazelcast
|
|
2
|
|
3 ## goal
|
|
4 Hazelcastをjavaで動かす.
|
|
5
|
|
6 ## What Hazelcast
|
|
7
|
|
8 - インメモリ・データグリッドのフレームワーク
|
|
9 - オープンソース
|
|
10 - javaで動く.
|
|
11
|
|
12 ## What in-memory data grid
|
|
13
|
|
14 - キーと値の1対1でデータを管理
|
|
15 - 極めて単純なデータ構造であり, メモリ上で動かすので, データ参照, 更新が速い
|
|
16 - 検索やトランザクション管理には向いていない(というか, そんな機能ない?)
|
|
17 - メモリーにデータを分散して管理する.
|
|
18 - パーティションもできる.
|
|
19
|
|
20 ## GetStarted
|
|
21 [[Get Started with Hazelcast IMDG:https://hazelcast.org/getting-started-with-hazelcast/]]
|
|
22
|
|
23 ### IntelliJの設定
|
|
24 - [[ここ:https://hazelcast.org/download/]]からHazelcast IMDGのzipをダウンロード, 解凍
|
|
25
|
|
26 - intelliJで, プロジェクトを作成.
|
|
27
|
|
28 - プロジェクト作成後, クラスパスを指定
|
|
29 - Project Structure -> Platform Setting -> SDKs -> 9.0 -> Classpathから「+」ボタンを押す.
|
|
30 - ダウンロードし, 解答した「hazelcast-3.9.x」フォルダの「lib/hazelcast-3.9.1.jar」ファイルを指定し, 追加.
|
|
31
|
|
32 ### サーバーのたて方
|
|
33 - 新しいjavaファイルを作成. javaのファイル名を「GettingStarted.java」にし, 以下のコードを追加
|
|
34
|
|
35
|
|
36 ```java
|
|
37 import com.hazelcast.core.*;
|
|
38 import com.hazelcast.config.*;
|
|
39
|
|
40 import java.util.Map;
|
|
41 import java.util.Queue;
|
|
42
|
|
43 public class GettingStarted {
|
|
44 public static void main(String[] args) {
|
|
45 Config cfg = new Config();
|
|
46 HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
|
|
47 Map<Integer, String> mapCustomers = instance.getMap("customers");
|
|
48 mapCustomers.put(1, "Joe");
|
|
49 mapCustomers.put(2, "Ali");
|
|
50 mapCustomers.put(3, "Avi");
|
|
51
|
|
52 System.out.println("Customer with key 1: "+ mapCustomers.get(1));
|
|
53 System.out.println("Map Size:" + mapCustomers.size());
|
|
54
|
|
55 Queue<String> queueCustomers = instance.getQueue("customers");
|
|
56 queueCustomers.offer("Tom");
|
|
57 queueCustomers.offer("Mary");
|
|
58 queueCustomers.offer("Jane");
|
|
59 System.out.println("First customer: " + queueCustomers.poll());
|
|
60 System.out.println("Second customer: "+ queueCustomers.peek());
|
|
61 System.out.println("Queue size: " + queueCustomers.size());
|
|
62 }
|
|
63 }
|
|
64 ```
|
|
65
|
|
66 実行結果
|
|
67
|
|
68 ```
|
|
69 Members {size:1, ver:1} [
|
|
70 Member [192.168.0.5]:5701 - f2eb4e2f-028e-4cf4-af5a-005c27591655 this
|
|
71 ]
|
|
72
|
|
73 Customer with key 1: Joe
|
|
74 Map Size:3
|
|
75 First customer: Tom
|
|
76 Second customer: Mary
|
|
77 Queue size: 2
|
|
78 ```
|
|
79
|
|
80
|
|
81 2台目
|
|
82
|
|
83
|
|
84 ```
|
|
85 Members {size:2, ver:2} [
|
|
86 Member [192.168.0.5]:5701 - f2eb4e2f-028e-4cf4-af5a-005c27591655
|
|
87 Member [192.168.0.5]:5702 - dc880f43-e9d4-4ad4-8428-2ca2d9732aa7 this
|
|
88 ]
|
|
89
|
|
90 12月 29, 2017 5:09:32 午後 com.hazelcast.core.LifecycleService
|
|
91 情報: [192.168.0.5]:5702 [dev] [3.9.1] [192.168.0.5]:5702 is STARTED
|
|
92 Customer with key 1: Joe
|
|
93 Map Size:3
|
|
94 First customer: Mary
|
|
95 Second customer: Jane
|
|
96 Queue size: 4
|
|
97 ```
|
|
98
|
|
99 mapは, <Integer, String>である. そのため, 2台目の場合は上書きしているだけなので, MapSizeは変わらない.
|
|
100
|
|
101 Queueはpushしているので, 2台目のデータの数と同じである.
|
|
102
|
|
103 ### クライアントの動かし方
|
|
104 - 新しいjavaファイルを作成. javaのファイル名を「GettingStartedClient.java」にし, 以下のコードを追加
|
|
105
|
|
106 ```java
|
|
107 package com.hazelcast.test;
|
|
108
|
|
109 import com.hazelcast.client.config.ClientConfig;
|
|
110 import com.hazelcast.client.HazelcastClient;
|
|
111 import com.hazelcast.core.HazelcastInstance;
|
|
112 import com.hazelcast.core.IMap;
|
|
113
|
|
114 public class GettingStartedClient {
|
|
115 public static void main(String[] args) {
|
|
116 ClientConfig clientConfig = new ClientConfig();
|
|
117 clientConfig.addAddress("127.0.0.1:5701");
|
|
118 HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
|
|
119 IMap map = client.getMap("customers");
|
|
120 IQueue queue = client.getQueue("customers");
|
|
121 System.out.println("Map Size : " + map.size());
|
|
122 System.out.println("mapCustomers 1 : " + map.get(1));
|
|
123 System.out.println("Queue Size : " + queue.size());
|
|
124 System.out.println("queueCustomers poll : " + queue.poll());
|
|
125 }
|
|
126 }
|
|
127 ```
|
|
128
|
|
129 実行結果
|
|
130
|
|
131 ```
|
|
132 Members [3] {
|
|
133 Member [192.168.0.5]:5701 - f2eb4e2f-028e-4cf4-af5a-005c27591655
|
|
134 Member [192.168.0.5]:5702 - dc880f43-e9d4-4ad4-8428-2ca2d9732aa7
|
|
135 }
|
|
136
|
|
137 Map Size : 3
|
|
138 mapCustomers 1 : Joe
|
|
139 Queue Size : 4
|
|
140 queueCustomers poll : Mary
|
|
141 ```
|
|
142
|
|
143 とりあえず, サーバーで指定したgetMap(String)のStringと同じ名前でgetMap(String)すれば, 同じMapが取れる.
|
|
144
|
|
145 ## 内部について
|
|
146 この2サイトに詳しい説明が書いてある.
|
|
147 - http://d.hatena.ne.jp/Kazuhira/20160928/1475077755
|
|
148 - http://d.hatena.ne.jp/Kazuhira/20161028/1477663801
|
|
149
|
|
150 パーティションでデータを保存しているため, 例えば4つサーバー(Node)をたて, そのうちのサーバー(Node)が1つなくなったとしても, map, queueに入れたデータは残る.
|
|
151
|
|
152 > HazelcastはNodeを起動すると、指定された方法に沿って他のNodeを見つけ出し、クラスタを構成します。 <略> デフォルトで選択されているのは、マルチキャストです。
|
|
153
|
|
154 #ref(http://cdn-ak.f.st-hatena.com/images/fotolife/K/Kazuhira/20160928/20160928233825.jpg,left,nowrap,画像)
|
|
155
|
|
156 ## 教えてもらったもの
|
|
157 このリンク先の記事がとっても役に立つらしい
|
|
158 - https://hazelcast.com/resources/hazelcast-jet-datasheet/
|
|
159
|
|
160 ## goal2 先輩の手伝い
|
|
161 1.以下のテストを書いてほしいです。
|
|
162
|
|
163 ・1つのローカル内で2つのノードに見立てて立ち上げ、データをやりとりします
|
|
164 ・相手ノードのノード名と相手側のデータの2つの入力が揃ったらそれを表示します
|
|
165 ・データをインクリメントしてそれを繰り返します
|
2
|
166 ```
|
0
|
167 インプット:
|
|
168 1
|
|
169 アウトプット:
|
|
170 A : 1
|
|
171 B: 2
|
|
172 A : 3
|
|
173 B: 4
|
|
174 A : 5
|
|
175 B : 6
|
|
176 A: 7
|
|
177 B : 8
|
|
178 A: 9
|
2
|
179 ```
|
0
|
180
|
|
181
|
|
182 2.調査:ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?
|
|
183
|
|
184 3.調査:送信するデータを圧縮したいとき、それをサポートする機能はあるか?
|
|
185
|
|
186
|
|
187 ## 1 コード
|
|
188
|
|
189
|
|
190 ```java
|
|
191 package jp.ac.uryukyu.ie.aka;
|
|
192 import com.hazelcast.core.*;
|
|
193 import com.hazelcast.config.*;
|
|
194
|
|
195 public class Incrementer {
|
|
196
|
|
197
|
|
198 public static void main(String[] args){
|
|
199 int initData = 0; // dataの初期値
|
|
200 int maxData = 10; // dataの最大値
|
|
201 int nodeNum = 2; // 最終的なnodeの数
|
|
202 char nodeBaseName = 'A';
|
|
203
|
|
204 // nodeの生成
|
|
205 Config config = new Config();
|
|
206 HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
|
|
207
|
|
208 // 名前の生成とアウトプット
|
|
209 int memberSize = instance.getCluster().getMembers().size();
|
|
210 String localName = String.valueOf((char)(nodeBaseName + memberSize - 1));
|
|
211 String remoteName = String.valueOf((char)(nodeBaseName + memberSize % nodeNum));
|
|
212
|
|
213 System.out.println("local : " + localName);
|
|
214 System.out.println("remote : " + remoteName);
|
|
215
|
|
216 // 自分と相手のデータ構造体Topicの作成, get
|
|
217 ITopic<Integer> localTopic = instance.getTopic(localName);
|
|
218 ITopic<Integer> remoteTopic = instance.getTopic(remoteName);
|
|
219
|
|
220 // 自分のTopicはリッスンする.
|
|
221 localTopic.addMessageListener(message -> {
|
|
222
|
|
223 // 送られてきたデータを受け取る
|
|
224 int data = message.getMessageObject();
|
|
225 System.out.println("from : " + remoteTopic.getName());
|
|
226 System.out.println("data : " + data);
|
|
227
|
|
228 // maxDataに到達するまで, 相手にdata + 1を送り, 到達したら全てのnodeをshutdownする.
|
|
229 if(data < maxData) {
|
|
230 remoteTopic.publish(data + 1);
|
|
231 }else{
|
|
232 //instance.getLifecycleService().terminate();
|
|
233 Hazelcast.shutdownAll();
|
|
234 }
|
|
235 });
|
|
236
|
|
237 // 相手のTopicにデータを送る.
|
|
238 remoteTopic.publish(initData);
|
|
239 }
|
|
240
|
|
241 }
|
|
242 ```
|
|
243
|
|
244
|
|
245
|
|
246 ## 実行結果
|
|
247
|
|
248 ```
|
|
249 Node A
|
|
250
|
|
251 local : A
|
|
252 remote : B
|
|
253
|
|
254 Members {size:2, ver:2} [
|
|
255 Member [10.10.10.167]:5701 - 30098b8c-ebaf-479a-85ed-6ff96389151a this
|
|
256 Member [10.10.10.167]:5702 - d7d30c33-ee10-43d8-aab4-b90f8a9fa513
|
|
257 ]
|
|
258
|
|
259 from : B
|
|
260 data : 0
|
|
261 from : B
|
|
262 data : 2
|
|
263 from : B
|
|
264 data : 4
|
|
265 from : B
|
|
266 data : 6
|
|
267 from : B
|
|
268 data : 8
|
|
269 from : B
|
|
270 data : 10
|
|
271
|
|
272
|
|
273 Node B
|
|
274
|
|
275 Members {size:2, ver:2} [
|
|
276 Member [10.10.10.167]:5701 - 30098b8c-ebaf-479a-85ed-6ff96389151a
|
|
277 Member [10.10.10.167]:5702 - d7d30c33-ee10-43d8-aab4-b90f8a9fa513 this
|
|
278 ]
|
|
279
|
|
280 local : B
|
|
281 remote : A
|
|
282 from : A
|
|
283 data : 1
|
|
284 from : A
|
|
285 data : 3
|
|
286 from : A
|
|
287 data : 5
|
|
288 from : A
|
|
289 data : 7
|
|
290 from : A
|
|
291 data : 9
|
|
292 ```
|
|
293
|
|
294 ## 2. ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?
|
|
295
|
|
296 Q: ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?
|
|
297
|
|
298 A: 読めてないけど解説はありました.
|
|
299
|
|
300 http://docs.hazelcast.org/docs/latest-development/manual/html/Hazelcast_Overview/Hazelcast_Topology.html
|
|
301
|
|
302 ただ, AliceのTopologyManagerみたいなものはなく, プログラムで指定するっぽい...多分.
|
|
303
|
|
304 http://docs.hazelcast.org/docs/latest-development/manual/html/Setting_Up_Clusters/Creating_Cluster_Groups.html
|
|
305
|
|
306 ## 3. 送信するデータを圧縮したいとき、それをサポートする機能はあるか?
|
|
307
|
|
308 Q: 送信するデータを圧縮したいとき、それをサポートする機能はあるか?
|
|
309
|
|
310 A: あるっぽいです.
|
|
311
|
|
312 https://blog.hazelcast.com/kryo-serializer/
|
|
313
|
|
314
|
|
315 Kryoというシリアライズ + 圧縮をするフレームワーク? 的なものがJavaの外部フレームワークにあるらしく, それを用いるそうです.
|
|
316
|
|
317
|
|
318 ## 参考サイト
|
|
319
|
|
320 - [Message](https://hazelcast.org/use-cases/messaging/)
|
|
321 - [Map](http://docs.hazelcast.org/docs/latest/manual/html-single/)
|
|
322 - [Map Listener](http://docs.hazelcast.org/docs/latest-development/manual/html/Distributed_Events/Event_Listener_for_Members/Listening_for_Map_Events.html)
|
|
323 - [Kryo](http://d.hatena.ne.jp/Kazuhira/20150425/1429946795)
|