Redisで大量データを扱う時の助っ人たち　①PostgreSQLのFDW

#はじめに
業務データやログ、さらにはストリームデータなど、多量のデータをRedisで扱うことかある。
私の場合、数億行✕数種類と、数千万行✕数百種類のデータが相手。
Redisの場合、条件に数千万行までのデータはハッシュ(HSET,HMSET)を使うことでアクセスもそこそこ高速でいてくれて、数億行になった後に応答速度とかRAM容量とかがかなり気になってくる感じ（そのため、データベースの分割を行ったり、それで混乱したり...）。

ということで、ここではRedisにたくさんのデータを突っ込んてあれこれ探す作業を効率化・高速化するためのTipsを備忘録としてまとめていく。
取り上げる予定は、
・　PostgreSQLのredisFDW(redisのデータをSQLのテーブルとして扱える) => 今回
・　[Vedis](https://github.com/symisc/vedis)（ネットワーク層を省いたredisリスペクトの軽量KVS）
・　[rediSQL] (https://github.com/RedBeardLab/rediSQL) (Redis module that provides a completely functional SQL database)

といったところ。

#Redisの活用シーン
Redisというとsorted setによるリアルタイムランキングが有名なのだろう（ [こちら](http://qiita.com/niisan-tokyo/items/170ef3ac47ee39cfb46c)とか）。ここではそれ以外の使われ方を書いておく。
##①　バッチ処理:pipeでのデータ投入
redisはデータを高速に受け取るのは得意。
　例えば、redisコマンド入りのテキストを作成し、

```mydata.txt
 HSET mytable data1 123
 HSET mytable data2 456
 HSET mytable data3 789
 ... 延々と続く　...
``` 
クライアント（redis-cli）のpipeモードでデータを一括投入できる。
　
>cat mydata.txt | redis-cli --pipe

※（私が普段使いしている環境のように）行の先頭に半角スペースを入れないとただしくデータ投入がなされない場合があることに注意。


参考　[Redis Documentation日本語訳『大量データのインサート』](http://redis-documentasion-japanese.readthedocs.io/ja/latest/topics/mass-insert.html)

##② ストリーム処理:キューイング
redisでは（リストと呼ばれる）キューイングに使いやすいpush/popの仕組みを持つ。
今のところストリーム処理はおこなっていないので、あまり試していないのだけれど、
Spark streamingやApache Flinkとの組み合わせていける模様。
このあたり、キューイングについてまとめてくれている以下の資料が参考になる（まとめが３３枚目、40枚目）。
[ストリーム処理を支えるキューイングシステムの選び方](https://www.slideshare.net/laclefyoshi/ss-67658888)

気合を入れて使うのにはキューイングに特化したApache Kafkaがおすすめらしいけど、とりあえずredisで、という選択肢があるのはうれしい。

#redisのハッシュをPostgresで扱う例

PostgreSQLのredis向けFDWを使ってうれしいのは、redisのハッシュに対しSQLでクエリをかけられることだろう。このアクセスは、最近のPostgresに入っているキーバリューストアhstoreを介して行われる。
そのため、はじめにpsqlでPostgreSQLに接続し、redis_fdw拡張に加え、hstore拡張を生成しておく必要がある。

```PostgreSQL.psql
CREATE EXTENSION redis_fdw;
CREATE EXTENSION hstore;
```
（redis_fdwのインストールと初期設定は[こちら](http://qiita.com/fujii_masao/items/6c116047cc134f2bed29)が参考になる。）

personから始まるキーを持つ以下のようなハッシュを登録した場合

```redis.cli
HMSET person:id100 name Nicolson age 55
```

PostgreSQL側に対応するテーブルredisPersonを用意し、

```PostgreSQL.psql
CREATE FOREIGN TABLE
 redisPerson (key text, value text[])
 SERVER redis_server 
 OPTIONS (database '0', tabletype 'hash', tablekeyprefix 'person:')
;
```

以下のようなクエリで50歳以上の人を絞り込むことができる。


```PostgreSQL.psql
select * from
 (select key,hstore(value) as value from redisPerson) as X
  where cast(value->'age' as numeric) > 50
;
```
結果

     key      |                    value                     
--------------+----------------------------------------------
 person:id100 | "age"=>"55", "name"=>"Nicolson"


SQLが得意な人にとっては、その知識を活かしつつ、PostgreSQL方言のhstoreをマスターするだけなので、　redis埋没データの発掘方法としては一番お手軽なのかと思う。
私は、redis_fdwを使えるようにするのに必要なスーパーユーザー権限の申請に気がひけて、業務では未活用。お試しした際のスクリーンショットを以下に貼っておく。

![スクリーンショット 2017-09-17 21.58.51.png](https://qiita-image-store.s3.amazonaws.com/0/16455/2c54e869-2313-ecf2-dc3d-136addae6114.png)

![スクリーンショット 2017-09-18 10.40.11.png](https://qiita-image-store.s3.amazonaws.com/0/16455/7f7cb0d2-0e3c-1b96-4734-41fa70d2a6a0.png)

# （参考）redis_fdwのインストール記

RedisのCクライアントライブラリとredis-fdwの両方が必要。
これらの導入は、PostgreSQLのバージョンやインストール状況に依存する。
必要条件は、　（おそらく）以下の通り
> psqlにパスを通しておくこと
> postgresql-server-devのインストール
> PostgreSQLのバージョンに合わせたredis_fdwブランチを導入

Ubuntu(Cloud9)に導入したpostgresql9.6の場合、

```
PATH=/usr/usr/share/postgresql-common/:$PATH #最近のpostgresの場合
sudo apt-get install postgresql-server-dev-9.6
git checkout -b REL9_6_STABLE origin/REL9_6_STABLE
```
が必要だった。ここに至るまで、若干の試行錯誤が。。
web上の導入記を見てみても、皆それぞれの環境で試行錯誤しながら導入している模様。

以下のようにdockerを使ってredisデータ分析用のpostgresを導入するのが簡単かと思う。
（redisのデータをrdbファイルとして移動させることは簡単）
[Docker で PostgreSQL の FDW を使って MySQL や Redis と JOIN してみた](
http://qiita.com/kitsuyui/items/c2cd38daa78d1eb07a3c)


関係ないけど、（私は趣味で使っている）cloud9はdocker環境にも導入できるので、両方扱えるようにしておくと、近い将来に、チーム開発の場面で約だったりするかもよ（=>近い将来の自分向けに）。