CTOの椎名アマドです。
今回は、Pairyのチャットデータを全てRedisからAmazon DynamoDBに移行した話をしたいと思います。
我々が 2012年6月に カップル専用アプリ Pairy をリリースした時には、
データベースは MySQL と Redis の両方を利用するところで始めました。
Redis の役割は:
1. MySQLレスポンスのキャッシュ
2. プッシュ通知等のキュー
3. チャットのデータを全保管
サービスローンチ直後はまだ Appサーバー(EC2)1台と、MySQL & Redisを両方走らせてる DBサーバー(EC2)1台で十分だという判断で、しばらくはそんな構成でやってました。(S3などは省略)
しかし、いざサービスが成長してくるともちろん MySQL & Redis を1台でまかなうのはキツくなり、MySQL と Redis を別々のEC2インスタンスに分けました。
プライマリなストレージとしてのRedis
Redisをあるデータのプライマリのストレージとして使用するのはやはり勇気と根気がいるもんです。
ある程度ちゃんとインフラのリソースが整ってれば良いんですが、
人数少ないスタートアップだと気にしなきゃいけない事が多めです。
我々の場合は、サービスが成長し出したぐらいから下記について悩むようになりました。
1. データ容量
Redisはあくまで「メモリが主」のストレージです。
AWSではメモリを多く積んだインスタンスは一緒にCPUスペックも上がるので、高くつきます。
それでもサービスが成長するとすぐ枯渇するので、インスタンスを足さなきゃいけない。
すると結構早い段階から Redis を複数台運用やシャーディングについて考えなきゃいけない。
小規模なスタートアップにとって、そういうところに気を配らなければいけないのは負担になってきます。
根本的にデータ上限がすぐ見えてくる(&永続化なので上限に到達したらまずい)ようなものなので、クラスタリングやハッシュ振り分け機構(Consistent Hashing等)がout-of-the-boxで搭載されてれば嬉しいんですけどね。
Redis Cluster も直近はまだ出そうにないし、期待は出来ない状態です。
2. 永続性の担保
もう一度言いますが、Redisはあくまで「メモリが主」のストレージです。
インスタンスが落ちればデータは消えるし、Redisプロセスが死ぬだけでもデータは消えます。
Redisは永続化戦略として「AOF」と「RDB」の2つを提供してます。
RDBはデータベース全体のスナップショットを一個のファイルにどんと保存する戦略で、
AOFはRedisへの書き込み履歴を常にファイルにログとして追記していく戦略です。
しかし、
- RDBはRedisが落ちたらワーストケースで直前数分のデータ消失(redis.confによるが、一般的なデフォ設定)
- AOFはファイルがすぐ肥大化する、再起動時のデータ復帰時間が長い、AOFファイル自体の破損があり得る
というお互いデメリットを持ってます。
公式で勧められてるのは「両方有効化すること」:
基本的な方針として、もしPostgreSQLと同程度の安全性を求めるなら両方の永続化方式を使った方が良いでしょう。
(The general indication is that you should use both persistence methods if you want a degree of data safety comparable to what PostgreSQL can provide you.)[ http://redis.io/topics/persistence ]
しかしまぁでかいファイルを2つも常にバックアップを取らなきゃいけないし、バックアップ〜クラッシュ時の復帰等は仕組みを整えるまでのコストが高く、やはり永続データのプライマリなストレージとしてはムダに考える事が多すぎました。
あと当時の自分は「RDB & AOF両方有効」運用を知らなかったので、RDBだけで運用してていつもビクビクしてました。
プライマリなストレージとしてのDynamoDB
そんな悩みの中で見つけたのがAmazon DynamoDBでした。
AWSが提供する クラウド上のNoSQLデータベース。
特徴をざっとあげると、
- データモデルは Cassandra に似た、 "Key : Column群" という構造
- データ容量はエンジニアリングレベルで気にする必要はまったく無し。(容量に応じた従量課金)
- データ保護に関してはAmazon S3と同程度の耐障害性を持っている
read/write性能を「何write per sec 欲しいな」てな感じの数字を入力するだけで一瞬で変えられるため、
新しくノードを増やしたりする必要はない。(設定した性能に応じた重量課金)
という内容。
「謳い文句通りならすごいな」と思い、試しにいじり始めたら、まさに謳い文句通りでした。
スループットは Capacity Units という単位で操作します。
Capacity Unitsの計算は、公式によると:
Read Capacity Units - 「強い整合性」のreadで、4KBのアイテムを1秒間で行なえる数
Write Capacity Units - 1KBのwriteを1秒間で行なえる数
(Read capacity units – The number of strongly consistent reads per second of items up to 4 KB in size per second. )
(Write capacity units – The number of 1 KB writes per second. )
[ http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithDDTables.html ]
とのこと。
※「強い整合性(Strongly Consistent)」とは、簡単に言うとwrite後のreadが必ず最新のwriteを反映している時の設定。対して「弱い整合性(Weakly Consistent)」は、readが多少(数秒〜数分)古いデータでも許容するという設定。
早速いざ使ってみようと思ったら、AWSのブラウザ上のコントロールパネルでテーブルを作成するだけ。
あとは言語別に提供されてるAWSのライブラリを使って操作可能です。
我々はPHPのAWS-SDKを使用しました。
しばらく開発環境で試験的にチャットのデータをこっちで回したあとで、「これ使えば一旦チャットのDB負荷やデータ容量に工数をかける必要はなくなるな」と判断し、チャットのRedis からDynamoDBへの全移行を決断しました。
実際の移行プロセスや、DynamoDBで注意するところなどを次のエントリーに書こうと思います。
次の記事:「Pairy : チャットデータを Redis から Amazon DynamoDB に全移行した話(2)」
================
子育て家族アプリFamm、カップル専用アプリPairyを運営する Timers inc. では、現在エンジニアを積極採用中!急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP : http://timers-inc.com