<commit_before># Hazelcast
- https://hazelcast.org/

## Hello World
https://hazelcast.org/getting-started-with-hazelcast/

### やること
- 2つのノード(JVM)でインメモリ・データグリッドを作成する
- 最終的には、外部の Java アプリケーションからデータグリッドにアクセスする

### インストール
https://hazelcast.org/download/

```groovy
compile 'com.hazelcast:hazelcast:3.10.6'
```

## ノードを自動検出する仕組み
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#discovery-mechanisms

- 一度クラスタを組んだノード同士の通信は TCP/IP によって行われている
    - これは、ノードの発見方法とは関係しない
- 発見メカニズム (Discovery Mechanisms)
    - 単純な TCP による発見以外にも、 AWS 上でノードを見つける方法や Azure で見つける方法など、様々な方法が用意されている
- 基本は xml の設定ファイルでクラスタの情報を定義するっぽい
    - 設定がないときは、デフォルトでローカルホスの 5701, 5702 ポートに接続しようとするっぽい

## トポロジー
- クラスタの組み方が二種類存在する
- 組み込み(Embedded)と、クラサバ(Client/Server)
- 組み込み
    - 非同期・ハイパフォーマンス・大量タスクの実行に向いている
    - アプリケーションの中に Hazelcast を組み込む
    - データアクセスのレイテンシ(待ち時間)が減るのがメリット
- クラサバ
    - Hazelcast だけでデータサーバーを構築し、そこにアプリケーションがアクセスしにいく形式
    - クライアントになるアプリケーションは、個々に独立した存在になれる
        - 異なるアーキテクチャで構築できる
        - 個々のクライアントアプリケーションごとにスケールできる
    - Hazelcast のクライアント API を使ってアクセスする
        - Java, .NET, C++ は専用のクライアント API ライブラリが用意されている
        - REST API もある
    - メリット
        - Hazelcast だけに絞ったスケールが容易

## データパーティション
- shard (シャード)
    - 破片
    - 分割されたデータのことか？
- Hazelcast では、シャードのことを**パーティション**(Partitions)と呼んでいる
- パーティションとは、メモリセグメントのこと
    - 中に数百から数千のデータを格納できる
    - 実際どれくらい保存できるかは、実行環境のメモリ容量に依存する
- パーティションは複数の複製を持つことができる
    - それらは（複製のこと指している？）、クラスタの各メンバーに分配される
    - １つの複製が**プライマリ** (primary)となる
    - それ以外の複製は**バックアップ** (buckups)となる
    - プライマリを持つクラスタメンバのことを **プライマリオーナー** (primary owner) と呼ぶ
- データにアクセスすると、オーナーに対して透過的に対話が行われる
    - どれがオーナーかとかは意識することなく、クラスタ内からデータを引っ張り出せる、ってことかな
- デフォルトだと、１つ目に立ち上がったノードでは 271 のパーティションが作成される
    - この時点では、 271 のパーティションがすべてプライマリということになる
        - クラスタ化されていないので、複製がない状態ということ
- ２つ目のノードを立ち上げてクラスタが組まれると、２つ目のノードに１つ目のノードのパーティションがコピーされる
    - そして、半分の 135 のパーティションが、それぞれで重複しない形でプライマリパーティションになる
    - 残りの 136 は、バックアップとなる
- 3.6 で追加された Lite メンバーは、自分のパーティションを持っていない
    - 代わりに、クラスタ内の他のノードのパーティションを見ることができる
- どのようにしてデータがパーティションに分けられるのか
    - Hazelcast は、ハッシュアルゴリズムを使ってデータをパーティション内に配布する
    - オブジェクトの名前をハッシュ化してパーティションの数の剰余を取得する
        - オブジェクトの名前は、 HazelcastInstance から getList(String) とかしたときに引数で指定するやつ
        - 他にも Key というのもあるらしいが、よくわかってない
    - 剰余の結果がパーティションの ID になり、そのパーティションにデータが割り振られる
- パーティションテーブル
    - ノードを作成すると、内部でパーティションテーブルが作られる
    - テーブルには次の情報が格納されている
        - パーティションID
        - そのパーティションが、クラスタ内のどのノードに所属しているか
            - どれがオーナーか、ということ？
    - このテーブルの目的は、クラスタ内の全メンバーが、あるパーティションのオーナーがどのメンバーかを知ること
        - そのデータがどこにあるかがわかる
    - 最初に作成されたメンバーが、定期的にパーティションテーブルの情報を他のメンバーに送信している
        - 情報を受け取ったメンバーは、オーナーがどう変化したかを知ることができる
        - 最初に作成されたメンバーがクラスタから外れた場合は、次に古いメンバーが役割を引き継ぐ
    - パーティションテーブルの情報を送信する頻度は変更できる
        - `hazelcast.partition.table.send.interval`
        - デフォルトは 15 秒
