simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

AWS:お金のかからないElastiCache活用術1

まえがき

CubeWalk ゲームは…キューブを置く処理に不正がないようサーバーで実行されます。
世界の情報はたった一つのサーバーであるため、負荷分散を考えて DB は同時アクセスに耐えられる DynamoDB などを考えてみましたが
世界データを格納するだけで 600 万円ほど費用がかかることがわかったので、DynamoDB は使わないことにします。

代わりにパフォーマンス面で注目していたのが ElastiCache の Redis です。
ユーザーが100人一斉に同じ場所にブロックを置こうとしたときに同時書き込みが発生したところで
たった一人のブロックだけが置かれることを保証する(原子的なのでアトミックな処理と呼ばれる)ためインメモリデータベースである Redis の原子性を活用することにします。

同時アクセスに耐えられるか?
知りません。10000 人から一斉アクセスで動かなかったらそれまでということで諦めます。
その不具合に見舞われる時、きっと私は億万長者ですので、笑いながら DynamoDB に移行します(夢物語)

Redis をオンラインに置いて活用するなら AWS の ElastiCache の Redis モードを使うのが簡単ですが、データを一括で更新したり
取得したりする通信量や処理時間は避けなければなりません。

そこで、バックアップで得られる rdb ファイルをダウンロードして解析できること
ローカルで編集した内容を一括でインポートできることなどを確かめて、これの手段を記録します。

ローカル環境で redis を触れるようにする

とにもかくにも docker コンテナで redis 環境を構築して ElastiCache と同じサーバーをローカルに立てます。
すべてはそこからです。

手順としては Docker for Windows を起動して redis:5.0.5 を pull します。
images で確認したときに、redis があれば OK

$ docker images
REPOSITORY                              TAG                 IMAGE ID            CREATED             SIZE
redis                                   5.0.5               63130206b0fa        9 days ago          98.2MB

docker-compose.yml テキストファイルを作ったら次のように記述し

version: '3'
services:
  redis:
    container_name: redis
    image: redis:5.0.5
    volumes:
      - ./redis:/redis
    ports:
      - "6379:6379"

同フォルダに up.sh ファイルを配置して次の通り実装

#!/bin/sh
cd `dirname $0`
docker-compose -f docker-compose.yml up -d

Git Bash プロンプトで sh ./up.sh なんて叩けば

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
1faa380aff8b        redis:5.0.5         "docker-entrypoint.s…"   18 minutes ago      Up 18 minutes       0.0.0.0:6379->6379/tcp     redis

docker redis ローカル環境のできあがり

後ほど volume マウントした redis フォルダを活用します。

ローカルから redis サーバーにアクセス

python 実行環境を Windows なら Anaconda Navigator 経由で用意します。
Anaconda プロンプトを開いて python 3 系が実行できる環境で redis-rdb-tools を用意します。

pip install rdbtools python-lzf

基本的な使い方はこちらを参照のこと
githubja.com

一応次の python の redis client を使った localhost 接続テストには合格

from __future__ import print_function
import redis
import uuid

#elasticache settings
r = redis.StrictRedis(host='localhost', port="6379", db=0)

def handler(event, context):
    """
    This function puts into memcache and get from it.
    Memcache is hosted using elasticache
    """

    #Create a random UUID... this will be the sample element we add to the cache.
    uuid_inserted = uuid.uuid4().hex
    #Put the UUID to the cache.
    r.set('uuid', uuid_inserted)
    #Get item (UUID) from the cache.
    uuid_obtained = r.get('uuid')
    if uuid_obtained.decode("utf-8") == uuid_inserted:
        # this print should go to the CloudWatch Logs and Lambda console.
        print ("Success: Fetched value %s from memcache" %(uuid_inserted))
    else:
        raise Exception("Value is not the same as we put :(. Expected %s got %s" %(uuid_inserted, uuid_obtained))

    return "Fetched value from memcache: " 

handler(None, None)

pythonデバッグの仕方が具体的じゃなかったので、整理して記録しました。
simplestar-tech.hatenablog.com