Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

大規模Redisサーバ縮小化の戦い

26,291 views

Published on

2/18のデブサミ2016で発表したスライドになります。
著作権の関係上、ネタスライドは全て削除しております。

Developers Summit 2016【18-C-4】
株式会社アカツキ
駒井祐人

Published in: Technology
  • Be the first to comment

大規模Redisサーバ縮小化の戦い

  1. 1. ⼤大規模Redisサーバ縮⼩小化の戦い 2016/02/18 株式会社アカツキ    駒井 祐人
  2. 2. 2 ⽒氏名:駒井  祐⼈人 経歴: ・2012〜~2015    NTTデータ   官公庁システムのインフラ設計/構築 ・2015〜~2016    アカツキ   ゲームのサーバサイド機能開発   インフラの設計構築、運⽤用保守 趣味: キャンプ、フェス、ドラム、でんぱ組   感情報酬社会を⽬目標に、明るく楽し いエンジニアリングを⽇日々⽬目指してい ます。 ⾃自⼰己紹介   ※よく未成年年と間違えられます 使っている技術:
  3. 3. 3 創業6年年⽬目のベンチャー企業 iOS/Androidのネイティブアプリのサービスを展開 アカツキって? サウザンド メモリーズ シンデレラ イレブン シンデレラ ナイン ※本⽇日はこういったアプリを 開発/運⽤用している中での インフラのお話をします
  4. 4. 4 直近4年年の収益成⻑⾧長率率率  2,106%  ⽇日本第1位  受賞 “働きがいのある会社ランキングベストカンパニー”  3年年連続受賞   アカツキって? Tips  Pitch (毎朝) ︎マンスリーパーティ (毎⽉月) ︎Good  And  New (毎朝)
  5. 5. 5 AWSのElastiCache(Redis)を64台から8台にしたノウハウ      話すこと   ・Redisのdumpのバイナリ構造   ・Redisのdumpのマージ⽅方法   ・マージ後に発⽣生した接続数トラブル   話さないこと   ・格納するデータ構造の⼯工夫   ・Redisのチューニング⽅方法 今⽇日話すこと
  6. 6. 6 前提   ・Redisとは   ・システムの問題点   ・64台になった経緯、64台の影響 縮⼩小化の流流れ   ・現状のRedisの構造の整理理   ・マージ⽅方法の検討   ・Redisのdumpのバイナリ構造   ・縮⼩小化の流流れ 発⽣生したトラブル等   ・困ったこと、当⽇日発⽣生したこと   ・縮⼩小結果、縮⼩小後に発⽣生したトラブル   ・まとめ ⽬目次
  7. 7. 7 Redisとは ・インメモリデータベース  →  ⾼高速 ・5種類のキー/バリューのデータ型  →  複数の⽤用途 ・ファイル永続化オプション  →  信頼性 どういうときに使われる? ・セッション情報のキャッシュ ・クエリのキャッシュ ・弊社では冒険に⾏行行く際のフレンド情報や、   ショップのセール情報などに そもそもRedisって?
  8. 8. 8 ・EC2が20台運⽤用に対して システムの問題点 EC2 20台
  9. 9. 9 ・Redis  (ElastiCache)  サーバが64台 システムの問題点 Redis 64台
  10. 10. 10 ・元々は8台運⽤用だった ・リリース当初、Redisの負荷が激増した。 ・緊急対応で64台までスケールアウト なぜ64台になったのか?
  11. 11. 11 ・調査すると、keys(“*”)を実⾏行行している箇所があった。 なぜ64台になったのか?
  12. 12. 12 ・調査すると、keys(“*”)を実⾏行行している箇所があった。 なぜ64台になったのか?
  13. 13. 13 ・全てのサーバにリクエストが⾏行行くので、   サーバ増やしても意味が無い ・レビュー漏漏れ+負荷テストでRedisのデータ量量のチェック が漏漏れていた なぜ64台になったのか?
  14. 14. 14 ・当然、お⾦金金がかかる     cache.m3.large($0.240)  *  64台  *  1ヶ⽉月  *  (1ドル→120円)                     =  135  万円/⽉月 64台運⽤用してみて ※  RedisはAWSのElastiCacheを使⽤用している。     Redisはシングルスレッドのため、コア数1の ノードタイプを採⽤用したかったが、コア数が少ない ノードタイプは、メモリ量量も少ないため、バランス を取ってcache.m3.largeを採⽤用している。
  15. 15. 15 ・冗⻑⾧長化に腰が重くなる    128台はさすがに…64台でも起動上限引き上げてるのに   また起動数上限数を緩和するのか… ・YAML(設定ファイル)に記載する   項⽬目がめちゃくちゃ増える 64台運⽤用してみて
  16. 16. 16 ・冗⻑⾧長化に腰が重くなる    128台はさすがに…64台でも起動上限引き上げてるのに   また起動数上限数を緩和するのか… ・YAML(設定ファイル)に記載する   項⽬目がめちゃくちゃ増える 64台運⽤用してみて 設定ファイルの⻑⾧長さ
  17. 17. 17 ・縮⼩小化…64台のRedisサーバを減らしたい! ・冗⻑⾧長化…マルチAZ対応させたい! 対処したい 64台のRedis
  18. 18. 18 ・縮⼩小化…64台のRedisサーバを減らしたい! ・冗⻑⾧長化…マルチAZ対応させたい! 対処したい これぐらいにしたい!
  19. 19. 19 ・縮⼩小化…64台のRedisサーバを減らしたい! ・冗⻑⾧長化…マルチAZ対応させたい! 対処したい 冗⻑⾧長化してもこれくらい
  20. 20. 20 ・現状のRedisの構造、データ件数を整理理してみる     インスタンスクラス:       cache.m3.large  *  64台          データの中⾝身:       冒険に⾏行行く際のフレンド情報       ショップのセール情報       イベントのランキング情報 現状整理理
  21. 21. 21 ・キーの件数 現状整理理
  22. 22. 22 ・キーの件数 →あれ、何か全く同じデータ件数がいっぱいある 現状整理理
  23. 23. 23 ・キーの件数                        ・設定ファイル →設定ファイルと⽐比較してみる 現状整理理
  24. 24. 24 ・キーの件数                        ・設定ファイル →各Redisで使っているdbは1個だけ 現状整理理
  25. 25. 25 ・なぜこんなことになったのか? 現状整理理 当時のデータ構造 ↓ コピーして ノード数を増やした
  26. 26. 26 ・なぜこんなことになったのか? 現状整理理 当時のデータ構造 ↓ コピーして ノード数を増やした
  27. 27. 27 ・なぜこんなことになったのか? 現状整理理 当時のデータ構造 ↓ コピーして ノード数を増やした
  28. 28. 28 ・なぜこんなことになったのか? 現状整理理 当時のデータ構造 ↓ コピーして ノード数を増やした
  29. 29. 29 ・なぜこんなことになったのか? 現状整理理 当時のデータ構造 ↓ コピーして ノード数を増やした
  30. 30. 30 ・なぜこんなことになったのか? 現状整理理 当時のデータ構造 ↓ コピーして ノード数を増やした
  31. 31. 31 ・キーの件数 全体だとこんな感じ 現状整理理
  32. 32. 32 マージ⽅方法の検討 ・Redisってマージできんの?     Redisのドキュメントを調べる     AWSのドキュメントを調べる     Github上のそれっぽいツール
  33. 33. 33 マージ⽅方法の検討 ・Redisってマージできんの?     Redisのドキュメントを調べる  →  のってない     AWSのドキュメントを調べる     Github上のそれっぽいツール
  34. 34. 34 マージ⽅方法の検討 ・Redisってマージできんの?     Redisのドキュメントを調べる  →  のってない     AWSのドキュメントを調べる  →  のってない     Github上のそれっぽいツール
  35. 35. 35 マージ⽅方法の検討 ・Redisってマージできんの?     Redisのドキュメントを調べる  →  のってない     AWSのドキュメントを調べる  →  のってない     Github上のそれっぽいツール  →  makeが通らない  w
  36. 36. 36 ■案1   Key/Valueを抜き出し別dbに⼊入れていく マージ⽅方法の検討 ■案2   dumpファイルを結合する dump dump+ dump+ 5つの データ型 ごとに計算
  37. 37. 37 ■案1   Key/Valueを抜き出し別dbに⼊入れていく マージ⽅方法の検討 ■案2   dumpファイルを結合する dump dump+ dump+ 5つの データ型 ごとに計算   以下の理理由で案2を採⽤用   ・計算量量が少なく     ⾼高速にマージできそう   ・触るのはヘッダフッタの構造部分のみで     中⾝身のデータを触る必要がない
  38. 38. 38 Redisはデフォルトで16個のdbを持っている Redisのdumpの構造 Redis ・・・ db15db0 db1 db2 dump
  39. 39. 39 Redisのdumpの中⾝身 Redisのdumpの構造 ヘッダ DB番号 db0:FE00 終端⽂文字 FF CRC64   checksum 9byte DB番号 db1:FE01 データ データ ・ ・ ・ 2byte 1byte 8byte データ
  40. 40. 40 Redisのdumpの中⾝身 Redisのdumpの構造 DB番号 db0:FE00 終端⽂文字 FF CRC64   checksum 9byte DB番号 db1:FE01 データ データ ・ ・ ・ 2byte 1byte 8byte データ ヘッダ
  41. 41. 41 Redisのdumpの中⾝身 Redisのdumpの構造 ヘッダ 終端⽂文字 FF CRC64   checksum 9byte DB番号 db1:FE01 データ データ ・ ・ ・ 2byte 1byte 8byte データ DB番号 db0:FE00
  42. 42. 42 Redisのdumpの中⾝身 Redisのdumpの構造 ヘッダ DB番号 db0:FE00 終端⽂文字 FF CRC64   checksum 9byte DB番号 db1:FE01 データ データ ・ ・ ・ 2byte 1byte 8byte データ
  43. 43. 43 Redisのdumpの中⾝身 Redisのdumpの構造 ヘッダ DB番号 db0:FE00 CRC64   checksum 9byte DB番号 db1:FE01 データ データ ・ ・ ・ 2byte 1byte 8byte データ 終端⽂文字 FF
  44. 44. 44 Redisのdumpの中⾝身 Redisのdumpの構造 ヘッダ DB番号 db0:FE00 終端⽂文字 FF CRC64   checksum 9byte DB番号 db1:FE01 データ データ ・ ・ ・ 2byte 1byte 8byte データ
  45. 45. 45 ごちゃごちゃしましたが、要は、こういうわけです Redisのdumpの構造 Redis ・・・ db15db0 db1 Redis db 0 デ ー タ ヘ ダ db 15 デ ー タ 終 端 ⽂文 字 チ ク サ ム db 1 デ ー タ ・・・ 9byte 1byte 8byte
  46. 46. 46 ・話を元に戻すと、こんなデータ構造でした マージ⽅方法
  47. 47. 47 ・ゴミを消します   →シンプルなシングルDBの構成に マージ⽅方法
  48. 48. 48 ・まず2つのdumpのマージ⽅方法について考えてみる マージ⽅方法
  49. 49. 49 ・まず2つのdumpのマージ⽅方法について考えてみる マージ⽅方法 Redis-‐‑‒01 db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム Redis-‐‑‒02 db 1 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte 9byte 1byte 8byte
  50. 50. 50 ・まず2つのdumpのマージ⽅方法について考えてみる マージ⽅方法 Redis-‐‑‒01 db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム Redis-‐‑‒02 db 1 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte 9byte 1byte 8byte Redis-‐‑‒01の 後ろ9byteを削除 Redis-‐‑‒02の 前の9byteを削除
  51. 51. 51 ・まず2つのdumpのマージ⽅方法について考えてみる マージ⽅方法 Redis-‐‑‒01 db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム Redis-‐‑‒02 db 1 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte 9byte 1byte 8byte Redis-‐‑‒01の 後ろ9byteを削除 Redis-‐‑‒02の 前の9byteを削除 Redis  (New) db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte db 1 デ ー タ
  52. 52. 52 ・試しにローカル環境でリストアしてみる (ローカルのredis-‐‑‒serverを停⽌止した状態で、dumpファイルを差し替えると、次 に起動する際に、差し替えたdumpファイルを読み込んで起動してくれます) マージ⽅方法 $ cp –p merged_dump.rdb dump.rdb $ redis-server /usr/local/etc/redis.conf dump ローカルPC redis-‐‑‒server
  53. 53. 53 マージ⽅方法 (カチャカチャ・・・) (ッターン!) $ cp –p merged_dump.rdb dump.rdb $ redis-server /usr/local/etc/redis.conf ・試しにローカル環境でリストアしてみる (ローカルのredis-‐‑‒serverを停⽌止した状態で、dumpファイルを差し替えると、次 に起動する際に、差し替えたdumpファイルを読み込んで起動してくれます)
  54. 54. 54 ・試しにローカル環境でリストアしてみる マージ⽅方法 _⼈人⼈人⼈人⼈人_ >  エラー!!<  ̄Y^Y^Y^ ̄ (カチャカチャ・・・) (ッターン!)
  55. 55. 55 ・よーく⾒見見ると・・・ マージ⽅方法 Redis-‐‑‒01 db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム Redis-‐‑‒02 db 1 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte 9byte 1byte 8byte Redis-‐‑‒01の 後ろ9byteを削除 Redis-‐‑‒02の 前の9byteを削除 Redis  (New) db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte db 1 デ ー タ
  56. 56. 56 ・よーく⾒見見ると・・・ マージ⽅方法 Redis-‐‑‒01 db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム Redis-‐‑‒02 db 1 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte 9byte 1byte 8byte Redis-‐‑‒01の 後ろ9byteを削除 Redis-‐‑‒02の 前の9byteを削除 Redis  (New) db 0 デ ー タ ヘ ダ 終 端 ⽂文 字 チ ク サ ム 9byte 1byte 8byte db 1 デ ー タ ここのチェックサムが Redis02全体のチェックサムに なっている
  57. 57. 57 ・CRC64  checksum(8byte)を付与することでおk ・checksumを無視する設定も マージ⽅方法 rdbchecksum no
  58. 58. 58 ・CRC64  checksum(8byte)を付与することでおk ・checksumを無視する設定も ・安⼼心してください、   dumpの構造が問題ないか   確認するコマンドありますよ      マージ⽅方法 rdbchecksum no $ redis-check-dump [dumpファイル名]
  59. 59. 59 どことどこをマージするか 59 元々のdb情報
  60. 60. 60 どことどこをマージするか 60 ゴミデータ削除後
  61. 61. 61 どことどこをマージするか 61 ゴミデータ削除後
  62. 62. 62 どことどこをマージするか 62
  63. 63. 63 どことどこをマージするか 63
  64. 64. 64 どことどこをマージするか 64
  65. 65. 65 どことどこをマージするか 65 Redis-‐‑‒01 (New)
  66. 66. 66 どことどこをマージするか 66 Redis-‐‑‒01 (New) Redis-‐‑‒02 (New)
  67. 67. 67 どことどこをマージするか 67 Redis-‐‑‒01 (New) Redis-‐‑‒02 (New)
  68. 68. 68 どことどこをマージするか 68 Redis-‐‑‒01 (New) Redis-‐‑‒02 (New)
  69. 69. 69 どことどこをマージするか 69 Redis-‐‑‒01 (New) Redis-‐‑‒02 (New) Redis-‐‑‒03 (New)
  70. 70. 70 どことどこをマージするか 70 Redis-‐‑‒01 (New) Redis-‐‑‒02 (New) Redis-‐‑‒03 (New) Redis-‐‑‒04 (New)
  71. 71. 71 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了
  72. 72. 72 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・EC2をReadReplicaとして接続 $ redis-cli slaveof [ホスト名] 6379 Redis EC2 redis-‐‑‒server
  73. 73. 73 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・バックアップ(dump)取得 ※  AWS上でスナップショットは取得できるが、     ファイル出⼒力力ができない $ redis-cli save Redis redis-‐‑‒server EC2 dump dump
  74. 74. 74 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・バックアップ(dump)取得 $ redis-cli save Redis redis-‐‑‒server EC2 dump dump AWSさん、何とかしてください!!w
  75. 75. 75 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・指定のdbをflushする ✕  64台 redis = Redis.new(host: HOSTNAME, port: 6379) redis.select(dbnum) redis.flushdb Redis redis-‐‑‒server EC2
  76. 76. 76 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・ゴミ消去後、再度度dump取得 $ redis-cli save Redis redis-‐‑‒server EC2 dump dump
  77. 77. 77 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・dumpデータをマージする Redis redis-‐‑‒server EC2 New dump dump dump
  78. 78. 78 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・S3にアップロードし、権限付与する   →aws-‐‑‒scs-‐‑‒s3-‐‑‒readonly@amazon.comに     開く/ダウンロードの権限 Redis S3 redis-‐‑‒server EC2 New dump dump dump
  79. 79. 79 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・S3のパスを指定して、Redisを起動 Redis S3 Redis(New) redis-‐‑‒server EC2 New dump dump dump
  80. 80. 80 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・設定ファイル変更更 ・キーの件数⽐比較 ・実機検証 Redis S3 Redis(New) redis-‐‑‒server EC2 New dump dump dump
  81. 81. 81 縮⼩小化の流流れ メンテナンス開始 バックアップ ゴミデータ削除 マージ リストア メンテナンス終了了 ・設定ファイル変更更 ・キーの件数⽐比較 ・実機検証 Redis S3 Redis(New) redis-‐‑‒server EC2 New dump dump dump
  82. 82. 82 1.  バックアップ失敗 ※  ReadReplicaとして接続した際に、過去のデータがflushされる前にsaveを実⾏行行 しても、正確にバックアップが取れない 失敗談 Redis redis-‐‑‒server EC2 dump dump ※  log出⼒力力の設定:syslog-‐‑‒enabled  yes    →  syslog、  logfile  stdout  →  標準出⼒力力
  83. 83. 83 1.  バックアップ失敗 ※  ReadReplicaとして接続した際に、過去のデータがflushされる前にsaveを実⾏行行 しても、正確にバックアップが取れない 失敗談 Redis redis-‐‑‒server EC2 dump dump ※  log出⼒力力の設定:syslog-‐‑‒enabled  yes    →  syslog、  logfile  stdout  →  標準出⼒力力
  84. 84. 84 2.  マージ後のdumpファイルはたった8個しかないのに     オペミスで同じdumpファイルから2台サーバを⽴立立ち上げる     ※  くれぐれも深夜作業にはご注意を・・・ 失敗談
  85. 85. 85 ・想定通り縮⼩小することができた!!冗⻑⾧長化も!! ・かかった時間はトラブルも含め約4時間 縮⼩小前   cache.m3.large  *  64台  →  135  万円/⽉月 縮⼩小+冗⻑⾧長化後   cache.r3.large  *  8台  *  2(マルチAZ)  →  38  万円/⽉月 →冗⻑⾧長化しつつも約100万/⽉月  コスト削減!!   (1ドル120円換算) 結果
  86. 86. 86 しかし、数週間後・・・
  87. 87. 87 突然のエラーの嵐嵐!!!
  88. 88. 88 突然のエラーの嵐嵐!!!
  89. 89. 89 ・ゲームのあるスペシャルイベントでリクエスト数が激増 ・サーバ台数をかなりの⼤大規模で増やした ・Redisのconnectionが上限に達してエラー   ※  接続数の計算例例       100(サーバ)  ✕  50(unicornプロセス)  ✕  16(DB)  =  80000  clients →複数DBを使ったことがアダとなり、接続数が激増した 縮⼩小後に発⽣生した事象 接続数設定 実際の接続数 $ redis-cli –h [ホスト名] –p 6379 info # Clients connected_clients:64086
  90. 90. 90 縮⼩小後に発⽣生した事象 リソースは余裕ありそうだし 接続数の上限を変更更すっか
  91. 91. 91 ・Redis(ElastiCache)の接続数の上限は変更更できない。 縮⼩小後に発⽣生した事象
  92. 92. ・今度度はDB数を減らす必要がある 92 再度度縮⼩小することに 縮⼩小後のRedis
  93. 93. ・今度度はDB数を減らす必要がある 93 再度度縮⼩小することに 縮⼩小後のRedis
  94. 94. ・今度度はDB数を減らす必要がある 94 再度度縮⼩小することに 縮⼩小後のRedis 最終状態
  95. 95. ・今度度はDB数を減らす必要がある ・問題点:   →さきほどのマージ⽅方法が使うのが難しい 95 再度度縮⼩小することに 縮⼩小後のRedis 最終状態
  96. 96. 96 ■案1   Key/Valueを抜き出し別dbに⼊入れていく マージ⽅方法の検討 ■案2   dumpファイルを結合する dump dump+ dump+ 5つの データ型 ごとに計算
  97. 97. 97 ■案1   Key/Valueを抜き出し別dbに⼊入れていく マージ⽅方法の検討 ■案2   dumpファイルを結合する dump dump+ dump+ 5つの データ型 ごとに計算    今度度は案1を採⽤用     ・計算量量は多いが       複数dbをまたいでデータを統合できる。
  98. 98. 98 ・試しに検証環境で同じ環境を構築してやってみる 検証 Redis redis-‐‑‒server EC2
  99. 99. 99 ・試しに検証環境で同じ環境を構築してやってみる    検証 Redis redis-‐‑‒server EC2 ・応答が返ってこない…
  100. 100. 100 ・試しに検証環境で同じ環境を構築してやってみる    とは⾔言え、それでもマージ時間だけでめちゃくちゃ時間がかかった       1dump  12分  *  8dump  =  96分 (※  最初のバイナリ結合の⽅方法だと、数秒で全てのマージが終わるのに対して) 検証 Redis redis-‐‑‒server EC2 dump ・応答が返ってこない… ・直接ElastiCache(Redis)を操作するよ り、ローカルでリストアしたデータを操作 したほうが早かった。
  101. 101. 101 ・複数サーバで並列列に実⾏行行し、   なんとか縮⼩小することができた!! ・想定通り接続数が半分に! 結果 接続数 $ redis-cli –h [ホスト名] –p 6379 info # Clients connected_clients:30125
  102. 102. 102 ・2種類の⽅方法でRedisを縮⼩小化することに成功。 ・dumpの構造を知ることで、⽐比較的容易易にマージ可能。 ・複数dbを使うと、connection数に気をつける必要がある。 ・We  are  hiring  !! まとめ

×