配列とアトミックな処理に強いKVS Redis

2017.01.18

こんにちは、YDCのミッツです。
Key-Valueストア(KVS)はシンプルな構造ですが、それぞれに特徴があり、少しずつ用途が異なります。
今回はKVSについて改めて説明しつつ、そんなKVSの一つであるRedisの主な特徴を紹介いたします。

KVSとは

まずはKVSについて簡単に説明します。
KVSとは一意なKeyとそれに対応する値(value)をペアで保存する簡素な構造のデータベースを言います。
KVSはデータの保持の仕方で揮発性KVSと永続性KVSに分けられます。

揮発性KVSはメモリのみにデータを保持するため、処理が高速ですがOSの再起動などでデータが消去されてしまうという
デメリットがあります。対して永続性KVSはディスクにデータを保持するため、パフォーマンスで揮発性KVSに劣るものの
データが消えることはありません。
データが消えてしまうという点で用途が限定される揮発性KVSに対し、永続性KVSはより幅の広い用途に使用できます。

RDBは複数のテーブルのJOINが必要となるような処理でどうしてもレスポンスが悪化することが懸念されますが、
KVSなら常に高速にレスポンスを返すことができます。
永続性KVSがパフォーマンスで揮発性KVSに劣るといっても、大量のデータをJOINするRDBと比較すると十分高い
パフォーマンスを発揮することが期待できます。

Redisとは

では、RedisとはどのようなKVSなのでしょうか。
Redisはイタリアの開発者が個人で開発し、2009年に公開されました。
上述の揮発性、永続性の分類でいうと基本的には揮発性KVSに当たります。
しかし、特定のタイミングでディスクにデータを書き込むよう設定したり、
随時データを書き込むよう設定したりできるため、永続性KVSとして使用することもできます。
データが消えても問題がない場合には永続化せずパフォーマンスを最大化し、
データが消えると困るような場合は永続化するといったようにRedisだけで柔軟に対応することが可能です。

永続化以外にもRedisには他のKVSがあまり持っていない特徴があります。
以下ではRedisの代表的な特徴について紹介したいと思います。

様々なデータ型

多くのKVSでは列はデータ型を持たず、文字列、またはバイト列しか格納できません。
しかし、Redisでは文字列型であるStringの他に配列形式のデータを格納することが可能です。
Redisが扱うことのできるデータ型は次の5種類です。

  • String
  • List
  • Set
  • Sorted Set
  • Hash

それぞれのデータ型について簡単に説明します。

String (文字列型)

最も基本的な文字列型です。1つのキーに対して1つの値が格納されます。

> set name Mitz
OK
> get name
"Mitz"
> mset shoes HIANGLE redpoint 5.11d ★まとめて書き込む場合
OK
> mget name shoes redpoint ★まとめて取得する場合
1) "Mitz"
2) "HIANGLE"
3) "5.11d"

List (リスト型)

リスト型は順番を持った文字列型の集合です。リストには新しい要素を先頭か末尾に追加することが可能です。

> rpush order Maru Luna Eldred ★末尾に値を追加
(integer) 3
> lrange order 0 2 ★1番目から3番目まで取得
1) "Maru"
2) "Luna"
3) "Eldred"
> lpush order Kikuchi Tanaka ★先頭に値を追加
(integer) 5
> rpush order Arai Shimozuru Ishihara Johnson
(integer) 9
> lrange order 0 -1 ★1番目から末尾から1番目(1番右端)まで取得
1) "Tanaka"
2) "Kikuchi"
3) "Maru"
4) "Luna"
5) "Eldred"
6) "Arai"
7) "Shimozuru"
8) "Ishihara"
9) "Johnson"
> lindex order 3 ★4番目を取得
"Luna"
> rpop order ★先頭を削除
"Johnson"
> lpop order ★末尾を削除
"Tanaka"

Set (セット型)

セット型は順番を持たない文字列型の集合です。要素の重複は許可されません。
和集合、差集合、積集合といった演算を行うことが出来ます。