- 再パーティション(Repartitioning)
    - 再パーティションとは、パーティションの所有者を再割り当てする処理のことを言う
    - 次のような場合に、再パーティションが行われる
        - メンバーがクラスタに参加した
        - メンバーがクラスタから離脱した
    - 最も古株のノードが持つパーティションテーブルが、新しいオーナーの情報で更新される
    - ただし、 Lite メンバーが参加・離脱しても再パーティションは行われない
        - Lite メンバーは自身のパーティションを持たないため
- パーティションの中にデータが入っているわけではないっぽい
    - 名前からパーティションを決定し、パーティションテーブルでオーナーを特定するというステップを踏むことで、効率的に分散されたデータにアクセスできるようになっている、ということか

## 設定ファイルを理解する
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#understanding-configuration

- Hazelcast の設定方法には以下の種類が存在する
    1. 宣言的な方法
    2. プログラミングによる方法
    3. Hazelcast のシステムプロパティを使用する方法
    4. Spring Context に含める方法
    5. 実行中のクラスで動的に設定を追加する方法(3.9 以上)
- 宣言的な方法
    - xml ファイルで設定を定義する
    - jar の中の `hazelcast-default.xml` がデフォルト値を定義した設定ファイル
    - `hazelcast-full-example.xml` は、全ての設定値を含むファイル
        - リファレンスドキュメントとして利用できる
- 設定ファイルの合成
    - `<import>` を使うことで、外部の設定ファイルをロードできる
- 設定ファイルをプログラムから読み込む
    - 設定ファイルの取得元ごとに `Config` クラスのサブクラスが用意されている
        - URL を指定して読み込む場合は `UrlXmlConfig`
        - ローカルファイルを読み込む場合は `FileSystemXmlConfig`
        - クラスパス上の設定ファイルを読み込む場合は `ClasspathXmlConfig`
- 動的な設定の追加
    - 普通、設定は静的で、一度インスタンスを生成すると変更することはできない
    - しかし、 3.9 からは一部の設定に限ってインスタンス生成後も設定を追加できるようになった
    - `Config` クラスで `add*Config()` という名前のメソッドが対象
    - `HazelcastInstance` の `getConfig()` で取得した `Config` インスタンスを使用するのが前提
    - 動的に追加する設定は、 `add*Config()` を呼び出す前に全て完了している必要がある
    - 動的に追加された設定は、クラスタ内の全てのノードに配布される
    - もしネットワークエラーなどの原因でクラスタ内のノードに配布できなかった場合
        - クラスタ内のメンバーの変更を検出するたびに内部的に再試行が行われる
        - `add*Config()` メソッドが例外を投げた場合は、ユーザ操作で再試行を行わなければならない
    - 設定ファイルの競合を制御する
        - 動的に追加した設定と同じ要素が、すでに静的な設定で指定されている場合
        - `ConfigurationException` がスローされる
        - 以前の動的な設定追加ものと同じ要素を、更に動的設定追加しようとした場合も `ConfigurationException` がスローされる
- 設定ファイルの検索
    - `Config` クラスを使わずに `HazelcastInstance` を生成した場合の挙動
        - `newHazelcastInstance()` を引数なしで使用した場合の話
    - デフォルトでは、次の順序で設定ファイルが検索される
        1. システムプロパティの `hazelcast.config` で指定されたファイル
            - `classpath:` で始めれば、クラスパス内のファイルを参照することも可能
        2. ワーキングディレクトリの `hazelcast.xml`
        3. クラスパス内の `hazelcast.xml`
        4. Hazelcast が内部に持つデフォルト値を設定した `hazelcast.xml`
- パターンマッチ
    - ワイルドカード
        - 分散データ構造の名前ではワイルドカードが使える
        - デフォルトでは、 `*` を使ったワイルドカードの指定がサポートされている
        - １つの名前の指定で `*` が使えるのは１回だけ
        - ある分散データ構造のインスタンス名が複数の設定とマッチした場合は、名前の指定が長い方が優先される
            - `mymap.customer.name` という名前のデータがあったとして、
            - `mymap.*` と `mymap.customer.*` という２つの設定が合った場合は、長い方の `mymap.customer.*` が優先される
    - 正規表現
        - パターンマッチのルールは任意のものに変更できる
        - 標準実装のなかに正規表現クラスがあるっぽいので、それに差し替えできそう
        <commit_msg>Hazelcast : 変数を設定ファイルで使用する<commit_after># Hazelcast
- https://hazelcast.org/

## Hello World
https://hazelcast.org/getting-started-with-hazelcast/

### やること
- 2つのノード(JVM)でインメモリ・データグリッドを作成する
- 最終的には、外部の Java アプリケーションからデータグリッドにアクセスする

