【初心者向け】Amazon EC2でRedisを使ってみる

わたしはPythonで書かれたWebフレームワークのFlaskを使い、Webアプリを作成しています。ログイン機能を実装したところ、ログイン状態を維持できない問題にぶちあたりました。

 

その解決策として、ログインのセッションデータを外部ストアに保存する必要がありました。

 

外部ストアに保存する方法の選択肢として、Redis、Memcached、データベースが考えられます。AWSの学習をする際に"Redis"がちょくちょく出てきていて興味があったので、"Redisで試してみよう"と思い立ったのです。

 

今回は「Amazon EC2を利用してRedisの簡単な使い方」と、「Flaskで作成したアプリのログインセッションデータをRedisに保存する方法」を紹介します。

 

 

Redisを使ってみよう

■Redisとは

redisアイコン

Redis(Remote Dictionary Server)は、高速なインメモリデータストアです。

 

通常はキーと値として保存・使用されますが、リスト、セット、ハッシュ、ソート済みセット、ビットマップなど、さまざまなデータ型をサポートしています。一般的には、キャッシュ、セッションストア、パブ/サブメッセージング、リアルタイムのアナリティクスなど、多くの用途で利用されます。

 

 

Redisのメリット

  • 高速: Redisはインメモリデータストアであるため、非常に高速な読み書きが可能です。
  • 複数のデータ型: キー-値ペアだけでなく、リスト、セット、ソート済みセット、ハッシュなど、多くの複雑なデータ型をサポートしています。
  • 持続性: 必要に応じて、メモリ上のデータをディスクに保存する設定も可能です。
  • 広範な言語サポート: 多くのプログラミング言語で利用できるクライアントライブラリがあります。

 

 

Redisのデメリット

  • メモリ使用量: すべてのデータは主にメモリに格納されるため、大量のデータを扱う場合はコストがかかる可能性があります。
  • 持続性の制限: 完全なACIDトランザクションをサポートしていないため、RDBMSに比べて持続性が低い場合があります。
  • クラスタリングの複雑さ: Redisのクラスタリングは比較的新しく、設定が複雑である可能性があります。
  • 単一スレッドモデル: Redisは単一スレッドで動作するので、多核プロセッサの能力をフルに活用することはできません。

 

AWSのページにRedisについて詳しく載っています。詳しく知りたい方はぜひ。

 

 

■前提条件

今回の記事ではRedisについて知るために、ハンズオンを3つ用意しました。ハンズオンの前提条件は以下の通りです。

 

  • 環境: AWS
  • 使用AWSリソース: Amazon EC2, Amazon VPC
  • セキュリティグループルール: ローカル環境からアクセスするため、自身のIPを許可(MyIP)
  • OS: AmazonLinux2023
  • 接続: 任意。Session Managerを利用する場合、適切なIAMポリシーを付与してください。
  • ユーザー: ec2-user
  • パブリックv4: あり

 

 

※ハンズオンではPythonやhtmlのソースコードが出てきますが、あくまでRedisの紹介ですのでコード説明は省きます。

 

 

■ハンズオン1:Redisを使ってみる

ハンズオン1では、Amazon EC2にRedisをインストールして、[redis-cli]を使い、キーと値を保存・参照してみます。

 

 

↓EC2インスタンスに接続し、以下のコマンドを実行します。
sudo dnf install -y redis6

 

redis-handson1

redis-handson1

 

インストールが完了したら、起動します。以下のコマンドを順に実行してください。
sudo systemctl start redis6
sudo systemctl enable redis6
systemctl status redis6

 
【実行結果】

