無償オープンソースのAerospike Server Community Editionを使おう

# はじめに
この記事を読んでる方は、Aerospikeをある程度はご存知かと思いますが、まず簡単にAerospikeをご紹介します。
Aerospikeは、低レイテンシー、高スループット、スケーラビリティ、アベイラビリティを誇る、分散NoSQLデータベースのソフトウェアです。
データモデルとしては、キーバリュー、ドキュメント、グラフ、そして、ベクトルをサポートしています。

詳細をご存じない方は、以下の２つの私が投稿した記事を参照してください。
[Aerospikeの紹介](https://qiita.com/aerospike_nakadai/items/238e5a2e15034f9070da)
[Aerospikeのアーキテクチャ](https://qiita.com/aerospike_nakadai/items/6b6bc68dbc4bba0d7bd3)

ところで、Aerospikeは有償で高額らしいのでちょっと手が出ないと思っている方も多いのではないでしょうか。
実は、Aerospikeは機能を制限した無償版も提供しています。
有償版がAerospike Server Enterprise Edition(およびStandard　Edition)、無償版はAerospike Server Community Editionです。以降、Aerospike Server Enterprise EditionをEE、Aerospike Server Community EditionをCEと省略して記載します。

この記事では安心して無償版であるAerospike Server Community Editionをご利用いただきたく、有償板との違いや使い方を詳しく説明します。

:::note info
Aerospike Serverの現在(2024/8/6)の最新版である7.1.0から、設定や内部のアーキテクチャが変更されました。
今が最新版からAerospikeを使い始める絶好の時期です。
:::


# 1. 有償版との相違点
詳しくは、以下のページに記載しています。
https://aerospike.com/products/features-and-editions/

ここで、ご利用になる上で影響の大きいところを説明します。
## 1.1 データ量とノード（サーバ）数の制限
Aerosikeは分散データベースですので、複数のサーバで１つのデータベースとしてご利用いただけます。このサーバをノード、ノードをまとめたデータベースの単位をクラスターと呼びます。
また、アベイラビリティを高めるために、データのレプリケーションも自動的に行われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950363/34b98a2b-7a23-3134-f695-81f8e0b984ab.png)

EEではノード数とデータ量について制限がありません。
CEではノード数は8、データ量は5TBの制限があります。
ここでのデータ量はクラスター全体でのユニークデータ量であり、レプリケーションして複製しているデータ量は含みません。データ量にはレコード毎のメタデータ等の付加情報も含みますのでご注意ください。

## 1.2 サポートの違い
当然ですが、EEでは万全のサポートが提供されますが、CEではCommunityでのサポートになります。
サポートサイトは以下です。
https://discuss.aerospike.com/
ご覧の通り英語サイトですし、完全な回答が保証されているわけではありませんので、ご注意ください。

日本語で質問したい方は、完全なサポートはできませんが、よろしければこの記事のコメントで質問をお寄せください。

## 1.3 暗号化および認証
CEではご利用いただけません。

## 1.4 他システムとのコネクション
EEでは他システムとのコネクターをご利用いただけます。（別途ライセンスの追加が必要）
CEではご利用いただけないので、自身でコネクション用のアプリケーションを作成していただく必要があります。

## 1.5 機能の相違点
Aerospikeはノードの追加や停止時に、自動的にデータの再分散、レプリケーションを行います。これをマイグレーションと呼びます。このマイグレーションの性能がEEと比較して低くなります。(Rapid Rebalance機能)

EEはサーバ上のデータおよび通信データの圧縮が可能ですが、CEでは利用できません。(Compression機能)

Aerospikeは、データの取得のためにインデックスが作成されていますが、EEではAerospikeのソフトウェアの再起動しても、停止前のインデックスをそのまま利用できますが、CEでは起動のたびにインデックスを再作成します。そのため、CEではデータ量が多い場合、起動時に時間がかかります。(Fast Restart機能)

## 1.6 データモデルの相違点
グラフデータベースとベクトルデータベースは、CEでは利用できません。

## 1.7 相違点のまとめ
以上の相違点がありますので、CEをご利用頂く場合は以下を理解した上でご利用ください。
- ノード数およびデータ量の制限がある。（他にもPerformanceに関する制限があります。）
- サポートがコミュニティのサポートになります
- 暗号化、認証、他システムとのコネクションは利用できません
- 起動時、マイグレーション時に時間がかかります
- グラフデータベース、ベクトルデータベースは利用できません
- 他にも利用できない機能がありますので確認が必要です

以上ですが、多くは他のオープンソースソフトウェアも同じかと思いますので、ぜひご利用ください。

# 2. CEを起動する
それではCEをインストールし、起動します。
CEを起動するインフラは大きく２つあります。
まず一つはLinuxサーバです。これは、AWSのEC2等のクラウドのインスタンスでも、オンプレでも結構です。
もう一つはDockerでの起動です。
Dockerでも複数ノードのクラスターを組むことは可能ですが、安定性や性能を考えて、Dockerでの起動は１ノードでの動作確認用と考えていただいた方が良いでしょう。
このあたり、詳しく知りたい方はぜひコメントください。
Dockerでの起動については以下の記事を参考にしてください。
[Aerospikeを使ってみる：Windows11環境のDockerを使って起動](https://qiita.com/aerospike_nakadai/items/ac879d857c97d9c9428e)
[Aerospikeを使ってみる：Dockerを使ってCRUDのテストと管理](https://qiita.com/aerospike_nakadai/items/7d8ecfa376b1206cbe5a)

それでは、Linuxサーバへのインストール方法を説明します。

## 2.1 Linuxサーバを準備する
Linuxサーバを準備する上で重要なのは、インデックスとデータをどこに保持するかです。
Aerospikeは、NVMe SSDを効率的に使うことで、In-Memoryとほぼ同等の性能を発揮します。
以下がインデックスとデータの保持するストレージとメリット・デメリットです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950363/f1e59a54-93b2-df41-9be1-74f12c7c8af3.png)
データをSSDに保存できるため、高価で容量に制限があるメモリを少なくでき、TCOが下がります。
この図にあるALL FLASHについてはCEではご利用いただけませんのでご注意ください。
また、SSDを利用するときはRAWデバイスへの直接アクセスになります。

ここでは、Aerospikeの特徴を発揮できる、インデックスはメモリ、データはSSDに保存するHYBRID構成で説明します。

それでは、Linuxサーバを準備しましょう。

### 2.1.1 ハードウェア
- CPU
CPUは性能要求によるため一概にはいえませんが、通常のサーバにご利用いただける程度のものがあれば大丈夫です。
多くの場合、ボトルネックはディスクかネットワークになります。
Inte/AMD64およびARM64が使用できます。
- ネットワーク
すくなくとも1Gbps、できれば10Gbpsは必要です。ボトルネックになることがありますので、ぜひ、ベンチマークして必要なネットワークを調査してください。
- SSD
NVMeのSSDを推奨いたします。ディスクの速度がボトルネックになることも多いので、こちらもベンチマークすることをおすすめします。
サイズは、以下を目安にしてください。
    - 想定するユニークなデータ量：X GB
    - ノード数： n台
    - 複製数：2(一つのデータが、クラスター内の２ノードに保持される）
この場合の、各ノードに入るデータ量は以下となります。ただし、メタデータが存在し、かつ、動作中に必要なディスクもあるため、最低でも、この値の２倍のディスクを用意してください。

　　　　**各ノードに入るデータ量**
```math
\frac{X}{n} \times 2
```
　　　　**各ノードで必要な最低限のディスク量**
```math
\frac{X}{n} \times 2 \times 2
```
- メモリ
一つのデータ(レコード)毎に64バイトがインデックスとして使用されます。
サイズは以下を目安にしてください。
    - 想定するユニークなレコード数：Y個
    - ノード数： n台
    - 複製数：2(一つのデータが、クラスター内の２ノードに保持される）
この場合の、ノードでインデックスとして使用されるメモリ量は以下になります。ディスクと同様、最低でもこの値の２倍のメモリを用意してください。

　　　　**ノードでインデックスとして使用されるメモリ量**
```math
\frac{Y}{n} \times 2 \times 64
```
　　　　**各ノードで必要な最低限のメモリ量**
```math
\frac{Y}{n} \times 2 \times 64 \times 2
```

### 2.1.2 OS
次にOSについては、最新のAerospike Serverの場合は、以下をご利用ください。
- Ubuntu 22.04
- Ubuntu 20.04
- Red Hat 9
- Red Hat 8
- Debian 12
- Debian 11
- Amazon 2023(EC2の場合)

Red HatはRocky Linuxなどの互換OSでも大丈夫です。

#### OSの設定
OSについて、以下にLinux best practiceの説明があります。
https://aerospike.com/docs/server/operations/install/linux/bestpractices#linux-best-practices
この中で、以下はぜひ設定してください。
- min_free_kbytes
https://aerospike.com/docs/server/operations/install/linux/bestpractices#min_free_kbytes
- swappiness
https://aerospike.com/docs/server/operations/install/linux/bestpractices#swappiness
SWAPは性能への影響が大きいので、使用しないように注意してください。
- THP - transparent huge pages
https://aerospike.com/docs/server/operations/install/linux/bestpractices#thp---transparent-huge-pages
- NVMe partitioning
https://aerospike.com/docs/server/operations/install/linux/bestpractices#nvme-partitioning
ここに記載されている通り、NVMeのディスクは少なくとも4つにパーティション分割するようしてください。

### 2.1.3 ファイアウォール
ノード間およびクライアントからノードへ、3000-3003のポートにアクセスできるようしてください。

## 2.2 CEのインストール

### 2.2.1 CEのダウンロード
CEのダウンロードは以下より行います。
1. https://aerospike.com/ にアクセスする
1. Resourcesをクリックし、表示されたメニューの右にある[Download now](https://aerospike.com/download/)をクリックしてください
![Resource Menu](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950363/96514672-7fba-fa38-cc57-b6c82e2dd652.png)
![Download Page](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950363/93a8b147-dd93-07ae-ed68-18871b882230.png)
1. 左の[Community Edition](https://aerospike.com/download/?software=server-community)をクリックしてください
![スクリーンショット 2024-08-05 17.48.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2950363/10c4f6ac-3901-84c7-3db4-3589ce4bc1c2.png)
1. Version、CPU、Systemを選択し、[Download]をクリックしてください
1. tgzファイルがダウンロードされます

### 2.2.2 CEのインストール
ダウンロードしたtgzを任意の場所に展開してください。
aerospike-server-communityのdebまたはrpmファイルと、aerospike-toolsのdebまたはrpmファイルが含まれます。
asinstallという実行ファイルがありますので、以下の通り実行すると上記のdebまたはrpmファイルがインストールされます。
```
sudo ./asinstall
```
これだけでAerospikeがインストールされます。
インストールされたAerospikeは、以下に保存されています。
- /opt/aerospike/
- /etc/aerospike/
- /usr/bin/asd

また、aerospike-toolsが同時に/usr/bin/の下にインストールされています。
aerospike-toolsについては以下を御覧ください。
https://aerospike.com/docs/tools

## 2.3 CEの設定
Aerospikeの設定は、`/etc/aerospike/aerospike.conf` で行います。
設定項目については、[Configuration Reference](https://aerospike.com/docs/server/reference/configuration)を御覧ください。

インストール直後の設定は
```
# Aerospike database configuration file for use with systemd.

service {
	proto-fd-max 15000
	cluster-name cakery
}

logging {
	console {
		context any info
	}
}

network {
	service {
		address any
		port 3000
	}

	heartbeat {
		mode multicast
		multicast-group 239.1.99.222
		port 9918

		# To use unicast-mesh heartbeats, remove the 3 lines above, and see
		# aerospike_mesh.conf for alternative.

		interval 150
		timeout 10
	}

	fabric {
		port 3001
	}

#	info {
#		port 3003
#	}
}

namespace test {
	replication-factor 2

	storage-engine memory {
		data-size 4G
	}
}

namespace bar {
	replication-factor 2

	storage-engine memory {
		data-size 4G

		# To use file storage backing, comment out the line above and use the
		# following lines instead.
#		file /opt/aerospike/data/bar.dat
#		filesize 4G
	}
}
```
`/etc/aerospike/sample` にサンプルのconfファイルが保存されているので参考にしてください。

ここでは、まずは起動に必要、または、設定したほうが良い項目の設定をおこないます。

### 2.3.1 名称の設定
クラスター全体の名前([cluster-name](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=cluster-name#service__cluster-name))と各ノードのid([node-id](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=node-id#service__node-id))を設定します。
ノードの名前は、当初は記載がないので追加の記載になります。
```
service {
        proto-fd-max 15000
        cluster-name cetest
        node-id a1
}
```
cluster-nameが同じノードだけがクラスターに参加できます。
node-idは0-1A-Fの値(16進数の値)で設定してください。
node-idは分散とレプリケーションを決めるための値になりますので、途中で変えたりせず、また、ノードが故障して別のサーバやインスタンスに変更した場合でも同じ値を使用するようにしてください。

### 2.3.2 heartbeatの設定
heartbeatとは、ノードが停止した時や追加された時の、生存確認をするためのネットワーク接続です。
設定には、`multicast`と`mesh`の２つがあり、[mode](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=mode#network__mode)で設定します。
multicastが可能なネットワーク構成であればmulticastが簡単ですが、クラウドの場合はmulticastが難しいため、meshをご利用ください。

multicastの場合は、デフォルトの以下のままか、グループやポートを適宜変更してご利用ください。
```
	heartbeat {
		mode multicast
		multicast-group 239.1.99.222
		port 9918

		interval 150
		timeout 10
	}
```
meshの場合は、以下のように変更してください。
```
        heartbeat {
                mode mesh
                port 3002
                mesh-seed-address-port 192.168.10.2 3002
                mesh-seed-address-port 192.168.10.3 3002

                interval 150
                timeout 10
        }
```
[mesh-seed-address-port](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=mesh-seed-address-port#network__mesh-seed-address-port)には、自ノード以外のIPアドレスを指定してください。
自ノードのIPアドレスを記載しても問題ありませんので、全ノードで共通の設定でも問題ありません。
ノードを追加した場合、元々のノードに追加したノードのIPアドレスの記載を追加する必要はありません。追加したノードに他のノードのIPアドレスが記載されていれば、問題なくクラスターに接続できます。

### 2.3.3 ストレージの設定
ストレージの設定は、namespaceの設定で行います。
#### In-Memory
まず、データをメモリに保持するIn-Memoryの設定が以下になります。
```
namespace test {
        replication-factor 2

        storage-engine memory {
                data-size 4G
        }
}
```
[storage-engine](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=storage#namespace__storage-engine)の設定で`memory`と記載するとデータがメモリに保存されます。その時に使用可能なメモリ領域を`data-size`で指定します。

#### Hybrid
次にSSDにデータを保持するHybridの設定が以下になります。
```
namespace ssd {
        replication-factor 2

        storage-engine device {
                device /dev/xvdb
                device /dev/xvdc
        }
}
```
[storage-engine](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=storage#namespace__storage-engine)の設定で`device`と記載するとデータがSSDに保存されます。
保存先のdeviceは`device /dev/xxxxx`とデバイス名で指定します。
複数の場合には、上記のように、複数行で記載します。
`device /dev/xxxx /dev/yyyy`の記載だと、他の機能になりますのでご注意ください。

#### 共通設定
上記の両方の設定にある、[replication-factor](https://aerospike.com/docs/server/reference/configuration?context=all&version=7&search=replication#namespace__replication-factor)は複製数です。この設定では、クラスターに1つのレコードが２つある事になります。

### 2.3.4 その他
ここでは、記載しませんが、以下のような場合の設定があります。詳しく知りたい方はコメント下さい。

- レコードのExpireのデフォルト設定(default-ttl)
- レコードの最大サイズ(max-record-size)
- パブリックIPとローカルIPがあり、クライアントからパブリックIPでアクセスする場合の設定
- EC2のエフェメラルとEBSを使用する場合の設定(バックアップデバイスの設定)

###　2.3.5 上記を反映した設定ファイル
以上の説明を反映した設定ファイルが以下になります。これはmeshの設定です。
```
# Aerospike database configuration file for use with systemd.

service {
	proto-fd-max 15000
	cluster-name cetest
    node-id a1
}

logging {
	console {
		context any info
	}
}

network {
	service {
		address any
		port 3000
	}

	heartbeat {
#		mode multicast
#		multicast-group 239.1.99.222
#		port 9918
        mode mesh
        port 3002
        mesh-seed-address-port 192.168.10.2 3002
        mesh-seed-address-port 192.168.10.3 3002


		# To use unicast-mesh heartbeats, remove the 3 lines above, and see
		# aerospike_mesh.conf for alternative.

		interval 150
		timeout 10
	}

	fabric {
		port 3001
	}

#	info {
#		port 3003
#	}
}

namespace test {
        replication-factor 2

        storage-engine memory {
                data-size 4G
        }
}
namespace ssd {
        replication-factor 2

        storage-engine device {
                device /dev/xvdb
                device /dev/xvdc
        }
}
```
## 2.4 CEの起動・再起動・停止
CEの起動、再起動、停止は以下で行います。

CEの起動
```
sudo systemctl start aerospike
```
CEの再起動
```
sudo systemctl restart aerospike
```
CEの停止
```
sudo systemctl stop aerospike
```
CEの状態
```
sudo systemctl status aerospike
```

以上で、CEが起動され、クラスターが構成されます。
複数ノードについても同じように起動してください。

起動しなかった場合は、上記のstatusを実行すると起動できない理由が表示されます。

# 3. ツールを使ってみる
## 3.1 CEの状態を確認する(asadm)
CEが起動され、ストレージの設定ができているか確認します。

CEをインストールしたサーバか、別途aerospike-toolsをインストールしたサーバで、以下を実行します。
```
asadm
```
aerospikeがインストールされたサーバ以外からの接続の場合は、以下のように任意のノードのIPアドレスを指定してください。
```
asadm -h xxx.xxx.xxx.xxx
```
正常に起動している場合は、以下のように表示されます。
```
[ec2-user@ip-192-168-10-2 ~]$ asadm
Seed:        [('127.0.0.1', 3000, None)]
Config_file: /home/ec2-user/.aerospike/astools.conf, /etc/aerospike/astools.conf
Aerospike Interactive Shell, version 3.0.1

Found 2 nodes
Online:  192.168.10.2:3000, 192.168.10.3:3000

Admin>
```
上記の場合は、2ノード起動しています。
このプロンプトで、summaryやinfoと入力していたくと、ノード、namespace等の現在の使用状況などが参照できます。
詳しくは、helpと入力していただくか、以下のページを参照してください。
https://aerospike.com/docs/tools/asadm
動的な設定の変更もこのツールで行えます。

## 3.2 データを操作してみる(aql)
Aerospikeは、[Aerospikeのアーキテクチャ](https://qiita.com/aerospike_nakadai/items/6b6bc68dbc4bba0d7bd3)に記載の通り、各種の開発言語に提供されるAerospike Client Labraryを使用してプログラムから、クラスターにアクセスしてデータのCRUDを行います。
しかし、プログラムを書く前にちょっとAerospikeにアクセスしてデータの追加などしてみたい場合のためのツールがあります。
```
aql
```
または
```
aql -h xxx.xxx.xxx.xxx
```
と入力してください。
```
[ec2-user@ip-192-168-10-2 ~]$ aql
Seed:         127.0.0.1
User:         None
Config File:  /etc/aerospike/astools.conf /home/ec2-user/.aerospike/astools.conf
Aerospike Query Client
Version 9.1.0
aql>
```
では、ここではCRUDを一通り見ていただきます。
上記で作成したssdのnamespaceに、RDBのテーブルにあたるsetとして`testset`を作成してレコードを追加します。ここでsetを作成と書きましたが、特別な処理を行うわけではなく、setを指定してレコードを作成すると自動的にsetが作成されます。
今回は、社員の情報をレコードとして操作してみましょう。
- keyは社員番号(1001,1002等)
- 名前をnameという名前のbin(RDBのカラムにあたるもの)へ文字列としていれる
- 年齢をageという名前のbinへ数値としていれる
- 既婚をmarriedという名前のbinにtrueかfalseでいれる
- 家族の名前をfamiliesという名前のbinにJSONでいれる

以下に実際の入力例を記載します。
まずは、結婚していて家族のいる`yamada taro`さんのレコードを作成します。
```
INSERT INTO ssd.testset (PK, name, age, married, families) VALUES ('1001', 'yamada taro', 30, true, JSON('[{"name":"hanako", "age":25},{"name": "ai", "age":2}]'))
```
次に、未婚で家族のいない`suzuki yukiko`さんのレコードを作成します。
```
INSERT INTO ssd.testset (PK, name, age, married) VALUES ('1002', 'suzuki yukiko', 28, false)
```
この作成したnamespaceがssd、setがtestsetのレコードをすべて参照してみましょう。
```
aql> select * from ssd.testset
+--------+-----------------+-----+---------+---------------------------------------------------------------+
| PK     | name            | age | married | families                                                      |
+--------+-----------------+-----+---------+---------------------------------------------------------------+
| "1001" | "yamada taro"   | 30  | true    | LIST('[{"age":25, "name":"hanako"}, {"age":2, "name":"ai"}]') |
| "1002" | "suzuki yukiko" | 28  | false   |                                                               |
+--------+-----------------+-----+---------+---------------------------------------------------------------+
2 rows in set (0.054 secs)

OK
```
Keyを指定してレコードを表示する場合は、以下のように実行します。
```
aql> select * from ssd.testset where PK='1001'
+--------+---------------+-----+---------+---------------------------------------------------------------+
| PK     | name          | age | married | families                                                      |
+--------+---------------+-----+---------+---------------------------------------------------------------+
| "1001" | "yamada taro" | 30  | true    | LIST('[{"age":25, "name":"hanako"}, {"age":2, "name":"ai"}]') |
+--------+---------------+-----+---------+---------------------------------------------------------------+
1 row in set (0.001 secs)

OK
```
更新については、上記と同じINSERT文で実行します。
変更したいbinのみ入力して変更します。
```
aql> INSERT INTO ssd.testset (PK, married) VALUES ('1002', true)
OK, 1 record affected.

aql> select * from ssd.testset where PK='1002'
+--------+-----------------+-----+---------+
| PK     | name            | age | married |
+--------+-----------------+-----+---------+
| "1002" | "suzuki yukiko" | 28  | true    |
+--------+-----------------+-----+---------+
1 row in set (0.001 secs)

OK
```
他にも追加、更新の記載方法は以下のように様々あります。
helpで表示されますので、ご確認ください。
```
INSERT INTO test.demo (PK, foo, bar, baz) VALUES ('key1', 123, 'abc', true)
INSERT INTO test.demo (PK, foo, bar, baz) VALUES ('key1', CAST('123' AS INT), JSON('{"a": 1.2, "b": [1, 2, 3]}'), BOOL(1))
INSERT INTO test.demo (PK, foo, bar) VALUES ('key1', LIST('[1, 2, 3]'), MAP('{"a": 1, "b": 2}'), CAST(0 as BOOL))
INSERT INTO test.demo (PK, gj) VALUES ('key1', GEOJSON('{"type": "Point", "coordinates": [123.4, -56.7]}'))
```
最後に、削除は以下のように記載します。
```
aql> DELETE FROM ssd.testset where PK='1002'
OK, 1 record affected.

aql> select * from ssd.testset where PK='1002'
Error: (2) 127.0.0.1:3000 AEROSPIKE_ERR_RECORD_NOT_FOUND
```

この状況で、前述のasadmを実行し、infoを入力してみると、以下のように現在の状況を参照できます。
~~~
Admin> info
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Network Information (2024-08-06 06:38:40 UTC)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                Node|Node|               IP|    Build|Migrations|~~~~~~~~~~~~~~~Cluster~~~~~~~~~~~~~~~|Client|  Uptime
                                                    |  ID|                 |         |          |Size|         Key|Integrity|Principal| Conns|
ip-192.168.10.2.ap-northeast-1.compute.internal:3000 |  A1|172.31.0.40:3000 |C-7.1.0.4|   0.000  |   2|FFDC95EAB16B|True     |       A2|     8|01:00:58
ip-192.168.10.3.ap-northeast-1.compute.internal:3000| *A2|172.31.11.68:3000|C-7.1.0.4|   0.000  |   2|FFDC95EAB16B|True     |       A2|     9|01:00:41
Number of rows: 2

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Namespace Usage Information (2024-08-06 06:38:40 UTC)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~A tool for interacting with your Aerospike clust~~~~~
Namespace|                                                Node|Evictions|  Stop|~System~|~~~~Primary Index~~~~~|~~Secondary~~|~~~~~~~~~~~~~~~~~~Storage Engine~~~~~~~~~~~~~~~~~~
         |                                                    |         |Writes|~Memory~|Type|      Used|Evict%|~~~~Index~~~~|  Type|      Used|Used%|Evict%|  Used|Avail%|Avail
         |                                                    |         |      |  Avail%|    |          |      |Type|    Used|      |          |     |      | Stop%|      |Stop%
ssd      |ip-192.168.10.2.ap-northeast-1.compute.internal:3000 |  0.000  |False |      21|mem |128.000 B | 0.0 %|mem |0.000 B |device|256.000 B |0.0 %| 0.0 %|70.0 %|99.0 %|5.0 %
ssd      |ip-192.168.10.3.ap-northeast-1.compute.internal:3000|  0.000  |False |      25|mem |128.000 B | 0.0 %|mem |0.000 B |device|256.000 B |0.0 %| 0.0 %|70.0 %|99.0 %|5.0 %
ssd      |                                                    |  0.000  |      |        |    |256.000 B |      |    |0.000 B |      |512.000 B |0.0 %|      |      |      |
test     |ip-192.168.10.2.ap-northeast-1.compute.internal:3000 |  0.000  |False |      21|mem |  0.000 B | 0.0 %|mem |0.000 B |memory|  0.000 B |0.0 %| 0.0 %|70.0 %|98.0 %|5.0 %
test     |ip-192.168.10.3.ap-northeast-1.compute.internal:3000|  0.000  |False |      25|mem |  0.000 B | 0.0 %|mem |0.000 B |memory|  0.000 B |0.0 %| 0.0 %|70.0 %|98.0 %|5.0 %
test     |                                                    |  0.000  |      |        |    |  0.000 B |      |    |0.000 B |      |  0.000 B |0.0 %|      |      |      |
Number of rows: 4

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Namespace Object Information (2024-08-06 06:38:40 UTC)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Namespace|                                                Node|Rack|  Repl|Expirations|  Total|~~~~~~~~~~Objects~~~~~~~~~~|~~~~~~~~~Tombstones~~~~~~~~|~~~~Pending~~~~
         |                                                    |  ID|Factor|           |Records| Master|  Prole|Non-Replica| Master|  Prole|Non-Replica|~~~~Migrates~~~
         |                                                    |    |      |           |       |       |       |           |       |       |           |     Tx|     Rx
ssd      |ip-192.168.10.2.ap-northeast-1.compute.internal:3000 |   0|     2|    0.000  |2.000  |0.000  |2.000  |    0.000  |0.000  |0.000  |    0.000  |0.000  |0.000
ssd      |ip-192.168.10.3.ap-northeast-1.compute.internal:3000|   0|     2|    0.000  |2.000  |2.000  |0.000  |    0.000  |0.000  |0.000  |    0.000  |0.000  |0.000
ssd      |                                                    |    |      |    0.000  |4.000  |2.000  |2.000  |    0.000  |0.000  |0.000  |    0.000  |0.000  |0.000
test     |ip-192.168.10.2.ap-northeast-1.compute.internal:3000 |   0|     2|    0.000  |0.000  |0.000  |0.000  |    0.000  |0.000  |0.000  |    0.000  |0.000  |0.000
test     |ip-192.168.10.3.ap-northeast-1.compute.internal:3000|   0|     2|    0.000  |0.000  |0.000  |0.000  |    0.000  |0.000  |0.000  |    0.000  |0.000  |0.000
test     |                                                    |    |      |    0.000  |0.000  |0.000  |0.000  |    0.000  |0.000  |0.000  |    0.000  |0.000  |0.000
Number of rows: 4
~~~

他にも、表示方法を変えたり、メタデータを参照したり、様々な利用方法がありますので、aqlをご利用ください。

詳しくは、helpと入力していただくか、以下のページを参照してください。
https://aerospike.com/docs/tools/aql

## 3.3 その他
他にも、ベンチマークツール、バックアップ/リストアツール、データローダーなどありますので、以下のページを参照してください。
https://aerospike.com/docs/tools

# 4. ユーザアプリケーションからの利用
最後に、いちばん重要なユーザアプリケーションからの利用方法を記載します。
前述した通り、ユーザアプリケーションからAerospikeにアクセスするには、Aerospike Client Library(以降、ACL)を使用します。
使用する手順を記載します。
今回は、Pythonで説明しますが、Aerospikeへのアクセスおよび利用方法の考え方は同じですので、参考にしてください。

## 4.1 ACLのインストール
言語によってACLのインストール方法が違ってきます。以下を参考にしてください。
https://aerospike.com/developer/client/install
言語を選択すると、各言語のインストール方法が記載されています。
以下を実行するとインストールされます。pythonおよびpipは事前にインストールしておいてください。
```
pip install aerospike
```

## 4.2 CRUDの実行
次に、CRUDの処理を見ていきます。以下を参考にしてください。
https://aerospike.com/developer/client/usage/atomic

### 4.2.1 レコードの追加
まず、[Create a record](https://aerospike.com/developer/client/usage/atomic/create?client=python)をクリックしてください。

Pythonを選択してください。

実行の重要な手順は以下になります。
- クライアントを作成する
```py
config = {
    'hosts': [ ('127.0.0.1', 3000) ]
}
# Establishes a connection to the server
client = aerospike.client(config).connect()
```
CEを起動したノードのどれかのIPアドレスを記載して（本来は、複数のノードを指定したほうがいいです。）、コネクションを張ります。
これだけで、すべてのノードとコネクションが作成されますので、通常は、このclientをその後の処理では使い続けます。
- Keyを作成する
```python
# Create the record key
key = ('ssd', 'ufodata', 5001)
```
namespace、set、そして、キーの値をタプルで設定します。他の言語では、Keyクラスのインスタンスを作る場合があります。
- Binを作成作成する
```python
# Create the report map
reportMap = {
    'city': 'Ann Arbor',
    'state': 'Michigan',
    'shape': ['circle', 'flash', 'disc'],
    'duration': '5 minutes',
    'summary': "Large flying disc flashed in the sky above the student union. Craziest thing I've ever seen!"
}

# Format coordinates as a GeoJSON string
geoLoc = GeoJSON({'type':'Point', 'coordinates':[42.2808,83.7430]})

# Create the bins
bins = {
    'occurred': 20220531,
    'reported': 20220601,
    'posted': 20220601,
    # reportMap defined in the section above
    'report': reportMap,
    # geoLoc defined in the section above
    'location': geoLoc
}
```
レコードに保存する値をDictionaryで設定します。

- レコードを追加（更新）する
```python
# Write the record to Aerospike
client.put(key, bins, policy=write_policy)
```
KeyとBinとpolicyを設定しputを実行すると、レコードが追加（すでにレコードが存在する場合は更新）されます。

#### コードの実行
各コードの説明がありますが、最後の[Code block](https://aerospike.com/developer/client/usage/atomic/create?client=python#code-block)を展開すると以下のコードがありますので、ご確認ください。


```python
import aerospike
from aerospike import GeoJSON

# Define host configuration
config = {
    'hosts': [ ('127.0.0.1', 3000) ]
}
# Establishes a connection to the server
client = aerospike.client(config).connect()

# Create new write policy
write_policy = {'key': aerospike.POLICY_KEY_SEND}

# Create the record key
key = ('sandbox', 'ufodata', 5001)

# Create the report map
reportMap = {
    'city': 'Ann Arbor',
    'state': 'Michigan',
    'shape': ['circle', 'flash', 'disc'],
    'duration': '5 minutes',
    'summary': "Large flying disc flashed in the sky above the student union. Craziest thing I've ever seen!"
}

# Format coordinates as a GeoJSON string
geoLoc = GeoJSON({'type':'Point', 'coordinates':[42.2808,83.7430]})

# Create the bins
bins = {
    'occurred': 20220531,
    'reported': 20220601,
    'posted': 20220601,
    # reportMap defined in the section above
    'report': reportMap,
    # geoLoc defined in the section above
    'location': geoLoc
}

# Write the record to Aerospike
client.put(key, bins, policy=write_policy)

# Close the connection to the server
client.close()
```
このプログラムの以下の箇所について、
```
key = ('sandbox', 'ufodata', 5001)
```
`sandbox`を`ssd`に変更して
```
key = ('ssd', 'ufodata', 5001)
```
実行するとレコードが作成されます。
aqlで確認すると以下のようになります。
```
aql> select * from ssd.ufodata
+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------+
| PK   | occurred | reported | posted   | report                                                                                                                                                                                                                 | location                                                       |
+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------+
| 5001 | 20220531 | 20220601 | 20220601 | MAP('{"city":"Ann Arbor", "duration":"5 minutes", "shape":["circle", "flash", "disc"], "state":"Michigan", "summary":"Large flying disc flashed in the sky above the student union. Craziest thing I've ever seen!"}') | GeoJSON('{"type": "Point", "coordinates": [42.2808, 83.743]}') |
+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------+
1 row in set (0.033 secs)

OK
```

### 4.2.2 レコードの参照
左のメニューの[Read a record](https://aerospike.com/developer/client/usage/atomic/read?client=python)をクリックしてください。
Pythonを選択してください。
まずは、ページの下の[Code block](https://aerospike.com/developer/client/usage/atomic/read?client=python#code-block)をクリックしてソースを御覧ください。
```python
mport aerospike

# Define host configuration
config = {
    'hosts': [ ('127.0.0.1', 3000) ]
}
# Establishes a connection to the server
client = aerospike.client(config).connect()

# Creates a key with the namespace "sandbox", set "ufodata", and user key 5001
key = ('sandbox', 'ufodata', 5001)

# Create new read policy
policy = {'socket_timeout': 300}

# Get whole record
(key_, meta, bins) = client.get(key, policy=policy)

# Do something
print('Record: ', bins)

# Close the connection to the server
client.close()
```
クライアントの作成とKeyの作成は、レコードの追加と同じです。
以下のコードがレコードの参照の部分です。
```python
# Get whole record
(key_, meta, bins) = client.get(key, policy=policy)
```
このbinsにレコードのBinのデータが入っています。

このページの前半には、レコードのメタ情報だけを取得する方法、レコードの存在チェック方法、一部のBinのみ参照する方法が記載しておりますので、ご確認ください。

### 4.2.3 その他
最初の以下のページから、レコードの更新、削除、その他の処理のサンプルコードが記載されていますので、そちらも参考にしてください。
https://aerospike.com/developer/client/usage/atomic

## 4.3 その他のサンプル
シンプルなCRUD以外にも様々な使用方法があります。以下より御覧ください。
https://aerospike.com/developer/client/usage

# 最後に
このページは、現在(2024/8/6)時点の最新版である7.1.0を対象に記載しています。
7.0および7.1で設定が大きく変更されています。
それ以前のバージョンをすでに使用になっている方には一部違いがあるかと思いますので、[Document page](https://aerospike.com/docs/)を参考にしてご確認ください。

これから、Aerospikeをご利用になる方には、新しい設定や機能になる今がいいタイミングです。
ぜひ、まずは試してみてください。

Aerospike Server Community Editionは、制限がありますが性能はEnterprise Editionと同様になりますので、お試しだけではなく、本番環境でもぜひご利用ください。

日本語でもコミュニティを作っていきたいと考えていますので、このページに記載されていないことでも、気軽にコメントしてください。
このページにコメントしてくださった事には可能な限り回答させていただきます。