これは、なにをしたくて書いたもの?
Valkeyのクライアントライブラリーとして、Valkey GLIDEというものがあるようなので試してみることにしました。
各言語のRedisクライアントが、どんどんredis Organizationに移っていっていたのでちょっと気になっていたんですよね。
Valkey GLIDE
Valkey GLIDEのGitHubリポジトリーはこちら。
Valkey GLIDEはValkeyとRedisをサポートするクライアントライブラリーです。
GLIDEというのは「General Language Independent Driver for the Enterprise」の略らしいです。
Valkey General Language Independent Driver for the Enterprise (GLIDE), is an open-source Valkey client library.
現時点でValkey 7.2、8.0、Redis 6.2、7.0、7.2をサポートしています。
複数の言語向けに提供されていて、Java、Python、Node.jsがあります。リポジトリーを見ているとGo、C#もありそうですね。
AWSによるブログなどはこちら。
Valkey GLIDE – Valkey と Redis OSS向けのオープンソースクライアントライブラリのご紹介 | Amazon Web Services ブログ
Valkey と Redis OSS のクライアントである Valkey GLIDE v1.1 が Node.js のサポートを開始 - AWS
ValkeyおよびRedisのすべてのコマンドのサポート、クラスターやレプリカからの読み取りへの対応、ステートフル接続を使った自動的な
pub/sub再接続などを機能として持っているようです。
内部構成としては、Rustで実装されたredis-rsをコアとしていて、各言語に対してラッパーと呼ばれるバインディングとコミュニケーション
レイヤーで構成されているようです。
ドキュメントはこちら。
Home · valkey-io/valkey-glide Wiki · GitHub
General Concepts · valkey-io/valkey-glide Wiki · GitHub
各ラッパーのドキュメント。
Java Wrapper · valkey-io/valkey-glide Wiki · GitHub
NodeJS wrapper · valkey-io/valkey-glide Wiki · GitHub
Python wrapper · valkey-io/valkey-glide Wiki · GitHub
各言語の実装状況は、こちらのページで確認できるようです。
ValKey Commands Implementation Progress · valkey-io/valkey-glide Wiki · GitHub
これを見ると、そのうちPHPのラッパーも実装されそうですね。
redis-rsについて
Valkey GLIDEはRustで実装されたredis-rsをコアとしていると書きましたが、redis-rsはValkey GLIDEのリポジトリーに取り込まれています。
https://github.com/valkey-io/valkey-glide/tree/v1.2.0/glide-core/redis-rs
オリジナルのredis-rsはこちらです。
GitHub - redis-rs/redis-rs: Redis library for rust
なのですが、Valkey GLIDEはredis-rsのフォークを使用していました。
GitHub - amazon-contributing/redis-rs: Redis library for rust
それがこちらのPull RequestでValkey GLIDEの中に取り込まれたようです。
Make redis-rs part of this repo by eifrah-aws · Pull Request #2456 · valkey-io/valkey-glide · GitHub
ドキュメントを見ていると、redis-rs 0.25.2からのフォークに見えますね。
ドキュメントなどを見るのはこれくらいにして、試してみましょう。今回はPythonラッパーを使うことにします。
環境
今回の環境はこちら。
$ python3 --version Python 3.12.3 $ pip3 --version pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)
Valkey。
$ bin/valkey-server --version Valkey server v=8.0.1 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=62879af2f2d0ec0f
Valkeyの設定は以下とし、172.17.0.2で動作しているものとします。
conf/valkey.conf
bind 0.0.0.0 user default off user valkey-user on >password +@all ~* &*
Valkey GLIDEのPythonラッパーを試す
では、Valkey GLIDEのPythonラッパーを試してみます。
valkey-glide/python at v1.2.0 · valkey-io/valkey-glide · GitHub
Python wrapper · valkey-io/valkey-glide Wiki · GitHub
インストール。
$ pip3 install valkey-glide
型定義はValkey GLIDEに含まれていそうです。
あとはpytestとMypyをインストール。
$ pip3 install pytest pytest-asyncio mypy
Valkey GLIDEではasync
、await
を使うことになりそうなのでpytest-asyncioをインストールしています。
GitHub - pytest-dev/pytest-asyncio: Asyncio support for pytest
インストールしたライブラリーの一覧。
$ pip3 list Package Version ----------------- ------- iniconfig 2.0.0 mypy 1.13.0 mypy-extensions 1.0.0 packaging 24.2 pip 24.0 pluggy 1.5.0 protobuf 5.29.1 pytest 8.3.4 pytest-asyncio 0.24.0 typing_extensions 4.12.2 valkey-glide 1.2.0
まずはテストコードの雛形。
tests/test_glide.py
from glide import GlideClient, GlideClientConfiguration, NodeAddress, ServerCredentials, Transaction import pytest ## ここに、テストを書く!
まずはValkeyへの接続、切断から。
@pytest.mark.asyncio async def test_connect_valkey() -> None: addresses = [NodeAddress("172.17.0.2", 6379)] credentials = ServerCredentials("password", "valkey-user") config = GlideClientConfiguration(addresses, credentials=credentials) client = await GlideClient.create(config) await client.close()
async
、await
を使うことになるんですね。
このあたりを参考にしています。
Python wrapper / Client Initialization / Standalone
Python wrapper / Advanced Configuration Settings / Authentication
ところで、pytestを実行するとこんな警告が出力されていたので
/path/to/site-packages/pytest_asyncio/plugin.py:208: PytestDeprecationWarning: The configuration option "asyncio_default_fixture_loop_scope" is unset. The event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: "function", "class", "module", "package", "session" warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET))
pytest.ini
を作成してこのように設定。
pytest.ini
[pytest] asyncio_default_fixture_loop_scope = function
デフォルト値らしいですけど。
Configuration — pytest-asyncio 0.25.2.dev5+g2188cdb documentation
set、getコマンド。
@pytest.mark.asyncio async def test_set_get() -> None: addresses = [NodeAddress("172.17.0.2", 6379)] credentials = ServerCredentials("password", "valkey-user") config = GlideClientConfiguration(addresses, credentials=credentials) client = await GlideClient.create(config) try: await client.set("key1", "value1") assert await client.get("key1") == b"value1" await client.delete(["key1"]) assert await client.get("key1") == None finally: await client.close()
最後にdeleteも入れていますけど。
値は自動的にエンコードされるようですが、取得した時にはデコードされていないようです。
hset、hget。
@pytest.mark.asyncio async def test_hset_hget() -> None: addresses = [NodeAddress("172.17.0.2", 6379)] credentials = ServerCredentials("password", "valkey-user") config = GlideClientConfiguration(addresses, credentials=credentials) client = await GlideClient.create(config) try: await client.hset("hkey1", {"key1": "value1", "key2": "value2"}) assert await client.hget("hkey1", "key1") == b"value1" assert await client.hgetall("hkey1") == {b"key1": b"value1", b"key2": b"value2"} await client.delete(["hkey1"]) assert await client.hgetall("hkey1") == {} finally: await client.close()
@pytest.mark.asyncio async def test_transaction() -> None: addresses = [NodeAddress("172.17.0.2", 6379)] credentials = ServerCredentials("password", "valkey-user") config = GlideClientConfiguration(addresses, credentials=credentials) client = await GlideClient.create(config) try: transaction = Transaction() transaction.set("key1", "value1") transaction.set("key2", "value2") transaction.get("key1").get("key2") result = await client.exec(transaction) assert result == ["OK", "OK", b"value1", b"value2"] await client.delete(["key1", "key2"]) finally: await client.close()
Python wrapper / Valkey commands / Transaction
トランザクションといっても、multi/execのことですが。
Valkey Documentation · Transactions
こんなところでしょうか。
おわりに
ValkeyとRedisのクライアントライブラリー、Valkey GLIDEをPythonラッパーで試してみました。
Valkey GLIDEの概要がわかったのと、Pythonラッパーの場合はasync
/await
を使ったスタイルになることがわかりました。
今後は、Valkeyを使う時はValkey GLIDEに慣れていってみようと思います。