[ec2-user@ip-10-0-1-41 ~]$ systemctl status redis6
● redis6.service - Redis persistent key-value database
     Loaded: loaded (/usr/lib/systemd/system/redis6.service; enabled; preset: disable>
    Drop-In: /etc/systemd/system/redis6.service.d
             └─limit.conf
     Active: active (running) since Sun 2023-09-10 00:40:50 UTC; 55s ago
   Main PID: 25082 (redis6-server)     Status: "Ready to accept connections"
      Tasks: 5 (limit: 9349)
     Memory: 2.1M
        CPU: 36ms
     CGroup: /system.slice/redis6.service
             └─25082 "/usr/bin/redis6-server 127.0.0.1:6379"

Sep 10 00:40:50 ip-10-0-1-41.ap-southeast-1.compute.internal systemd[1]: Starting red>
Sep 10 00:40:50 ip-10-0-1-41.ap-southeast-1.compute.internal systemd[1]: Started redi>lines 1-15/15 (END)

 

[actiove(running)]になっていたら、起動しています。

 

↓それではRedisを使ってみましょう。Redisサーバを操作する方法はいくつかありますが、まずは"redis6-cli"ツールを使ってみます。以下のコマンドを実行してください。
redis6-cli

 

redis-handson1

 

↓キーと値を保存します。
SET mykey "Hello, Redis!"

 

redis-handson1

 

↓保存した値を取り出します。
GET mykey

 

redis-handson1

 

キーと値の保存・参照の仕方はシンプルでわかりやすいですね。

 

ハンズオン1は以上です。

 

 

■ハンズオン2:PythonでRedisを使ってみる

ハンズオン2はPythonでRedisを操作するコードを使って、Redisにキーと値を保存し、指定したキーの値を表示してみます。

 

 

↓"Python"をインストールします。環境によってはすでにインストール済みかもしれません。
sudo dnf install -y python3-pip python3-devel

 

redis-handson2

 

↓PythonでRedisを扱うためのパッケージをインストールします。
pip install redis

 

redis-handson2

redis-handson2

 

↓インストールが完了したら、Pythonファイルを保存するディレクトリを作成します。
mkdir test_redis/

 

redis-handson2

 

↓ディレクトリを作成したら、実行ファイルを作成します。コマンドとソースコードは以下を利用してください。
sudo vim test_redis/test_redis.py

 
【ソースコード(test_redis.py)】

import redis

# Redisに接続
r = redis.Redis(host='localhost', port=6379, db=0)

# データのセット
r.set('my_key', 'Hello from Python!')

# データの取得
value = r.get('my_key')
print(value.decode('utf-8'))

 

redis-handson2

redis-handson2

 

↓ソースコードを入力したら、[Esc]キーを押し、以下のコマンドで保存してエディターを終了します。
:wq

 

redis-handson2

 

↓ディレクトリを移動し、pyファイルを実行しましょう。
cd test_redis/
python3 test_redis.py

 

redis-handson2

 

キー"my_key"を指定して、値"Hello from Python!"が返ってきました。

 

ハンズオン2は以上です。

 

■ハンズオン3:Redis×Flaskを使ってみる

さいごに、WebフレームワークのFlaskを利用して、redisにセッションデータを保存してみます。Flaskについてはこちら

 

ハンズオン2の続きから始めますので、カレントディレクトリに注意してください。

 

 

↓必要なパッケージをインストールします。
pip install Flask Flask-Session

 

redisハンズオン3

 

↓htmlファイルを置くディレクトリを作成し、htmlファイルも作成していきます。
mkdir templates/
sudo vim templates/login.html

 

【ソースコード(login.html)】

<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
{% with messages = get_flashed_messages() %}
  {% if messages %}
    {% for message in messages %}
      <p>{{ message }}</p>
    {% endfor %}
  {% endif %}
{% endwith %}
    <h1>Login</h1>
    <form method="POST" action="/login">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required><br><br>

        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required><br><br>

        <input type="submit" value="Login">
    </form>
</body>
</html>

 

 

redisハンズオン3

redisハンズオン3

 

[Esc]キーを押し、以下のコマンドで保存してエディターを終了します。
:wq

 

↓Flaskを実行するファイルを作成し、以下のソースコードを貼り付けましょう。
sudo vim app.py

 

【ソースコード(app.py)】

from flask import Flask, request, render_template, redirect, session, url_for
from redis import Redis
from flask_session import Session

app = Flask(__name__)
app.secret_key = 'your_secret_key'
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_PERMANENT'] = False
app.config['SESSION_USE_SIGNER'] = True
app.config['SESSION_KEY_PREFIX'] = 'your_prefix'
app.config['SESSION_REDIS'] = Redis(host='localhost', port=6379, db=0)

# セッションのセットアップ
Session(app)

# ダミーのユーザーデータ
users = {
    'user1': 'password1',
    'user2': 'password2'
}

# ログインページ
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        if users.get(username) == password:
            session['username'] = username
            return redirect(url_for('dashboard'))
        else:
            return 'ログインに失敗しました'

    return render_template('login.html')

# ダッシュボード(ログインが必要なページ)
@app.route('/dashboard')
def dashboard():
    if 'username' in session:
        username = session['username']
        return f'こんにちは、{username}さん! <a href="/about">ログイン継続チェック</a> <a href="/logout">ログアウト</a>'
    else:
        return 'ログインしてください。'

# /about ページ(ログインが必要)
@app.route('/about')
def about():
    if 'username' not in session:
        return f'ログインが必要です。 <a href="/login">ログイン</a>'
    username = session['username']  # 'username'をセッションから取得
    print('username:', username)
    return f'{username}さん!、ログイン継続中です! <a href="/logout">ログアウト</a>'

# ログアウト
@app.route('/logout')
def logout():
    if 'username' in session:
        session.pop('username')
    return redirect(url_for('login'))

if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0')

 

redisハンズオン3

redisハンズオン3

 

 

[Esc]キーを押し、以下のコマンドで保存してエディターを終了します。
:wq

 

↓準備が整いましたので、Webアプリを起動しましょう。WARNINGが表示されますが、問題ないので進めてください。
python3 app.py

 

redisハンズオン3

 

↓ブラウザからWebアプリにアクセスします。アクセスできない場合は、セキュリティグループのインバウンドルールとパブリックIPアドレスを確認してください。
http://<EC2インスタンスパブリックIPアドレス>:5000/login

 

redisハンズオン3

 

↓ダミーのユーザーデータを用意していますので、Usename: user1、Password: password1 でログインしてみてください。

 

redisハンズオン3

 

ログインできましたでしょうか。
 

redisハンズオン3

 

↓今回はログインしたユーザーのセッションデータをRedisに保存するのが目的です。ログインしていなければアクセスできないページを用意してありますので、確認してみましょう。[ログイン接続チェック]をクリックしてください。

 

redisハンズオン3

redisハンズオン3

 

Usernameが表示され、ログイン継続中と出ました。

 

↓しかし、本当にRedisにセッションデータが保存されているのか気になりますよね。確認してみましょう。コマンドラインに戻り、[Ctrl + c]でWebアプリを一旦止めます

 

redisハンズオン3

 

↓[redis6-cli]を実行し、以下のコマンドを実行します。
keys *

 

redisハンズオン3

 

↓いくつかデータが保存されていますが、今回のFlaskアプリのキー名は[your_prefix]から始まるデータです。

 

redisハンズオン3

 

↓値を確認してみます
GET <キー名>
例)GET your_prefixc8b8431a-d59f-4235-bf2c-75ed3ab77d93

 

