Redisの使い方

# はじめに
Redisに最後に触れたのが結構前なので、
自身の備忘録をかねてRedisの環境構築、また動作について改めて確認してみました。

拙い文章ですが、どなたかの助けになれば幸いです。

# 前提環境環境
* MacOS Catalina
* Docker
* Homebrew

# Redisとは
いわゆるNoSQLの一つです。
RDBと比べても高速に動作し、構造化、準構造化、非構造化データを問わず、あらゆるタイプのデータを、
事前定義のスキーマに頼るRDBよりも容易に扱うことができます。
事前定義に左右されないため、柔軟なデータ構造を保持可能です。
また、分散処理にも適しています。

NoSQLの参考： https://aws.amazon.com/jp/nosql/

# 主なユースケース
I/O共に高速に動作するために、 主に下記用途で使われるケースが多いのではと思います。

* キャッシュ用途
* リアルタイムランキング集計
* 大量メッセージ送信のQueue

# データ保持形式
いわゆるKVS（Key-Value Store）の形式でデータを保持します。
KVSはKeyとValueを組み合わせる単純な構造からなるデータストアです。
Keyを指定すると対となるValueが返却されるものになります。
Redisは下記5つのデータ型を使用可能です。

* String型
* List型
* Set型
* SortedSet型
* Hash型

# 環境構築について
Dockerで構築するのがお手軽なので、下記コマンドでRedisのコンテナを起動します。

## Redisコンテナの起動
```bash
docker run --name redis -d -p 6379:6379 redis redis-server --appendonly yes
```
## 起動確認
無事に起動しています。

```bash
% docker ps -a
CONTAINER ID        IMAGE        COMMAND                  CREATED             STATUS              PORTS                                NAMES
XXXXXXXXXXXX        redis        "docker-entrypoint.s…"   5 seconds ago       Up 4 seconds        0.0.0.0:6379->6379/tcp               redis
```

## ホストPCへのインストール
コンテナのRedisに接続するために、ホストへもRedisをインストールします。
ここでは `Homebrew` を使用してインストールしています。

```bash
% brew install redis
```

## 接続確認
下記コマンドで接続します。

```bash
% redis-cli
127.0.0.1:6379>
```
無事に接続できました。

# 各型の挙動確認
各型について軽く挙動を確認しましたが、それぞれの詳細なコマンドや型の説明は、下記リファレンスが参考になります。
[datatypes](http://redis.shibu.jp/datatypes.html)

## String型
String型はバイナリセーフで、どんな種類のデータも保持できます。
画像やシリアライズされたオブジェクト等も保持可能です。

### 値の設定

```bash
127.0.0.1:6379> set name inagacky
OK
```
### 値の取得

```bash
127.0.0.1:6379> get name
"inagacky"
```

## List型
String型のリストです。

### 値の設定
`LPUSH` コマンドでは新しい要素をリストの先頭に追加、 `RPUSH` では新しい要素を末尾に追加します。

```bash
127.0.0.1:6379> lpush sampleList hogehoge
(integer) 1
127.0.0.1:6379> rpush sampleList fugafuga
(integer) 2
```
### 値の取得
`lindex` コマンドでは、インデックスを指定して値を取得します。

```bash
127.0.0.1:6379> lindex sampleList 0
"hogehoge"
127.0.0.1:6379> lindex sampleList 1
"fugafuga"
```

## Set型
Set型ではメンバの重複を許可しないという性質があります。
そのため、下記の例では `member1` を2回追加していますが、
Setには一つしか格納されていません。

### 値の設定

```bash
127.0.0.1:6379> sadd test_set member1
(integer) 1
127.0.0.1:6379> sadd test_set member2
(integer) 1
127.0.0.1:6379> sadd test_set member3
(integer) 1
127.0.0.1:6379> sadd test_set member1
(integer) 0
```

### 値の取得
```bash
127.0.0.1:6379> smembers test_set
1) "member3"
2) "member2"
3) "member1"
```

## SortedSet型
Set型と似ていますが、すべてのメンバに対してスコアを指定する必要があります。
そのスコアを用いて、メンバ情報を並べ替えてくれます。

### 値の設定

```bash
127.0.0.1:6379> zadd sort_set 1 member1
(integer) 1
127.0.0.1:6379> zadd sort_set 2 member3
(integer) 1
127.0.0.1:6379> zadd sort_set 3 member2
(integer) 1
```

### 値の取得
```bash
127.0.0.1:6379> ZRANGE sort_set 0 2
1) "member1"
2) "member3"
3) "member2"
```

## Hash型
Hash型は、フィールドと値のマップです。
オブジェクト構造を表現することができます。
下記の例では、 `member1` として  `taro` の情報、
`member2` として `hanako` の情報を格納しています。

### 値の設定

```bash
127.0.0.1:6379> hset member1 name taro
(integer) 1
127.0.0.1:6379> hset member1 age 20
(integer) 1
127.0.0.1:6379> hset member1 gender male
(integer) 1
127.0.0.1:6379> hset member2 name hanako
(integer) 1
127.0.0.1:6379> hset member2 age 21
(integer) 1
127.0.0.1:6379> hset member2 gender female
(integer) 0
```

### 値の取得
```bash
127.0.0.1:6379> hget member1 name
"taro"
127.0.0.1:6379> hget member2 name
"hanako"
127.0.0.1:6379> hkeys member1 # キー情報の取得
1) "name"
2) "age"
3) "gender"
127.0.0.1:6379> hvals member1 # バリューの取得
1) "taro"
2) "20"
3) "female"
127.0.0.1:6379> hGetAll member1 # キーに対するハッシュ値全て取得。
1) "name"
2) "taro"
3) "age"
4) "20"
5) "gender"
6) "male"
```

# SDK
各言語ごとのSDKについては、下記にまとめられています。
https://redis.io/clients

# 最後に
redisは非常にシンプルですし、様々な用途があるかと思います。
必要に応じて採用し、しっかりと使いこなしていきたいものです。
読んで頂きありがとうございます！