redis-objects de Hash

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](https://github.com/nateware/redis-objects/blob/master/lib/redis/hash_key.rb)
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](https://github.com/resque/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を使う
```

```

```

```


## redis-objectsを使う場合は