Redis入門とPythonでのRedis接続をやってみた

#はじめに
現状では勘違い等があるかもしれないので導入部分のみ書いています。
より知りたい方は最後に記載してある、ありがたい参考記事をチェックしてみてください。

#きっかけ
マネージャー「今回の改修でRedis周りも触っているからテストでもその辺よろしく！」
!? :persevere:
Redisとか名前くらいしか知らない。。こりゃ勉強しないと。。。
#Redisって何？
ググってみると[ドットインストール](https://dotinstall.com/)に[Redis入門](https://dotinstall.com/lessons/basic_redis)がある！
プレミアム会員だから活用しないと。
動画を見た結果のRedisの理解の一部は

- データをマトリクスではなく、KVS（Key-Value Store）で扱う
- インメモリデータベースなので永続化しないでRedisを落とすとデータが消える
- デフォルトでDB番号0〜15で分けられている（DB名はない）
- データ構造は String, List, Set, Sorted set, Hash

データの読み書きの基本のコマンドは

```
$ redis-cli　　　　　　　　　　　　　　# Redisサーバーに接続
（以降Redisサーバー接続後）
> exit　　　　　　　　　　　　　　　　　# Redisクライアント終了
> shutdown　　　　　　　　　　　　　　 # Redisサーバーを落とす
> select DB番号　　　　　　　　　　　　# DB切り替え

> set key value　　　　　　　　　　　 # Stringデータのセット
> get key　　　　　　　　　　　　　　　# Stringデータの取得

> rpush key value　　　　　　　　　　# Listデータを末尾にセット（先頭はlpush）
> lrange key 開始index 終了index　　# Listデータの取得。index全指定は 0 -1

> sadd key value　　　　　　　　　　 # Setデータのセット
> smembers key　　　　　　　　　　　　# Setデータの取得

> zadd key score value　　　　　　　# Sorted setデータのセット
> zrange key 開始index 終了index　　# Sorted setデータの取得

> hset key field value　　　　　　　# Hashデータのセット
> hkeys key　　　　　　　　　　　　　 # Hashデータのfieldの取得
> hvals key　　　　　　　　　　　　　 # Hashデータのvalueの取得
> hgetall key　　　　　　　　　　　　 # Hashデータのfieldとvalueの取得

> keys *　　　　　　　　　　　　　　　 # key一覧の取得
> type key　　　　　　　　　　　　　　 # keyのデータタイプを確認
```
なるほど。では早速実験。
でもよく分かっていない状態でローカルを汚すのは嫌なので、RedisサーバーはDockerで立てることにします。

# DockerでRedisサーバーの立ち上げ
```
$ docker run -p 6379:6379 redis
```
上記でもRedisサーバーは立ち上がりますが、永続化していないためサーバーを落とすとデータが消えるので

```
$ docker run --name redis -p 6379:6379 -v [ローカルのパス]:/data redis redis-server --appendonly yes
```
`--appendonly yes`とオプションをつけるとRedisの操作を都度`appendonly.aof`ファイルに書き出す設定になります。
これによりDockerを落としてもデータは保持されます。
Dockerの場合はDocker内の`/data`にファイルが作られるので、`-v`オプションでローカルと繋げてファイルを出力させます。
DockerのRedisサーバーの終了も`$ redis-cli`の`> shutdown`でできます。
その場合Dockerコンテナは残るので`$ docker rm コンテナID`でRedisコンテナの削除をしましょう。
コンテナを消さないまま再度docker runでRedisサーバーを立ち上げようとするとエラーになります。

#日本語が文字化けする！
早速DockerのRedisサーバーに接続して試してみたところ


```
> set json '{"message": null,"results": [{"address1": "東京都","address2": "千代田区","address3": "丸の内","kana1": "ﾄｳｷｮｳﾄ","kana2": "ﾁﾖﾀﾞｸ","kana3": "ﾏﾙﾉｳﾁ","prefcode": "13","zipcode": "1000005"}],"status": 200}'
> get json

"{\"message\": null,\"results\": [{\"address1\": \"\xe6\x9d\xb1\xe4\xba\xac\xe9\x83\xbd\",\"address2\": \"\xe5\x8d\x83\xe4\xbb\xa3\xe7\x94\xb0\xe5\x8c\xba\",\"address3\": \"\xe4\xb8\xb8\xe3\x81\xae\xe5\x86\x85\",\"kana1\": \"\xef\xbe\x84\xef\xbd\xb3\xef\xbd\xb7\xef\xbd\xae\xef\xbd\xb3\xef\xbe\x84\",\"kana2\": \"\xef\xbe\x81\xef\xbe\x96\xef\xbe\x80\xef\xbe\x9e\xef\xbd\xb8\",\"kana3\": \"\xef\xbe\x8f\xef\xbe\x99\xef\xbe\x89\xef\xbd\xb3\xef\xbe\x81\",\"prefcode\": \"13\",\"zipcode\": \"1000005\"}],\"status\": 200}"
```
ぎゃー！ :scream: 文字化けしてるー！（JSONは[郵便番号検索API zipcloud](http://zipcloud.ibsnet.co.jp/doc/api)で適当に拾ったデータ）
調べてみたところ`--raw`オプションをつけてRedisサーバーに接続すれば文字化けは回避できるらしい。

```
$ redis-cli --raw
> get json

{"message": null,"results": [{"address1": "東京都","address2": "千代田区","address3": "丸の内","kana1": "ﾄｳｷｮｳﾄ","kana2": "ﾁﾖﾀﾞｸ","kana3": "ﾏﾙﾉｳﾁ","prefcode": "13","zipcode": "1000005"}],"status": 200}
```
うーん、文字化けは回避できたけれど、JSONは読みにくい・・・。
調べてみたところ[Keylord](https://protonail.com/)というGUIのRedisクライアントがあり良さそうだけど有料！**¥3,592！**高い！
うーん、うーん..JSONのライブラリもあるしPythonでクライアントを書いてみようかな。

#PythonでRedis接続
Redisサーバーへの接続

```python
import redis
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.StrictRedis(connection_pool=pool)
```
コネクションプールを使わずに`r = redis.StrictRedis(host='localhost', port=6379, db=0)`と接続することもできますが、コネクションプールを使った方が接続が速く、閉じる処理も不要なので良いとのこと。
接続後のRedis操作は

```python
r.set('key', 'value')
r.get('key')
r.type('key')
r.keys()
```
と、ほぼredis-cliと一緒。（key一覧取得はちょっと違う）
これは簡単でいい！ということで、さっきのJSONを整形してみます。

```python
import json
js = r.get('json')
js = json.loads(js)
js = json.dumps(js, indent = 2, ensure_ascii = False)
print(js)

{
  "message": null,
  "results": [
    {
      "address1": "東京都",
      "address2": "千代田区",
      "address3": "丸の内",
      "kana1": "ﾄｳｷｮｳﾄ",
      "kana2": "ﾁﾖﾀﾞｸ",
      "kana3": "ﾏﾙﾉｳﾁ",
      "prefcode": "13",
      "zipcode": "1000005"
    }
  ],
  "status": 200
}
```
素敵！ :laughing: 日本語も文字化けしていないしJSONも綺麗！
せっかくなのでtkinterで作ってみました。
<img width="573" alt="スクリーンショット 2019-02-22 1.44.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/361666/89fbaeea-00bc-4713-8279-64f370f4687d.png">
tkinterのコードは省略します。tkinterあまり得意じゃないし..:innocent:
#まとめ
マネージャーに言ったら[Keylord](https://protonail.com/)買ってくれるんだって。会社で :no_mouth: あれ？無駄な苦労？
#まとめ2
結局テスト実施時には開発の人がRedisのデータ投入とかしてくれました..:no_mouth: イイ ベンキョウニ ナッタヨ



###We're hiring!
AIチャットボットを開発しています。
ご興味ある方は [Wantedlyページ](https://www.wantedly.com/projects/266837) からお気軽にご連絡ください！

##参考記事
[ドットインストール Redis入門](https://dotinstall.com/lessons/basic_redis)
[PythonでRedisを扱う(redis-pyの基本)](http://www.denzow.me/entry/2017/10/07/233233)
[日本語を含むUnicodeのJSON文字列を得る.](https://qiita.com/yamaneko1212/items/83d42ab1bdf369fd494a)
[【Python】RedisにJSON形式の文字列を入れて、それをPythonで取得して辞書型に登録するっていう](https://kuzunoha-ne.hateblo.jp/entry/2018/12/07/200000)