メモ > サーバ > サービス: AWS > ElastiCache (Redis)
■ElastiCache (Redis)
ElastiCacheでRedisを使用する
ElastiCache + Redis に出てくる概念と、クラスタモードごとの違い - nyamadoriの日記
https://nyamadori.hatenablog.com/entry/2017/09/12/103523
redis-cliについては以下を参照
redis-cliの使い方 - Qiita
https://qiita.com/sawada_masahiko/items/1f60936c421ecab8dfbf
Redis に保存されてる値を見ようと思った時に覚えておきたい redis コマンド | そんなこと覚えてない
https://blog.eiel.info/blog/2014/08/26/remember-redis/
RedisのKeyを全て削除する - Qiita
https://qiita.com/reoring/items/b92cac4c83c88a725faa
PHPのセッションをRedisで扱う方法は以下を参照
AWSでPHP7+ElastiCache(Redis)を利用したセッション保持 | Skyarch Broadcasting
https://www.skyarch.net/blog/?p=11966
【AWS入門】ElastiCache を起動してみる | SONICMOOV LAB
https://lab.sonicmoov.com/development/aws/elasticache/
【Elasticache】ELB配下の複数インスタンス間でのセッション管理【Laravel例】 - 備忘録の裏のチラシ
https://norikone.hatenablog.com/entry/2016/02/08/%E3%80%90Elasticache%E3%80%91ELB%E9%85%8D%E4%B8%8B%...
AWS EC2にredisをインストールする - Qiita
https://qiita.com/stoshiya/items/b8c1d2eb41770f92ffcf
PHPのセッションをRedisクラスターモードで扱う方法は以下を参照
PHPのSESSION管理はRedisではなくRedis Clusterを使いたいという方にだけこっそり教えます - Qiita
https://qiita.com/hayakawatomoaki/items/f667359d028232475d4e
PHP Sessions with Redis Cluster (using AWS Elasticache) - Brandon Checketts
https://www.brandonchecketts.com/archives/php-sessions-with-redis-cluster-using-aws-elasticache
以下、PHPのセッション置き場として使うために検証した内容
■準備: EC2を起動
以下の内容でEC2インスタンスを起動
名前: cache_test
Amazonマシンイメージ: Amazon Linux 2 AMI
インスタンスタイプ: t2.micro
キーペア名: AWS
Network: Develop
サブネット: Develop-DMZ-A
パブリックIPの自動割り当て: 有効化
ファイアウォール: default, ssh, web
ストレージ: 20GiB / 汎用SSD(GP2)
■準備: EC2を設定
$ sudo su -
# localedef -f UTF-8 -i ja_JP ja_JP
# localectl set-locale LANG=ja_JP.UTF-8
# localectl status
# timedatectl set-timezone Asia/Tokyo
# timedatectl status
$ sudo su -
# date
# yum install httpd -y
# systemctl start httpd
# systemctl enable httpd
# usermod -a -G apache ec2-user
# echo 'cache_test' > /var/www/html/index.html
以下にアクセスして確認
http://203.0.113.1/
■準備: PHPをインストール
# amazon-linux-extras install php7.4 -y
# yum install php php-mbstring -y
# php -v
# systemctl restart httpd
# echo '<?php phpinfo() ?>' > /var/www/html/phpinfo.php
以下にアクセスして確認
http://203.0.113.1/phpinfo.php
■準備: PHPセッションを動作確認
# vi /var/www/html/session.php
以下にアクセスして確認
http://203.0.113.1/session.php
セッションは以下に保存されている
<?php
session_start();
if (isset($_SESSION["count"])) {
$_SESSION["count"]++;
} else {
$_SESSION["count"] = 1;
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>セッション</title>
</head>
<body>
<h1>セッション</h1>
<p><?php
echo $_SESSION["count"] . "回目のアクセスです。";
?></p>
</body>
</html>
# ll /var/lib/php/session
合計 4
-rw------- 1 apache apache 10 7月 25 20:04 sess_39iatvd1po1bpbsfl9c0agnijp
# cat /var/lib/php/session/sess_39iatvd1po1bpbsfl9c0agnijp
count|i:5;
■準備: ElastiCache用のサブネットグループを作成
AWS → ElastiCache → サブネットグループ → サブネットグループを作成
名前: develop
説明: for develop.
VPC ID: develop
AWS → ElastiCache → パラメータグループ → パラメータグループを作成
RDSパラメータグループのように、常に変更されるものでは無いか
それなら「必要に応じて作成する」でいいか
■Redis(クラスターモード無効の場合)検証: ElastiCacheを起動
AWS → ElastiCache → Redisクラスター → Redisクラスターを作成
クラスターの作成方法を選択: 新しいクラスターを設定および作成
クラスターモード: 無効
名前: develop
ロケーション: AWSクラウド
マルチAZ: 無効(本番環境なら有効にすべきだと思われる)
エンジンバージョン: 6.2
ポート: 6379
パラメータグループ: default.redis6.x(必要に応じて変更する)
ノードのタイプ: cache.t2.micro
レプリケーション数: 2
サブネットグループ: develop
アベイラビリティーゾーンの配置: 指定がありません
「次へ」をクリック
詳細設定はいったん変更せずに、そのまま「次へ」をクリック
確認画面が表示されるので、そのまま「作成」をクリック
作成されるまで5分ほど待つ
作成されたら、詳細画面からプライマリエンドポイント(接続先)を確認しておく
# amazon-linux-extras install redis6 -y
# systemctl start redis
# systemctl enable redis
# redis-cli -h develop.vjtrrr.ng.0001.apne1.cache.amazonaws.com
> quit
■Redis(クラスターモード無効の場合)検証: PHPセッションをElastiCacheに保存
# yum install php-pecl-redis -y
# vi /etc/php.ini
変わらない場合、以下などのファイルで値が上書きされていないか確認する
;session.save_handler = files
;session.save_path = "/tmp"
↓
session.save_handler = redis
session.save_path = "tcp://develop.vjtrrr.ng.0001.apne1.cache.amazonaws.com:6379"
# systemctl restart httpd
# vi /etc/httpd/conf.d/php.conf
# vi /etc/php-fpm.d/www.conf
以下にアクセスして確認
http://203.0.113.1/session.php
セッションがRedisに保存されていることを確認する
# redis-cli -h develop.vjtrrr.ng.0001.apne1.cache.amazonaws.com
> keys "PHP*"
1) "PHPREDIS_SESSION:39iatvd1po1bpbsfl9c0agnijp"
> get PHPREDIS_SESSION:39iatvd1po1bpbsfl9c0agnijp
"count|i:5;"
■Redis(クラスターモード有効の場合)検証: ElastiCacheを起動
AWS → ElastiCache → Redisクラスター → Redisクラスターを作成
クラスターの作成方法を選択: 新しいクラスターを設定および作成
クラスターモード: 有効
名前: develop
ロケーション: AWSクラウド
マルチAZ: 有効化
エンジンバージョン: 6.2
ポート: 6379
パラメータグループ: default.redis6.x.cluster.on(デフォルトで「cluster.on」が選択されていた)
ノードのタイプ: cache.t2.micro
レプリケーション数: (設定項目が無かった)
シャード数: 3(デフォルト値のまま / 1〜500で指定できる)
シャードあたりのレプリカ: 2(デフォルト値のまま / 0〜5で指定できる)
サブネットグループ: develop
アベイラビリティーゾーンの配置: 均等分散
「次へ」をクリック
詳細設定はいったん変更せずに、そのまま「次へ」をクリック
確認画面が表示されるので、そのまま「作成」をクリック
作成されるまで10分ほど待つ
作成されたら、詳細画面から設定エンドポイント(接続先)を確認しておく
(クラスターモードを有効にした場合、「プライマリエンドポイント」ではなく「設定エンドポイント」を使う)
# amazon-linux-extras install redis6 -y
# systemctl start redis
# systemctl enable redis
# redis-cli -h develop.vjtrrr.clustercfg.apne1.cache.amazonaws.com
> quit
■Redis(クラスターモード有効の場合)検証: PHPセッションをElastiCacheに保存
# yum install php-pecl-redis -y
# vi /etc/php.ini
変わらない場合、以下などのファイルで値が上書きされていないか確認する
;session.save_handler = files
;session.save_path = "/tmp"
↓
session.save_handler = rediscluster
session.save_path = "seed[]=develop.vjtrrr.clustercfg.apne1.cache.amazonaws.com:6379"
# systemctl restart httpd
# vi /etc/httpd/conf.d/php.conf
# vi /etc/php-fpm.d/www.conf
以下にアクセスして確認
http://203.0.113.1/session.php
セッションがRedisに保存されていることを確認する
設定エンドポイントに接続しても、何も記録されていない
# redis-cli -h develop.vjtrrr.clustercfg.apne1.cache.amazonaws.com
> keys "*"
(empty array)
各シャード内にある各ノードを一つずつ調べていくと、0002にだけ記録されていた
(0001〜0003のいずれかに記録されているはず)
# redis-cli -h develop-0001-001.vjtrrr.0001.apne1.cache.amazonaws.com
# redis-cli -h develop-0001-002.vjtrrr.0001.apne1.cache.amazonaws.com
# redis-cli -h develop-0001-003.vjtrrr.0001.apne1.cache.amazonaws.com
> keys "*"
(empty array)
# redis-cli -h develop-0002-001.vjtrrr.0001.apne1.cache.amazonaws.com
# redis-cli -h develop-0002-002.vjtrrr.0001.apne1.cache.amazonaws.com
# redis-cli -h develop-0002-003.vjtrrr.0001.apne1.cache.amazonaws.com
> keys "*"
1) "PHPREDIS_CLUSTER_SESSION:2f0867jmhpd912v5tohlvlj7os"
develop-0002-001.vjtrrr.0001.apne1.cache.amazonaws.com:6379> get PHPREDIS_CLUSTER_SESSION:2f0867jmhpd912v5tohlvlj7os
"count|i:5;"
# redis-cli -h develop-0003-001.vjtrrr.0001.apne1.cache.amazonaws.com
# redis-cli -h develop-0003-002.vjtrrr.0001.apne1.cache.amazonaws.com
# redis-cli -h develop-0003-003.vjtrrr.0001.apne1.cache.amazonaws.com
> keys "*"
(empty array)
シャーディングされたデータなので、
・現状、自身のアクセスは常に0002に対して読み書きされる
・他ユーザのアクセスは0001や0003で読み書きされる可能性がある
となっている
■Redis検証: AmazonLinux1に php-pecl-redis をインストール
AmazonLinux1の場合、yumではインストールできなかった
# yum install php-pecl-redis
1007 packages excluded due to repository priority protections
パッケージ php-pecl-redis は利用できません。
エラー: 何もしません
# yum install php-pecl-redis --enablerepo=epel
1007 packages excluded due to repository priority protections
パッケージ php-pecl-redis は利用できません。
エラー: 何もしません
以下にある手順でインストールできた
かなり前の記事なので、「今はCentOS6系には提供されていない」などではなく、当時からyumではインストールできなかったのだと思われる
Amazon LinuxにPHP + memcached + Redisをインストール - WonderPlanet Developers’ Blog
https://developers.wonderpla.net/entry/2013/10/01/190555
# cd
# git clone https://GitHub.com/nicolasff/phpredis.git
# cd ./phpredis
# phpize
# ./configure && make && make install
# vi /etc/php.d/redis.ini
これでPHPからRedisを利用できるようになった
なお、最初は以下のエラーになった
; Enable redis extension module
extension=redis.so
# service httpd reload
# yum install php-pecl-redis --enablerepo=epel
It was impossible to connect to the Red Hat servers.
This could mean a connectivity issue in your environment, such as the requirement to configure a proxy,
or a transparent proxy that tampers with TLS security, or an incorrect system clock.
Please collect information about the specific failure that occurs in your environment,
using the instructions in: https://access.redhat.com/solutions/1527033 and open a ticket with Red Hat Support.
yumのレポジトリが httpsかつ証明書が不正な場合の無理やり許可する。 - Qiita
https://qiita.com/iitenkida7/items/cbf0ce48632c84db3c80
上記の記事を参考に
# vi /etc/yum.repos.d/webtatic-testing.repo
としたが、解消できなかった
さらに
【AWS/EC2/Amazon Linux2】curl: (60) SSL certificate problem: certificate has expired - Qiita
https://qiita.com/wadakatu/items/80919711bb05d0142cd5
上記の記事を参考に
sslverify=0 … 3箇所に追記する
# yum install https://cdn.amazonlinux.com/patch/ca-certificates-update-2021-09-30/ca-certificates-2018.2.22-65.1.2...
としてTLSのエラーは解消できたが、そもそも php-pecl-redis のパッケージは見つからなかった
よって上記のとおり、GitHubからソースコードを入手して手動でインストールした
■オプション
weightなどのオプションを指定する場合、以下が参考になりそう
PHPセッションをPhpRedisに保存する - Qiita
https://qiita.com/zurazurataicho/items/a71437412410955afd44
以下も参考になりそう
Amazon ElastiCache Redis の各パラメータについてまとめてみた | DevelopersIO
https://dev.classmethod.jp/articles/amazon-elasticache-redis-param/
■費用
公式の見積もりツールによると、cache.t2.small をノード数2で追加すると$70ほど上がった
ノート数を3にすると、さらに$40ほど上がった
■Redis とMemcached
基本的にはRedisを使っておけば良さそう
Redis とMemcached | AWS
https://aws.amazon.com/jp/elasticache/redis-vs-memcached/
【AWS入門】Amazon ElastiCacheとは?redisとmemcachedの違いやユースケース、料金について解説 | よくわかるAWS・クラウド
https://cloudnavi.nhn-techorus.com/archives/4270
Amazon ElastiCacheとは?RedisとMemcachedの違いとは | SunnyCloud
https://www.sunnycloud.jp/column/20210428-01/
ElastiCacheはMemcachedとRedisのどっちを選ぶ? | DevelopersIO
https://dev.classmethod.jp/articles/which-choice-redis-memcached/
PHPアプリケーションのセッション管理にAWS ElastiCacheを使う | DevelopersIO
https://dev.classmethod.jp/articles/php-session-elasticache/
AWS運用 ElastiCache Redis で PHP のセッション情報を保存してみよう | AWS運用最適化サービス cloud link (クラウドリンク)
https://aws.taf-jp.com/blog/38956
■スペックの変更
スペックの変更を試した。
「ElastiCache → Redis クラスター」の画面で作業対象を選択し、「アクション → 変更」を実行
今回はノードのタイプ「cache.t2.micro」を「cache.t2.small」に変更してみる
20:00 に変更作業を実行した。ステータスが「Modifying」に変わった
20:18 に変更作業が完了した。ステータスが「Available」に変わった
基本的には20分ほどかかるということで良さそう
「cache.t2.small」を「cache.t2.micro」に戻したときも、同じくらいの時間で完了した
セッション数がリセットされたりは無かった
ときどきアクセスして確認したが、ダウンタイムは見られなかった。ただし数秒のダウンは発生すると思っておく
ダウンタイムについては、以下を総合すると「瞬断は発生します」くらいの案内で良さそう
以下は cache.m5.large を cache.t2.small に変更(スペックダウン)した時のメモ
Cronエラーが来たので、瞬断は発生したと思われる
18:51 変更
18:51 ステータスが「Modifying」になった
19:08 キャッシュに接続できなくなった(画面では確認できていないが、Cronからエラーが来た)
19:09 キャッシュに接続できるようになった
19:10 ステータスが「Available」になった
ElastiCache Redisのサービス更新時のダウンタイムを調査した - karakaram-blog
https://www.karakaram.com/elasticache-service-update-downtime/
「ダウンタイムは数秒と記載あり」
ElastiCacheのスケールアップは本当にダウンタイムなしでできるのか検証してみた! #reinvent | DevelopersIO
https://dev.classmethod.jp/articles/can-elasticache-onlinescalingup-without-downtime/
「ミリ秒単位で観測するとわずかにリクエストに影響があるようです。」基本的にはダウンタイムは無いみたい?
Amazon MemoryDB for Redisのシャード数を変更してみた | DevelopersIO
https://dev.classmethod.jp/articles/amazon-memorydb-for-redis-change-shard/
「キー数やシャード数によりますが、変更に数時間かかることもあるようです。(今回は20分程度かかりました)」
「シャード数」や「シャードあたりのレプリカ」の変更は、別画面で行う。以下を参照
Amazon MemoryDB for Redisのシャード数を変更してみた | DevelopersIO
https://dev.classmethod.jp/articles/amazon-memorydb-for-redis-change-shard/
■オートスケーリング
ElastiCache for Redis クラスターの Auto Scaling - Amazon ElastiCache for Redis
https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/AutoScaling.html
Elasticache for RedisでAutoScalingを利用できるようになりました | DevelopersIO
https://dev.classmethod.jp/articles/autoscaling-elasticache-for-redis/
ElastiCache のスケーリングについてまとめてみた - サーバーワークスエンジニアブログ
https://blog.serverworks.co.jp/elasticache-scaling
ElastiCache for Redisはオートスケーリングに対応しているらしい
それなら
・RDSはオートスケーリング無しで作成する
・ElastiCache for Redisはオートスケーリングありで作成する
・負荷が問題になりそうな部分は、
「RDSからの参照結果をElastiCacheに保存する」「書き込みたい内容を一時的にElastiCacheに保存し、後からRDSに登録する」
のような対応はできそう
ただしキャッシュなので、突発的にデータが消えることは常に考えておく必要はありそう
また、これで大量のアクセスに耐えられるとしても、別途クラウド破産対策は必要
どんなアクセス数にも耐えられるのは、それはそれで問題になる可能性はある
CloudFrontやWAFなどで、一定以上のアクセスが来たら「しばらくお待ちください」画面を出すように制御するくらいか
■要検証
詳細設定に「スローログ」がある。以下などを参考にしたい
「エンジンログ」というのもあるが、Redis自体の動作ログのことか
[アップデート] ElastiCache for RedisのスローログをCloudWatch LogsやKinesis Data Firehoseにパブリッシュできるようになりました! | DevelopersIO
https://dev.classmethod.jp/articles/amazon-elasticache-now-supports-publishing-redis-slow-logs/
アップデートが多いとクラスターモードは無効の方がいい?
セッションはアップデートが非常に多いと言えるので、クラスターモード無しでもいいか
Amazon ElastiCacheってなんだろ?
https://zenn.dev/mn87/articles/6de8deb3b02f26
■トラブル: 「プライマリエンドポイント」が表示されない
クラスターモードを有効にした場合、「プライマリエンドポイント」ではなく「設定エンドポイント」を使って読み書きする
■トラブル: PHPからセッションを扱えない1
/etc/php.ini の設定ではなく、以下などのファイルの設定が優先されていないか確認する
/etc/httpd/conf.d/php.conf
/etc/php-fpm.d/www.conf
■トラブル: PHPからセッションを扱えない2
接続先を間違えると、以下のエラーになる
ブラウザで画面は表示されるが、セッションの値はカウントされない
[Wed Jul 27 21:37:01.543078 2022] [php7:warn] [pid 4251] [client 203.0.113.1:60324] PHP Warning: session_start(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /var/www/html/session.php on line 3
[Wed Jul 27 21:37:01.543144 2022] [php7:warn] [pid 4251] [client 203.0.113.1:60324] PHP Warning: session_start(): Failed to read session data: redis (path: tcp://test.vjtrrr.clustercfg.apne1.cache.amazonaws.com:6379) in /var/www/html/session.php on line 3
■トラブル: クラスターモードでPHPからセッションを扱えない
以下のエラーになる
ブラウザで画面は表示されない(「このページは動作していません」になる)
[Wed Jul 27 21:23:41.752235 2022] [php7:warn] [pid 4037] [client 203.0.113.1:60002] PHP Warning: session_start(): Failed to read session data: redis (path: tcp://test.vjtrrr.clustercfg.apne1.cache.amazonaws.com:6379) in /var/www/html/session.php on line 3
[Wed Jul 27 21:23:41.752294 2022] [php7:error] [pid 4037] [client 203.0.113.1:60002] PHP Fatal error: Uncaught RedisException: MOVED 6734 10.1.2.103:6379 in /var/www/html/session.php:3\nStack trace:\n#0 /var/www/html/session.php(3): session_start()\n#1 {main}\n thrown in /var/www/html/session.php on line 3