こんにちは。サイオステクノロジー OSS サポート担当 山本 です。
今回は NoSQL というものについてと、NoSQL の一種である memcached の基本的な使い方を見ていきたいと思います。
■そもそも NoSQL って?
NoSQL もまた、データベースを指す言葉です。
NoSQL という名前の細かい由来や意図などには諸説あるようですが、ざっくりと言うならば…
(前回までで見てきた、SQL を使う MySQL や postgreSQL などのような) RDB ではないデータベースの総称
と言えるでしょうか。
名前からもわかるとおり SQL (RDB) が広く定着した後に出てきた概念で、NoSQL には何かしらの RDB とは違った強みがある場合が多いです。
一方で NoSQL という表現がカバーする範囲は広く、RDB のような「構造上の決まり事」もないため、基本的に NoSQL はそれぞれのソフトウェアごとに特徴や強みや操作方法などがバラバラです。
「NoSQL である」というだけでは (データベースであるということを除いて) どんなソフトウェアかはわからないため、NoSQL のソフトウェアを理解するにはそのソフトウェアごとに個々に理解していく必要があります。
このシリーズでは何回かに分けて、あくまで一例として、何種類かの NoSQL のソフトウェアの基本的な使い方を見ていこうと思います。
■memcached ってどんなもの?
memcached は NoSQL に区分される…場合もあるソフトウェアの一種です。
その特徴をいくつか見てみましょう。
■保存するデータの形
memcached は、「キーワード (key)」と「値 (value)」の組を単位として、データを保存します。
データを保存した後は、「キーワード」で問い合わせると対応する「値」を返してくれる……というのが、基本的な動作になります。
例えばあくまでイメージとしてですが、飲食店のメニューで、メニュー名をキーワードに、値段を値にして保存するならこんな感じでしょうか。
(key):(value)
・トースト:300円
・ホットケーキ:700円
・コーヒー:550円
memcached ではこのような「キーワード」&「値」という形でのみデータを保存します。
もしも「3つ (以上) の要素を持つデータを保存したいなぁー」と思っていたとしても、memcached 側でそのようなデータのための枠組みを用意する機能はありません。「キーワード」と「値」の部分で工夫をすれば、疑似的に実現可能ではあるでしょうが…
また、「キーワード」「値」ともにどんなデータであるかなどの検証は行われず、ただの文字列として単純に保存されます。
■データの保存場所
memcached は、基本的にメモリ上にデータを保存します。
(現在は “サイズの大きな「値」” については、通常の記憶媒体も併用するようになっています。)
ご存じのとおり HDD や SSD などの記憶媒体と比べてメモリは高速であるため、メモリを使用する memcached は記憶媒体を使用するデータベースたちに比べて高速な応答が期待できます。
一方で、メモリは一般的に永続的な保存ができない一時的な記録領域であり、容量も記憶媒体と比べると非常に小さいです。
メモリを使用する memcached は、その性質上データを永続的に保存できず、メモリの圧迫を避けるために使用頻度の低いデータを自動的に削除するようになっています。
名前のとおり「mem (メモリに)」「cache (一時保存する)」「d (デーモン)」、ということですね。
そのため、データの永続的な保存には全くの不向きで、とにかく「速度」を重視したい場合に役立つという、前回までで見てきた RDB とは目的・用途が全く異なるものになっています。
恐らくこうした性質から、データベースなのかそうじゃないのか、場所によって扱いがまばらだったりします。
なお、公式ドキュメントでは「memcached はデータベースではない」と記されていたりします。
しかし「データを保存するツール」であることは間違いないので、この一連のブログで扱ってしまいます。
またメモリを使用する性質上、他のアプリケーションなどでメモリを多く使用した場合に双方に悪影響が出る可能性が考えられます。
このため、memcached は原則として memcached 専用のサーバを用意することが推奨されています。
■複数マシンでの協調動作 (スケールアウト)
memcached では、memcached を動作させるサーバを複数用意して設定を行うことで、それらの複数サーバがあたかも1つの巨大な memcached サーバであるかのように振る舞わせることができます。
つまり、負荷の増大に対して協調動作させるサーバを増やすことで対応する、所謂スケールアウトが可能です。
memcached では、この機能はあくまでデータの保存先を分散させることで負荷を軽減するものです。
設定や「キーワード」などを元に、クライアント側のロジックでデータの保存先となるサーバを判定する、というものであり、その挙動はクライアント側の実装によって異なります。
サーバ側はこの動作に特に関与することはなく、サーバ同士でお互いを認識していません。
例えばいずれかのサーバが何らかの原因で停止した際の対策 (保存データを共有しておくレプリケーションや停止したサーバの動作を別サーバが受け継ぐフェイルオーバーなどのようなもの) のような機能はない点には注意してください。
■memcached (サーバ側) のインストール
memcached のインストールには、各 OS のパッケージ管理システムを使うことが推奨されています。
今回も Red Hat Enterprise Linux 9 を例として使用しますが、この場合は以下のようなコマンドでインストールできます。
$ sudo dnf install memcached
他の OS などでのインストールについては、公式ドキュメントを参照してください。
■memcached (サーバ側) の起動
バイナリファイル memcached (今回の例では /usr/bin/memcached) を実行するか、パッケージ管理システムでのインストールに付属している初期化スクリプトを実行します。
今回の例となる RHEL9 のパッケージでは、/etc/sysconfig/memcached で記述したオプションを使用して memcached を起動する service ファイルが付属しているため、以下のコマンドを実行すれば OK です。、
$ sudo systemctl start memcached
memcached のオプションについては、”man memcached” やドキュメントを参照してください。
特に Listen するアドレスを決める “-l” オプションには留意してください。
■memcached の基本的な使い方
記事の執筆時点では、memcached を直接操作するような “クライアント” は公式から提供されていません。
代わりに「大体のプログラミング言語には memcached のクライアントモジュール/ライブラリがあるので、環境に合ったものを探してクライアント側のドキュメントなどを参照するように。」とされています。
当然ながらクライアントごとに実装内容や使い方、細かい機能などは異なる上に、memcached では例えば先にお話ししたような “データの保存先の決定方法” など一部の機能の挙動がクライアント側に依存しています。
そのため、同一の memcached サーバ群を使用していても、クライアントが異なる場合には原則として意図した結果にならない点にも注意が必要です。
※ 勿論、「クライアントの満たすべき機能」については公式に記載されているため、データの書き込み読み出し等の基本的な機能は原則として全てのクライアントにあるはずですが…
今回の例では特定のクライアントではなく、公式の protocol.txt を参考にして telnet を使って直接 memcached の基本的な動作を見てみようと思います。
なお、実際に memcached を導入する場合には、環境にあったクライアントを使用し、そのクライアントのドキュメントを参照するようにしてください。
■memcached に接続する
telnet で memcached に接続する場合は、memcached のアドレス・ポートを直接指定します。
デフォルトではアドレスは “INADDR_ANY (そのサーバで受けられるアドレスであれば何でも)”、ポートは “11211” です。
例えば、今回の例で用意した memcached サーバの環境から試すのであれば以下のようなコマンドになります。
$ telnet 127.0.0.1 11211
別のサーバから試す場合、firewall やネットワークの設定で予め接続できるようにしておきましょう。
■データを保存する
telnet から直接 memcached の API でデータを保存する場合、接続後に以下のように2回に分けてコマンドを実行します。
set (上記入力後)
それぞれの項目は概ね以下のような役割があります。
(1つ目)
・「キーワード」(2番目の項目)
後にこのデータを読み出すために使う「キーワード」を入力します。
(最大:250文字)
・フラグ (3番目の項目)
符号なし整数を入れることができます。
この項目自体には特別な意味はありませんが、クライアント側でこの項目に意味を持たせた実装をされる場合があります。(例:直列化されているかどうか、など)
または、ユーザ自身が「何かしらの意味」を持たせた値を入れておくことなども可能です。
(最大値:符号なし 16bit または 32bit の整数)
・有効期限 (4番目の項目)
有効期限を秒単位で指定します。
データを保存してからこの時間が経過すると、このデータは無効化され読み出すことができなくなります。
「0」を設定すると、有効期限は無期限になります。
有効期限が過ぎていなくても、memcached の使用する領域が不足した場合には削除されていく可能性がある点には注意してください。
・「値」の byte 数 (5番目の項目)
このデータの「値」の byte 数を指定します。
「値」の byte 数と一致させる必要があり、「値」の byte 数がこれより大きくても小さくてもデータの保存は失敗します。
(2回目)
・「値」
このデータの「値」を設定します。
1回目の入力の5番目の項目で指定した byte 数のデータを入力する必要があります。
例えば、以下のようにしてデータを保存することができます。
set test_key 1 0 14 sample_message
保存に成功した場合、入力の後に “STORED” と表示されます。
“STORED” と表示されない場合は保存が失敗しているので、表示されたメッセージなどを参考に問題点を確認しましょう。
memcached でのデータの保存は、必ず保存を行う “set” の他に
指定した「キーワード」が登録されていない場合にのみ保存を行う “add”、
指定した「キーワード」が登録されている場合にのみ上書き保存を行う “replace”
などがあります。
■データを読み出す
telnet から直接 memcached の API でデータを読み出す場合、接続後に以下のようなコマンドを実行します。
get
「キーワード」のデータが登録されていれば、以下のような形でデータが返ってきます。
VALUE
例えば、先の手順で登録したデータを読み出すと、以下のようになります。
get test_key VALUE test_key 1 14 sample_message END
なお、「キーワード」のデータが登録されていない場合でも特にエラーなどにはならず、ただ何も返さないだけです。
get test END
■データの保存期間と失効について
先にお話ししたとおり、memcached ではデータを永続的に保存できません。
例えば、memcached を再起動した場合、保存されたデータは全て消えてしまいます。
再起動の際に一時的にデータを記憶媒体に移す機能もありましたが、記事投稿の時点では改修中でした。
今回の環境でも以下のようにして、保存したデータが再起動で消えてしまうことを確認できるかと思います。
(telnet の操作を抜ける場合は、”quit” と入力してください。)
$ sudo systemctl restart memcached $ telnet 127.0.0.1 11211 : get test_key END
また、保存の際に有効期限を指定しておくことで、指定した時間が経過した後にはそのデータを読み出すことができなくするようにもできます。
例えば、以下のように保存したデータは、書き込み後1分以内にしか参照することができません。
set test_expire 1 60 14 sample_message
■最後に
今回は比較的新しいデータベース群の概念 NoSQL についてざっくりと、
「データベースではない」と名乗っていながら、データベースと扱われたり扱われなかったりするなんとも微妙な立ち位置の memcached についてお話ししました。
memcached 自体は NoSQL と呼ぶべきか否かは難しいところですが、その特徴である
・「キーワード (key)」と「値 (value)」の組でのみデータを保存 (store) する方式:KVS (Key Value Store)
・データをメモリに保存して高速化を図る:インメモリ
・複数のマシンで協調動作させることで、容量の拡張や負荷軽減を図る:スケールアウト
などは、他の NoSQL のソフトウェアでも見られることのある特徴なのでどういったものなのか覚えておいて損はないはずです。
わからないなりに理解したいデータベース②:RDB編:MySQL②
わからないなりに理解したいデータベース③:RDB編:MariaDB
わからないなりに理解したいデータベース④:RDB編:PostgreSQL
(今回) わからないなりに理解したいデータベース④:NoSQL編:memcached