### インストール
https://hazelcast.org/download/

```groovy
compile 'com.hazelcast:hazelcast:3.10.6'
```

## ノードを自動検出する仕組み
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#discovery-mechanisms

- 一度クラスタを組んだノード同士の通信は TCP/IP によって行われている
    - これは、ノードの発見方法とは関係しない
- 発見メカニズム (Discovery Mechanisms)
    - 単純な TCP による発見以外にも、 AWS 上でノードを見つける方法や Azure で見つける方法など、様々な方法が用意されている
- 基本は xml の設定ファイルでクラスタの情報を定義するっぽい
    - 設定がないときは、デフォルトでローカルホスの 5701, 5702 ポートに接続しようとするっぽい

## トポロジー
- クラスタの組み方が二種類存在する
- 組み込み(Embedded)と、クラサバ(Client/Server)
- 組み込み
    - 非同期・ハイパフォーマンス・大量タスクの実行に向いている
    - アプリケーションの中に Hazelcast を組み込む
    - データアクセスのレイテンシ(待ち時間)が減るのがメリット
- クラサバ
    - Hazelcast だけでデータサーバーを構築し、そこにアプリケーションがアクセスしにいく形式
    - クライアントになるアプリケーションは、個々に独立した存在になれる
        - 異なるアーキテクチャで構築できる
        - 個々のクライアントアプリケーションごとにスケールできる
    - Hazelcast のクライアント API を使ってアクセスする
        - Java, .NET, C++ は専用のクライアント API ライブラリが用意されている
        - REST API もある
    - メリット
        - Hazelcast だけに絞ったスケールが容易

## データパーティション
- shard (シャード)
    - 破片
    - 分割されたデータのことか？
- Hazelcast では、シャードのことを**パーティション**(Partitions)と呼んでいる
- パーティションとは、メモリセグメントのこと
    - 中に数百から数千のデータを格納できる
    - 実際どれくらい保存できるかは、実行環境のメモリ容量に依存する
- パーティションは複数の複製を持つことができる
    - それらは（複製のこと指している？）、クラスタの各メンバーに分配される
    - １つの複製が**プライマリ** (primary)となる
    - それ以外の複製は**バックアップ** (buckups)となる
    - プライマリを持つクラスタメンバのことを **プライマリオーナー** (primary owner) と呼ぶ
- データにアクセスすると、オーナーに対して透過的に対話が行われる
    - どれがオーナーかとかは意識することなく、クラスタ内からデータを引っ張り出せる、ってことかな
- デフォルトだと、１つ目に立ち上がったノードでは 271 のパーティションが作成される
    - この時点では、 271 のパーティションがすべてプライマリということになる
        - クラスタ化されていないので、複製がない状態ということ
- ２つ目のノードを立ち上げてクラスタが組まれると、２つ目のノードに１つ目のノードのパーティションがコピーされる
    - そして、半分の 135 のパーティションが、それぞれで重複しない形でプライマリパーティションになる
    - 残りの 136 は、バックアップとなる
- 3.6 で追加された Lite メンバーは、自分のパーティションを持っていない
    - 代わりに、クラスタ内の他のノードのパーティションを見ることができる
- どのようにしてデータがパーティションに分けられるのか
    - Hazelcast は、ハッシュアルゴリズムを使ってデータをパーティション内に配布する
    - オブジェクトの名前をハッシュ化してパーティションの数の剰余を取得する
        - オブジェクトの名前は、 HazelcastInstance から getList(String) とかしたときに引数で指定するやつ
        - 他にも Key というのもあるらしいが、よくわかってない
    - 剰余の結果がパーティションの ID になり、そのパーティションにデータが割り振られる
- パーティションテーブル
    - ノードを作成すると、内部でパーティションテーブルが作られる
    - テーブルには次の情報が格納されている
        - パーティションID
        - そのパーティションが、クラスタ内のどのノードに所属しているか
            - どれがオーナーか、ということ？
    - このテーブルの目的は、クラスタ内の全メンバーが、あるパーティションのオーナーがどのメンバーかを知ること
        - そのデータがどこにあるかがわかる
    - 最初に作成されたメンバーが、定期的にパーティションテーブルの情報を他のメンバーに送信している
        - 情報を受け取ったメンバーは、オーナーがどう変化したかを知ることができる
        - 最初に作成されたメンバーがクラスタから外れた場合は、次に古いメンバーが役割を引き継ぐ
    - パーティションテーブルの情報を送信する頻度は変更できる
        - `hazelcast.partition.table.send.interval`
        - デフォルトは 15 秒