> sadd set1 a ★値の追加
(integer) 1
> sadd set1 b
(integer) 1
> sadd set1 c
(integer) 1
> smembers set1 ★値の参照
1) "a"
2) "c"
3) "b"
> srem set1 c ★値の削除
(integer) 1
> smembers set1
1) "a"
2) "b"
> sadd set 1 d e f h
(integer) 5
> sadd set1 d e f h
(integer) 4
> smembers set1
1) "e"
2) "b"
3) "h"
4) "a"
5) "d"
6) "f"
> sadd set2 b c d f g h
(integer) 6
> sunion set1 set2 ★和集合の取得
1) "c"
2) "h"
3) "e"
4) "b"
5) "a"
6) "d"
7) "f"
8) "g"
> sdiff set1 set2 ★差集合の取得
1) "a"
2) "e"
> sinter set1 set2 ★積集合の取得
1) "b"
2) "h"
3) "d"
4) "f"

Sorted Set (ソート済みセット型)

ソート済みセット型はセット型とよく似ていますが、個々の要素がそれぞれスコアという値をもっており、スコア順にソートされます。

> zadd sset 1 a ★値の追加
(integer) 1
> zadd sset 2 b
(integer) 1
> zadd sset 3 c
(integer) 1
> zrange sset 0 1 ★スコアが低い順に1番目から2番目までの値を取得
1) "a"
2) "b"
> zrange sset 0 2 ★スコアが低い順に1番目から3番目までの値を取得
1) "a"
2) "b"
3) "c"
> zrevrange sset 0 1 ★スコアが高い順に1番目から2番目までの値を取得
1) "c"
2) "b"
> zrem sset c ★値の削除
(integer) 1
> zrange sset 0 -1 ★スコアが低い順に1番目から高い順に1番目までの値を取得
1) "a"
2) "b"
> zadd sset 4 d 5 e 6 f 8 h
(integer) 4
> zrange sset 0 -1
1) "a"
2) "b"
3) "d"
4) "e"
5) "f"
6) "h"
> zrank sset d ★値がdの要素の順位をスコアの低い順に取得
(integer) 2 ★低い順に3番目
> zrevrank sset d ★値がdの要素の順位をスコアの高い順に取得
(integer) 3 ★高い順に4番目
>

Hash (ハッシュ型)

ハッシュ型は文字列型のフィールドと値のセットの集合です。

> hset Maru position cf ★フィールドと値を書き込み
(integer) 1
> hmset Maru order 3 team carp ★フィールドと値のセットを複数書き込み
(integer) 1
> hget Maru order ★keyとフィールドを指定し値を取得
"3"
> hmget Maru team position ★keyとフィールドを指定し値を複数取得
1) "carp"
2) "cf"
> hkeys Maru ★keyに対応するフィールドを取得
1) "position"
2) "order"
3) "team"
> hvals Maru ★keyに対応する値を取得
1) "cf"
2) "3"
3) "carp"

アトミックな処理

多くのKVSは複数の処理をトランザクションとして実行することができず、原子性を保証することができません。
複数のプロセスから同時に同じkeyに対して変更が行われると不整合が生じることがあります。
しかし、RedisではMULTI、EXEC、DISCARDといったコマンドを使用することでトランザクション処理を行うことができます。
MULTIコマンドを実行するとトランザクションが開始されEXECコマンドが実行されるとトランザクション内の処理が順に実行されます。

> MULTI
OK
> set name Yamada
QUEUED
> set email taro@hogehogehoge
QUEUED
> EXEC
1) OK
2) OK
> mget name email
1) "Yamada"
2) "taro@hogehogehoge"

EXECコマンドではなくDISCARDコマンドが実行されるとトランザクション内の処理は実行されず全てキャンセルされます。

> MULTI
OK
> set firstname Taro
QUEUED
> set lastname Sato
QUEUED
> DISCARD
OK
> get firstname
(nil)






というわけで、RedisというKVSの主な特徴について説明させていただきました。
Redisは今回紹介させていただいたように配列形式のデータを扱える、アトミックな処理が可能という特徴がありますので、
PV等のカウンター、ランキング生成、タイムラインを表示するようなWebアプリといったところで活用されています。

KVSと一言にいっても様々な特徴がありますので個々の強みと弱みを把握して使い分けられることを目指しましょう。

Standby Expressに関するお問合わせ

  • TEL 042-333-6217
  • FAX 042-352-6101
  • LINE
  • Mail