まえがき
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