- 再パーティション(Repartitioning)
    - 再パーティションとは、パーティションの所有者を再割り当てする処理のことを言う
    - 次のような場合に、再パーティションが行われる
        - メンバーがクラスタに参加した
        - メンバーがクラスタから離脱した
    - 最も古株のノードが持つパーティションテーブルが、新しいオーナーの情報で更新される
    - ただし、 Lite メンバーが参加・離脱しても再パーティションは行われない
        - Lite メンバーは自身のパーティションを持たないため
- パーティションの中にデータが入っているわけではないっぽい
    - 名前からパーティションを決定し、パーティションテーブルでオーナーを特定するというステップを踏むことで、効率的に分散されたデータにアクセスできるようになっている、ということか

## 設定ファイルを理解する
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#understanding-configuration

- Hazelcast の設定方法には以下の種類が存在する
    1. 宣言的な方法
    2. プログラミングによる方法
    3. Hazelcast のシステムプロパティを使用する方法
    4. Spring Context に含める方法
    5. 実行中のクラスで動的に設定を追加する方法(3.9 以上)
- 宣言的な方法
    - xml ファイルで設定を定義する
    - jar の中の `hazelcast-default.xml` がデフォルト値を定義した設定ファイル
    - `hazelcast-full-example.xml` は、全ての設定値を含むファイル
        - リファレンスドキュメントとして利用できる
- 設定ファイルの合成
    - `<import>` を使うことで、外部の設定ファイルをロードできる
- 設定ファイルをプログラムから読み込む
    - 設定ファイルの取得元ごとに `Config` クラスのサブクラスが用意されている
        - URL を指定して読み込む場合は `UrlXmlConfig`
        - ローカルファイルを読み込む場合は `FileSystemXmlConfig`
        - クラスパス上の設定ファイルを読み込む場合は `ClasspathXmlConfig`
- 動的な設定の追加
    - 普通、設定は静的で、一度インスタンスを生成すると変更することはできない
    - しかし、 3.9 からは一部の設定に限ってインスタンス生成後も設定を追加できるようになった
    - `Config` クラスで `add*Config()` という名前のメソッドが対象
    - `HazelcastInstance` の `getConfig()` で取得した `Config` インスタンスを使用するのが前提
    - 動的に追加する設定は、 `add*Config()` を呼び出す前に全て完了している必要がある
    - 動的に追加された設定は、クラスタ内の全てのノードに配布される
    - もしネットワークエラーなどの原因でクラスタ内のノードに配布できなかった場合
        - クラスタ内のメンバーの変更を検出するたびに内部的に再試行が行われる
        - `add*Config()` メソッドが例外を投げた場合は、ユーザ操作で再試行を行わなければならない
    - 設定ファイルの競合を制御する
        - 動的に追加した設定と同じ要素が、すでに静的な設定で指定されている場合
        - `ConfigurationException` がスローされる
        - 以前の動的な設定追加ものと同じ要素を、更に動的設定追加しようとした場合も `ConfigurationException` がスローされる
- 設定ファイルの検索
    - `Config` クラスを使わずに `HazelcastInstance` を生成した場合の挙動
        - `newHazelcastInstance()` を引数なしで使用した場合の話
    - デフォルトでは、次の順序で設定ファイルが検索される
        1. システムプロパティの `hazelcast.config` で指定されたファイル
            - `classpath:` で始めれば、クラスパス内のファイルを参照することも可能
        2. ワーキングディレクトリの `hazelcast.xml`
        3. クラスパス内の `hazelcast.xml`
        4. Hazelcast が内部に持つデフォルト値を設定した `hazelcast.xml`
- パターンマッチ
    - ワイルドカード
        - 分散データ構造の名前ではワイルドカードが使える
        - デフォルトでは、 `*` を使ったワイルドカードの指定がサポートされている
        - １つの名前の指定で `*` が使えるのは１回だけ
        - ある分散データ構造のインスタンス名が複数の設定とマッチした場合は、名前の指定が長い方が優先される
            - `mymap.customer.name` という名前のデータがあったとして、
            - `mymap.*` と `mymap.customer.*` という２つの設定が合った場合は、長い方の `mymap.customer.*` が優先される
    - 正規表現
        - パターンマッチのルールは任意のものに変更できる
        - 標準実装のなかに正規表現クラスがあるっぽいので、それに差し替えできそう
        
- 変数
    - システムプロパティに設定した値は、 `${名前}` という記法で設定ファイルに埋め込むことができる
    - `XmlConfigBuilder` に `setProperties(Properties)` を設定して `build()` で生成した設定ファイルを使えば、システムプロパティ以外で設定できる
{'fraction_non_alphanumeric': 0.08077236877889583, 'fraction_numerical': 0.009065361254645998, 'mean_word_length': 3.5380501851090087, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4298892', 'n_tokens_mistral': 8469, 'n_tokens_neox': 8090, 'n_words': 553}