はじめに
Redisの検証を行う際に、検証用のデータを作成する必要が生じまして、その方法を考えました。
文字型やリスト型などで、キーと値だけ定義できればよいならredis-benchmarkが使えるのですが、redis-benchmarkでは以下のようなことはできないようでした。
- セット型で1つのキーに複数の要素を持たせる
- キーに有効期限を設定する
他にも、ソート済みセット型やHyperLogLog型などを登録してみたいと思いましたが、いずれもredis-benchmarkではできないようでした。そもそも、redis-benchmarkはRedisのベンチマークツールです。
今回はSet型で1つのキーに複数の要素を持たせるようにしたかったので、Pythonのクライアントライブラリredis-pyを使ってみました。
1つのSet型に1000万・2000万という要素を持たせると、キーの削除には数秒かかり、その間はブロックが発生します。このブロックをわざと発生させるための方法を考えていて、Set型に1000万単位で要素を登録することを思いついて、その処理にクライアントライブラリを使おうと考えました。
Set型1つに1000万単位で要素を持たせる事自体は、実用的な使い方ではないですが、キー削除時のブロック処理・ノンブロック処理を検証するには都合の良いキー・値となります。
Pythonのクライアントライブラリredis-pyのインストール
クライアントライブラリのインストールを行います。
$ pip install redis
参考・redis-cliでセット型のキーを登録する
以下のキーを登録するとします。
- セット型でmysetというキー
- 10個の要素
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
セット型のキーの登録にはSADD
コマンドを使います。
127.0.0.1:6379> SADD myset 1 2 3 4 5 6 7 8 9 10
(integer) 10
Pythonで上記のキーを登録するには?
redis.commands.core.CoreCommandsのsadd
コマンドを使います。
1つ目の引数にキー名を、2つ目以降は要素をカンマ区切りで列挙します。
import redis
r = redis.Redis(host='localhost', port=6379)
r.sadd('mydata', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
以後、import ...
とr = redis ...
は省略します。
最初に考えた記述
sadd
コマンドの挙動を確認した際に、値はカンマ区切りで列挙すれば登録できていたことから、当初はrange()で連番を作り、それをリスト型にした後、カンマ区切りで文字型にしたものを値として渡せばよいと思いました。
l = list(range(1, 11))
s = ','.join(str(n) for n in l) # print(s)で確認すると 1,2,3,4,5,6,7,8,9,10
r.sadd('mySet', s)
r.sadd('mySet', 1,2,3,4,5,6,7,8,9,10)
になると思ったのですが、登録されたキーを確認したら、要素数は1でした。これは失敗です。
127.0.0.1:6379> SMEMBERS mySet
1) "1,2,3,4,5,6,7,8,9,10"
うまくいった記述
リスト型でデータを作った後、アンパックしてsaddのvalueに渡すとうまくいきました。
l = list(range(1, 11)) # print(l)で確認すると [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
r.sadd('mySet', *l)
確認すると、今度は意図したとおりに10個の要素が登録されていました。
127.0.0.1:6379> SMEMBERS mySet
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
10) "10"
要素数を1000万件にして実行
この後、range()
の引数を1, 10_000_001
にしてsadd
コマンドを実行、redis-cliで確認したところ、キーの要素数が1000万となったことを確認できました。
127.0.0.1:6379> SCARD myset
(integer) 10000000
SMEMBER myset
でも確認しました。1000万件の要素を表示するのに140秒程かかりました。
127.0.0.1:6379> SMEMBERS mySet
1) "6538995"
2) "756997"
3) "3976871"
【中略】
9999998) "9994395"
9999999) "4432247"
10000000) "5477660"
(140.21s)