Redisチートシート(コマンド編)

- [1. 導入編](http://qiita.com/morrr/items/271548776938e7ddc0ec)
- 2. コマンド編
- 3. [設定編](http://qiita.com/morrr/items/26dbdd87df03315fa680)


## 概要

`redis-cli`の接続後に実行できるコマンドを抜粋した。
コマンドの全容は[公式のリファレンス](https://redis.io/commands)を参照のこと。

またアプリケーション(外部プログラミング言語)によってRedisを操作するためのAPI/バインディングについて調べた。


コマンド
------------------------------------------------------------

SQLと同様に、コマンドの大文字小文字を区別__されない__。
(対してキーは区別される。当然値も)


### 基本的な操作

#### 保持と取得、削除(SET / GET / SETNX / DEL)

キーに対する値を設定/取得する。
GET時にキーが存在しない場合はnilが返る。

```
> SET foo bar   => OK
> GET foo       => "bar"
> GET baz       => (nil)
```


SETNXは、SET if Not eXists の略。
キーが存在しない場合のみ、値を格納する。

```
> SETNX foo 'bar'   => (integer) 1
> SETNX foo 'baz'   => (integer) 0
```

DELでキーを削除する。
復数のキーを指定可能。
成功時には削除件数が返る。

```
> DEL foo           => (integer) 0
> SET foo 'bar'     => OK
> SET hoge 'piyo'   => OK
> DEL foo, hoge     => (integer) 2
> DEL foo           => (integer) 0
```

#### DBを切り替える(SELECT)

復数個のDBを切り替えて使うことができる。
切り替えられるDBの数は設定により決まる。

```
> SELECT 0       => OK
> SET foo 'bar'  => OK
> GET foo        => "bar"

> SELECT 1       => OK
[1]> GET foo     => (nil)
```

#### 検索(KEYS)

SETされたキーを検索する。

```
> SET foo 'bar'
> SET hoge 'piyo'
> KEYS foo
=> 1) "hoge"
=> 2) "foo"


// 正規表現(風？)の指定が可能
> keys fo*
=> 1) "foo"

// マッチしない場合は空が返る
> keys nomatchkey
(empty list or set)
```


#### インクリメント(INCR)

値をインクリメントする。

```
> INCR count   => (integer) 1
> INCR count   => (integer) 2
> INCR count   => (integer) 3
```

```
(チュートリアルより)
GETして+1した値をSETすればいいのでは、と思えるが、
復数ユーザが接続する想定だと、この方法では値に矛盾が起こりえる。
アトミックな挙動を保証するためにINCRはあるのだ、とのこと。
```

#### 有効期限(EXPIRE / TTL)

EXPIREは、キーの期限を秒数で設定する。
期限に到達すると、指定したキーは削除される。
成功時は1, 失敗時は0を返す。


設定した期限は、TTLで確認できる。
期限が未設定の場合は-1を、期限に到達したら -2 を返す。


```
> SET foo 'bar'     => OK
> EXPIRE foo 120    => 1
> TTL foo           => 118

// 120sec

> TTL foo           => -2

> EXPIRE bar        => 0
> TTL bar           => -1
```


### データ構造の操作

#### リスト(RPUSH / LPUSH / LLEN / LRANGE / LPOP / RPOP)

リスト構造を操作するためのコマンド。


RPUSH/LPUSHは、リストの左右にオブジェクトを追加する。

```
// キーabcにオブジェクトを追加していく
> RPUSH abc 'alpha'
> RPUSH abc 'bravo'
> RPUSH abc 'charlie'
> LPUSH abc 'x-ray'
```

LLENは、リストの長さを取得する。

```
> LLEN abc      => 4
```

LPOP/RPOPは、リストの左右からオブジェクトを削除し、返す。

```
LPOP abc        => "x-ray"
```

LRANGEは、範囲を指定してリストを取得する。

```
> LRANGE abc 0 2
=> 1) "alpha"
=> 2) "bravo"
=> 3) "charlie"
```

リストに格納するアイテムは、型を問われない。

```
> RPUSH mixed 'abc'
=> (integer) 1

> RPUSH mixed 123
=> (integer) 2

> LRANGE mixed 0 1
=> 1) "abc"
=> 2) "123"
```


#### セット(SADD / SREM / SISMEMBER / SMEMBERS / SUNION / SINTER / SDIFF)

セット構造を操作するためのコマンド。


SADDは、セットに要素を追加する。

```
> SADD abc 'alpha'      => (integer) 1
> SADD abc 'bravo'      => (integer) 1
> SADD abc 'charlie'    => (integer) 1

// 重複は許可しない
> SADD abc 'alpha'      => (integer) 0
```

SREMは、セットから要素を削除する。

```
> SREM abc 'charlie'    => 1
> SREM abc 'delta'      => 0
```

SISMEMBERは、セットに要素が含まれるか確認する。(is member)

```
> SISMEMBER abc 'alpha'     => (integer) 1
> SISMEMBER abc 'x-ray'     => (integer) 0
```


SMEMBERSは、セットに含まれる要素を出力する。

```
> SMEMBERS abc
=> 1) "bravo"
=> 2) "alpha"
```


SUNIONは、2つ以上のセット(集合)の論理和をとる。
同様にSINTERは積集合、SDIFFは差集合。

```
> SADD groupA 'alice'       => (integer) 1
> SADD groupA 'bob'         => (integer) 1
> SADD groupA 'charlie'     => (integer) 1

> SADD groupB 'alpha'       => (integer) 1
> SADD groupB 'bravo'       => (integer) 1
> SADD groupB 'charlie'     => (integer) 1

// A ∪B
> SUNION groupA groupB
=> 1) "charlie"
=> 2) "alice"
=> 3) "bravo"
=> 4) "bob"
=> 5) "alpha"

// A ∩B
> SINTER groupA groupB
127.0.0.1:6379> SINTER groupA groupB
=> 1) "charlie"

// A - B
> SDIFF groupA groupB
=> 1) "alice"
=> 2) "bob"

```


#### ソート済みセット(ZADD / ZREM / ZRANGE)

ソート済みセットを操作するためのコマンド。

```
> ZADD nations 1 america    => (integer) 1
> ZADD nations 2 britain    => (integer) 1
> ZADD nations 3 china      => (integer) 1
> ZADD nations 100 japan    => (integer) 1  // インデックスは飛んでもいい
> ZADD nations 101 america  => (integer) 0  // 重複すると失敗扱いとなるが、インデックスは変わる

> ZRANGE nations 0 3
=> 1) "britain"
=> 2) "china"
=> 3) "japan"
=> 4) "america"
```


#### ハッシュ(HSET / HGETALL / HMSET / HGET)

ハッシュ構造を操作するためのコマンド。


HSETは、ハッシュにプロパティを追加する。

```
> HSET user name 'alice'                => (integer) 1
> HSET user mail 'alice@example.com'    => (integer) 1
> HSET user password 'test'             => (integer) 1
```

HGETALLは、ハッシュのキーとプロパティを一括取得する。

```
> HGETALL user
=> 1) "name"
=> 2) "alice"
=> 3) "mail"
=> 4) "alice@example.com"
=> 5) "password"
=> 6) "test"
```

HMSETは、復数のキーを同時に設定する。

```
> HMSET user2 name 'bob' mail 'bob@example.com' password 'test2'    => OK
```

HGETは、ハッシュのキーを指定して取得する。

```
> hget user name    => "alice"
```

### トランザクションの操作

#### 実行する(MULTI / DISCARD / EXEC)

トランザクションはMULTIで開始、DISCARDで破棄、EXECで実行する。

```
> MULTI          => OK
> SET a 'alice'  => QUEUED
> SET b 'bob'    => QUEUED

> EXEC
=> 1) OK
=> 2) OK
```

トランザクションを入れ子にすることはできない。

また、Redisは障害時にトランザクションを__ロールバックしない__。途中でエラーがあっても継続して実行される。
(Redisで起こり得るエラーはプログラムミスに限定される、という原則による)


#### 監視する(WATCH / UNWATCH)

WATCHを指定すると、トランザクションの間に他のクライアントがその値を変更した際に、エラーとなるように監視する。

WATCHによる監視は、UNWATCHで解除するかEXECするまで継続される。

```
> WATCH x
// xに対する更新を実施
> MULTI
// トランザクション処理
> EXEC
```

### 接続の制御

#### 保存と終了(EXIT / SAVE / BGSAVE / SHUTDOWN)

EXITは、単にサーバとの接続を切る。

SAVEはDBの状態をスナップショットとしてファイルに保存する。(BGSAVEは非同期保存)

cliを実行中のカレントフォルダに、`dump.rdb` というファイルが作成される。
保存されたrdbファイルは、設定ファイルによって再起動時に読み込むことができる。

SHUTDOWNはSAVE + EXIT。



バインディング
------------------------------------------------------------

復数言語のバインディングが存在し、アプリケーションからRedisを直接操作できる。
対応する言語は[公式の一覧](https://redis.io/clients)を参照のこと。

```ruby:ex.(ruby)
require 'redis'     # gem install redisしておく
r = Redis.new       # #<Redis client v3.3.3 for redis://127.0.0.1:6379/0>
r.ping              # "PONG"
r.set('foo', 'bar') # "OK"
r.get('foo')        # "bar"
```


## 参考
- [Redis(公式)](https://redis.io/)
    - [Redis Quick Start](https://redis.io/topics/quickstart)
    - [Try Redis](https://try.redis.io/)
    - [Commands](https://redis.io/commands)
    - [Clients](https://redis.io/clients)
    - [Transactions](https://redis.io/topics/transactions)
- [Nested hash in redis](http://stackoverflow.com/questions/35720892/nested-hash-in-redis)


***

[設定編](http://qiita.com/morrr/items/26dbdd87df03315fa680)に続く