lynx   »   [go: up one dir, main page]

ラベル Redis の投稿を表示しています。 すべての投稿を表示
ラベル Redis の投稿を表示しています。 すべての投稿を表示

2013-01-18

Redis でインデックス的なものを使う

お手軽さとパフォーマンスの噂を聞いて Redis を使い始めたわけですが、RDB のようなクエリをしようとすると、当然、利用者側でなんとかする必要があります。たぶん、こうやればいいのかなぁという感じで。

クイズの回答を Redis に保存しようとしています。「各 user は、各 quiz に多くとも1つだけ回答できる。ただし、上書きができる。」という前提です。こんな JSON でデータを保存しましょう。

{"quiz": "1", "user": "alice", "ans": "X", ...}
{"quiz": "2", "user": "alice", "ans": "Y", ...}
{"quiz": "1", "user": "bob", "ans": "X", ...}


必要なクエリは以下のとおり。
  • quiz=1 に回答したユーザを取得する。
  • quiz=1 に、ans=X と回答したユーザを取得する。
  • user=alice の回答を取得する。

データ構造

データ本体を保持するハッシュ
quiz:1:user, alice => {...}

クイズ番号と回答の組み合わせごとのユーザを保持するセット
index:quiz:1:ans:X:users => (alice, bob)

ユーザが回答したクイズ番号を保持するセット
Index:user:alice:quizzes => (1, 2)


まず登録。以下、コードは redis-cli です。

> HSET quiz:1:user alice '{...}'
(integer) 1
> SADD index:quiz:1:answer:X:users alice
(integer) 1
> SADD index:user:alice:quizzes 1
(integer) 1

残りふたつの回答も同様に。

> HSET quiz:2:user alice '{...}'
> SADD index:quiz:2:answer:Y:users alice
> SADD index:user:alice:quizzes 2

> HSET quiz:1:user bob '{...}'
> SADD index:quiz:1:answer:X:users bob
> SADD index:user:bob:quizzes 1

クイズ番号とユーザ名から、任意の回答を取得できます。

> HGET quiz:1:user alice
"{...}"
quiz=1 の回答、回答数、および回答したユーザは、このハッシュから取り出します。
> HGETALL quiz:1:user
1) "alice"
2) "{…}"
3) "bob"
4) "{…}"
> HLEN quiz:1:user
(integer) 2
> HKEYS quiz:1:user
1) "alice"
2) "bob"
quiz=1 かつ ans=X の回答数、回答したユーザ、回答は index:quiz:1:answer:X:users セットから取り出します。
> SCARD index:quiz:1:answer:X:users
(integer) 2
> SMEMBERS index:quiz:1:answer:X:users
1) "alice"
2) "bob"
> HMGET quiz:1:user alice bob  # クイズ番号とユーザ名を使って、ハッシュから取得
1) "{…}"
2) "{…}"
user=alice の回答数、クイズ番号、回答は index:user:alice:quizzes セットから取得します。
> SCARD index:user:alice:quizzes
(integer) 2
> SMEMBERS index:user:alice:quizzes
1) "1"
2) "2"
> HGET quiz:1:user alice
"{…}"
削除するときには、ハッシュと2つのセットを削除します。
> HDEL quiz:1:user alice
(integer) 1
> SREM index:quiz:1:answer:X:users alice
(integer) 1
> SREM index:user:alice:quizzes 1
(integer) 1
と、こんなやりかたで考えています。筋がいいことを願う。

2013-01-06

Redis をさわりはじめました

Python で Redis を触ってみました。オートインクリメントやインデックス用のkeyを使うイディオムがある。

import json
import redis
r = redis.Redis()

def create_user(name, auth):
    uid = r.incr('global:next_uid')  # ユニークなIDを取得
    return put_user(uid, name, auth)

def get_user(uid):
    value = r.get('user:%s' % uid)
    if value:
        return json.loads(value)

def put_user(uid, name, auth):
    user = {'uid': uid, 'name': name, 'auth': auth}
    r.set('user:%s' % uid, json.dumps(user))
    r.set('index:user:auth:%s' % auth, uid)  # auth -> uid を引くため
    return user

def get_user_by_auth(auth):
    uid = r.get('index:user:auth:%s' % auth)
    if not uid:
        return
    return get_user(uid)

a = create_user('wozozo', 'xxxxxxxx')
b = get_user(a['uid'])
assert a == b
put_user(a['uid'], b['name'], 'yyyyyyyy')

c = get_user_by_auth('yyyyyyyy')
Лучший частный хостинг