redis-objectsでHashを扱う場合のちょっとしたメモ書きです。
Redis::Objects
Redisで扱えるデータ型
REDIS_CLASS_NAMES = [:Counter, :HashKey, :List, :Lock, :Set, :SortedSet, :Value]
https://github.com/nateware/redis-objects/blob/master/lib/redis/objects.rb
と
https://github.com/nateware/redis-objects/blob/master/lib/redis/objects/hashes.rb
のおかげでRedis::Objectsをincludeすれば
簡単にRedisのHashを扱えるようになります。
実際のredisへの操作は
https://github.com/nateware/redis-objects/blob/master/lib/redis/hash_key.rb
で行うようです
HashKey
Redis::Helpers::CoreCommandsをincludeしていますので、
storeメソッドでredisのHSETコマンドを実行して、Hashを登録したり、
valuesメソッドでredisのHVALSコマンドを実行して、Hashの値を取得できたりします。
また、Enumerableをincludeしていますので、
...
def all
h = redis.hgetall(key) || {}
h.each{|k,v| h[k] = unmarshal(v, options[:marshal_keys][k]) }
h
end
...
def each(&block)
all.each(&block)
end
...
eachメソッドを使った際にkeyとvalueのペアがhashの配列として
取得できたりします。(たぶん)
Redisクライアント(redis-cli)で接続して確認
キーの一覧
>hkeys [hash name]
hashのキー一覧
>hvals [hash name]
hashの値一覧
>HGETALL [hash name]
hashのキーと値を交互に出力
ちなみに、
ActiveRecordを介して登録した場合は
モデル名:ID:指定したキー
という形になります。
https://github.com/nateware/redis-objects#option-1-model-class-include
また、プロジェクトや環境ごとにキーを区別したいときは
redis-namespace
も一緒に使うといいと思います。
ziplistとhashtable
hash-max-ziplist-entriesとhash-max-ziplist-value
を設定することでziplistを使うための閾値をあげることができます。
ziplistを使う
下記をredis.confに設定
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
>redis-cli INFO memory
used_memory:1007360
used_memory_human:983.75K
used_memory_rss:4890624
used_memory_rss_human:4.66M
used_memory_peak:5134560
used_memory_peak_human:4.90M
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:4.85
mem_allocator:libc
keyが500のhashを登録してみます。
>hashes=""
>for i in {1..500} ; do hashes="$hashes field-name-$i field-value-$i" ; done
>redis-cli HMSET hash01 $hashes
used_memory:1023840
used_memory_human:999.84K
used_memory_rss:4907008
used_memory_rss_human:4.68M
used_memory_peak:5134560
used_memory_peak_human:4.90M
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:4.79
mem_allocator:libc
すると
1023840 - 1007360 = 16480 bytes
ziplistを使わない
下記をredis.confに設定
hash-max-ziplist-entries 50
hash-max-ziplist-value 5
>redis-cli flushall
>redis-cli INFO memory
used_memory:1007520
used_memory_human:983.91K
used_memory_rss:1974272
used_memory_rss_human:1.88M
used_memory_peak:1007520
used_memory_peak_human:983.91K
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.96
mem_allocator:libc
>hashes=""
>for i in {1..500} ; do hashes="$hashes field-name-$i field-value-$i" ; done
>redis-cli HMSET hash01 $hashes
used_memory:1075664
used_memory_human:1.03M
used_memory_rss:2048000
used_memory_rss_human:1.95M
used_memory_peak:1075664
used_memory_peak_human:1.03M
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.90
mem_allocator:libc
1075664 - 1007232 = 68432 bytes
ziplistを使った場合の16480bytesに対して、
使わない場合は68432bytesとなりました。
少ないデータ量の場合はziplistを使ったほうがメモリ効率はよいようです。
データ件数を増やしてみましょう
ziplistを使わない
for j in {1..10000} ; do
hashes=""
for i in {1..500} ; do
hashes="$hashes field-name-$i field-value-$i"
done
redis-cli HMSET "hash$j" $hashes
done
used_memory:1007392
used_memory_human:983.78K
used_memory_rss:3211264
used_memory_rss_human:3.06M
used_memory_peak:2322992
used_memory_peak_human:2.22M
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:3.19
mem_allocator:libc
used_memory:1279824
used_memory_human:1.22M
used_memory_rss:2285568
used_memory_rss_human:2.18M
used_memory_peak:1279824
used_memory_peak_human:1.22M
total_system_memory:8589934592
total_system_memory_human:8.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.79
mem_allocator:libc
ziplistを使う