RedisのString型は今でも本当に512MBが上限か?

RedisのString型は今でも本当に512MBが上限か?

RedisのString型が512MBが上限であると言われる事が多いことをご存知の方も多いかもしれません。 実際に、Redisの公式ドキュメント(An introduction to Redis data types and abstractions)にも以下のように記載されています。

  • キーの制限

The maximum allowed key size is 512 MB.

  • 値の制限

A value can’t be bigger than 512 MB.

この512MB制限は、キーと値のそれぞれ両方に適用される制限です。理由はRedisの文字列はSDS(Simple Dynamic Strings)で管理されており、バージョン1の制限によります。バージョン2でその制限がなくなりましたが、512MBの制限撤廃のためにはRedis側でも追随する必要がありました。

一方で、String型の512MBのIssueがクローズされていることを確認しました。すなわち、今現在は512MBの制限がなくなったようです。Redis 4.0.7でproto-max-bulk-lenディレクティブが追加されているので、このタイミングと考えられます。

関連するディレクティブ(パラメーター)として2種類あり、proto-max-bulk-lenは実際に実行するコマンドのバイト数の制限、client-query-buffer-limitはRESPのフォーマットを含めたバイト数で制限されます。これらを調整しながら確認していきます。

では、実際に検証して10GBのようなデータでも値として送ることができるのか確認してみましょう。今回はredis-pyを使用して確認します。インストールしていない場合は、pip3 install redisなどで事前にインストールしておいてください。

検証は、MacOSおよびAWSのEC2インスタンスでUbuntu, 20.04 LTS(オレゴンリージョンのAMI ami-03d5c68bab01f3496)、インスタンスタイプはr5.24xlargeのものを使用しました。

最初はMacOS上で検証します。最初からEC2上で検証しても問題ありません。

string512.pyという名前で以下のように512MiBの値をString型として保存する検証用コードを準備します。

import redis

client = redis.Redis(host = '127.0.0.1', port = 6379)
client.set('str512', "a" * int(512 * 1024 * 1024))

print(client.strlen('str512'))

以下のように実行します。

512MBより大きい値を送ると以下のエラーが返ってきます。

そこで、proto-max-bulk-lenディレクティブの値を512mbから10gbに変更します。すると、512MiB+1Bのデータも送信できるようになります。

今度は1GB以上の値を送ると以下のエラーが返ってきます。

Redisサーバー側には以下のメッセージが表示されます。

そこでclient-query-buffer-limitディレクティブの値を1gbから11gbに変更します。前述の通り、client-query-buffer-limitはRESPのフォーマットを含めたバイト数で制限されますので、少し多めに確保しています。

1GBでもデータを送ることができるようになりました。

ここからは検証サイズが大きくなってきましたので、ローカル端末ではなく、大きめのEC2インスタンスを立てて検証します。

次に、4GBより大きな値を送ると以下のようにエラーが返ってきました。

freeコマンドを定期的に取ると、メモリーを使い切ってそうです。

そこでr5.24xlargeに変更に変更したところ(その前はr5.12xlargeで検証していました)、無事10GiBのデータも送ることができるようになりました。

値だけではなく、キーの512MB制限について試す場合も同様に検証できます。コードを以下のように修正するのみです。

ドキュメントにも修正依頼を出しておきました。

Last updated