redisハンズオン3

 

値の中にusernameとuser1が入っているのが確認できました。

 

↓もう一度、Webアプリを起動し、以下のページにアクセスしてください。セッションデータが保持されているので、アクセスできるかと思います。
http://<EC2インスタンスパブリックIPアドレス>:5000/about

 

redisハンズオン3

 

↓[ログアウト]をクリックしてください。

 

redisハンズオン3

↓それでは、もう一度redisのデータを確認してみます。[redis6-cli]→[keys *]を実行します。

 

redisハンズオン3

 

さきほどまであった、[your_prefixxxxxxxxxxxxxxxxxx]というキーが消えていますね。ログアウトしたことで、セッションデータが消えました。

 

今回のハンズオンは以上です。

 

 

まとめ:【初心者向け】Amazon EC2でRedisを使ってみる

Webアプリケーションを作成していて、各実行プロセスがユーザーのログイン情報を保持できずに困っていました。

 

解決策は外部ストアを利用することで、外部ストアの選択肢のひとつに今回紹介したRedisがあったのです。AWSの認定資格で"Amazon ElastiCache for Redis"ってしょうちゅう出てきますよね。

 

今回のハンズオンを通して、"Redis"の動きや操作がなんとなくわかった気がします。

 

 

参考リンク:RedisFlask – クイックスタート
 

 

↓ほかの協栄情報メンバーもPythonに関する記事を公開しています。ぜひ参考にしてみてください。

 

■【簡単】Pythonで始めるwebアプリ開発入門【Flask】(齊藤弘樹)
https://cloud5.jp/saitou-intro-flask/

 

■天気予報情報をスクレイピング(Python)で、LINE NotifyによりLINE通知の構築(INAMURA)
https://cloud5.jp/web-scraping_line-notify/

 

■Pythonでlxmlを用いてhtmlから情報取得(zhangzy)
https://cloud5.jp/python-ixml/

 

■仮想環境作成ツール”virtualenv”を使ってみる(齊藤弘樹)
https://cloud5.jp/saitou-howtouse-virtualenv/

 

■【初学者向け】PCにPythonを学習するための環境を整える part1【Windows編】(齊藤弘樹)
https://cloud5.jp/saitou-python-install/
 

Last modified: 2023-09-10

Author