はじめに
こんにちは、荒堀です。
ElastiCacheの公式のハンズオンがあります。今回はこれをAmazon ElastiCache Serverlessでやってみます。
このハンズオンは、RDSのデータをキャッシュするというシナリオになっています。 しかし少し試したいだけでRDSを作るのは大仰なので、今回はCloud9の中にSQLiteでデータベースを作ってそれを使います。
概要
- 利用するサービスは以下です
- Amazon ElastiCache Serverless
- AWS Cloud9
- この中にSQLiteでデータベースを作ります
- VPCは、デフォルトVPCを使います
- ElastiCacheにデフォルトのセキュリティグループを宛がうので、インバウンドルールを追加します
参考
やってみた
環境作成
以前の記事と同じ環境を作ります。
- Cloud9の起動
- ElastiCache Serverlessを作成
- セキュリティグループにインバウンドルールを追加
Cloud9にデータベース作成
ハンズオンでRDSに作成しているデータベースを、Cloud9上のSQLiteで作成します。
ディレクトリを作成し、seed.sql
で空のSQLファイルを作成します。
mkdir demo-elasticacheserverless && cd demo-elasticacheserverless touch seed.sql
seed.sql
に、テーブルを作成・データを登録するSQLを記述します。
CREATE TABLE planet ( id integer primary key autoincrement, name VARCHAR(30) ); INSERT INTO planet (name) VALUES ("Mercury"); INSERT INTO planet (name) VALUES ("Venus"); INSERT INTO planet (name) VALUES ("Earth"); INSERT INTO planet (name) VALUES ("Mars"); INSERT INTO planet (name) VALUES ("Jupiter"); INSERT INTO planet (name) VALUES ("Saturn"); INSERT INTO planet (name) VALUES ("Uranus"); INSERT INTO planet (name) VALUES ("Neptune");
SQLiteを実行し、SQLファイルを実行します。
sqlite3 tutorial.sqlite sqlite> .read seed.sql sqlite> SELECT * FROM planet;
Python実行
以下のサンプルコードを参考にしました。
redisをインストールして、Pythonを実行します。
pip install redis python
まずは必要なパッケージをインポートします。
import json import redis import sqlite3
データベースクラスを作ります。dict_factory
は、SQLiteの戻り値を辞書型にする関数です。指定しないとtuple型になり、Redisの.hmset
で扱えなくなります。
# 戻り値を辞書型にする関数 def dict_factory(cursor, row): d = {} for idx,col in enumerate(cursor.description): d[col[0]] = row[idx] return d # SQLiteを扱うクラス class DB: def __init__(self, dbname): self.sqlite = sqlite3.connect(dbname) self.sqlite.row_factory = dict_factory def query(self, sql): cursor = self.sqlite.cursor() try: cursor.execute(sql) return cursor.fetchall() finally: cursor.close() def record(self, sql, values): cursor = self.sqlite.cursor() try: cursor.execute(sql, values) return cursor.fetchone() finally: cursor.close()
次に、SQLiteとElasticacheに接続します。
# Time to live for cached data TTL = 10 # Initialize the database Database = DB('tutorial.sqlite') # Initialize the cache Cache = redis.RedisCluster( host='xxx.cache.amazonaws.com'(ElastiCacheのエンドポイント) , ssl=True , decode_responses=True )
redis.RedisCluster
にdecode_responses=True
は、.hgetall
の戻り値をバイト型にしないため指定します。
fetch関数を定義して試してみます。
def fetch(sql): """Retrieve records from the cache, or else from the database.""" res = Cache.get(sql) if res: print("キャッシュあり") return json.loads(res) print("キャッシュなし") res = Database.query(sql) Cache.setex(sql, TTL, json.dumps(res)) return res
何回か実行してみます。
>>> print(fetch("SELECT * FROM planet")) キャッシュなし [{'id': 1, 'name': 'Mercury'}, {'id': 2, 'name': 'Venus'}, {'id': 3, 'name': 'Earth'}, {'id': 4, 'name': 'Mars'}, {'id': 5, 'name': 'Jupiter'}, {'id': 6, 'name': 'Saturn'}, {'id': 7, 'name': 'Uranus'}, {'id': 8, 'name': 'Neptune'}] >>> print(fetch("SELECT * FROM planet")) キャッシュあり [{'id': 1, 'name': 'Mercury'}, {'id': 2, 'name': 'Venus'}, {'id': 3, 'name': 'Earth'}, {'id': 4, 'name': 'Mars'}, {'id': 5, 'name': 'Jupiter'}, {'id': 6, 'name': 'Saturn'}, {'id': 7, 'name': 'Uranus'}, {'id': 8, 'name': 'Neptune'}] >>> print(fetch("SELECT * FROM planet")) キャッシュあり [{'id': 1, 'name': 'Mercury'}, {'id': 2, 'name': 'Venus'}, {'id': 3, 'name': 'Earth'}, {'id': 4, 'name': 'Mars'}, {'id': 5, 'name': 'Jupiter'}, {'id': 6, 'name': 'Saturn'}, {'id': 7, 'name': 'Uranus'}, {'id': 8, 'name': 'Neptune'}]
次はplanet関数を定義します。
def planet(id): """Retrieve a record from the cache, or else from the database.""" key = f"planet:{id}" res = Cache.hgetall(key) if res: print("キャッシュあり") return res print("キャッシュなし") sql = "SELECT `id`, `name` FROM `planet` WHERE `id`=?" res = Database.record(sql, (id,)) if res: Cache.hmset(key, res) Cache.expire(key, TTL) return res
何回か実行してみます。idが文字列型になってしまっているのは残念ですが、キャッシュに入っていることが確認できます。
>>> print(planet(3)) キャッシュなし {'id': 3, 'name': 'Earth'} >>> print(planet(3)) キャッシュあり {'name': 'Earth', 'id': '3'} >>> print(planet(3)) キャッシュあり {'name': 'Earth', 'id': '3'}
おわりに
実装されたAmazon ElastiCache Serverlessを、ハンズオンで使ってみました。 サーバレスでも元のElastiCacheでも、使用感は変わらないと感じました。すぐに起動する分、サーバレスの方がいいかもしれません。
この記事がどなたかのお役に立てれば幸いです。