00:06
はい、5月6日、土曜日ですね。
地獄の朝9時14分になってしまいました。
ごめんなさい。朝から洗濯物をやっていたら、すっかり時間が過ぎてしまいました。
はい、今から始めていきたいと思います。
はい、おはようございます。ユメミのきーすくんのくばはらです。
ではでは、本日も朝活を始めていきまーす。
で、今日は、前回に引き続きですね、Redis Explainedの記事ですね。
はい、まぁRedisについての説明というか、紹介なお話ですね。
設計周りだったりそうですし、途中の中の処理、どんなことやってんの?とか話ですね。
それに加えて、他の周辺的な知識とかのお話もセットでされてまして、
すごく勉強になるなと思っているので、その辺の記事の続きを読んでいこうと思っております。
はい、ざっくりですけど、アーキテクチャー周りの話を確かめようかな、前回ですね。
いわゆるシングルRedisインスタンスですね。
Redisのインスタンス的な動きの話と、
AHAですね、高可用性、ハイアベリアピリティの話と、
Redis Sentinelっていう機能があって、それの話とですね。
で、次はRedis Clusterの話かな、がまだ途中だった気がするので、
今日はその続きだったと思っております。
間違ってたらごめんなさい。
重複してたりしたら、復習として聞いていただけるとすごく嬉しいなと思ってます。
で、途中ですね、Sentinelの話の中で、クオラムっていう、
発音クオラムかクオラムかわからないですけど、
っていうお話もあって、
それがRedisの中でも結構根幹の機能の一つというか、
仕様になっているので、その辺のところも、
みなさんの方で読んで復習していただけるというのかなと思ってます。
いわゆるクラスター周りのところの話ですね。
クオラムっていうのがあって、それとセットでくっついてくるという話ですね。
ではでは、今日はRedis Clusterのところから入っていきたいと思います。
後ほどですね、この記事、前回もシェアしたんですけど、
改めて後ほど、僕からまた記事を共有させていただきたいと思いますので、
詳しく見たい人は見てみてください。
それぞれのセクションとか、この記事全体の冒頭で、
画像が一枚ペッと貼られてるんですけど、
それを見ると、だいたい今回の記事全体で言いたいことが全て書かれてます。
それを見てもらった方がむしろ分かりやすいかもしれないですね。
ということで、前置きは去っておき、では早速入っていきたいと思います。
Redis Clusterの話ですね。
一台のマシンで全てのデータをメモリに保存できなくなったときのことを考えたことがある、
という人は多いんじゃないでしょうか。
現在一台のサーバーで利用できるRAMですね。
というのは24TiBですね。
現在AWSのオンラインに掲載されています。
しかしシステムによってはキャッシングレイヤーでさえも、
これでは十分ではありません。
Redis ClusterはRedisの水平スケーリングというのを可能にしています。
というお話ですね。
バーティカル&ホリズンタルのスケーリング。
垂直と水平のスケーリングの話という補足があるので、
そこも一緒に読んでいこうと思っています。
システムが大きくなるにつれて、3つの選択肢が出てきます。
1つは、より少なくする。
私たちは悪なき怪物なので、
これを完全に実行する人は多分いないでしょう。
少なくします。
続いてはスケールアップする。
03:01
最後はスケールアウトする。
この3つの選択肢を僕らはとると思っています。
後者の2つですね。
スケールアップとスケールアウトですね。
そういうのを真剣に考えると、
それぞれ垂直方向と水平方向のスケーリングとして知られています。
垂直スケーリングは、より早く仕事をするために、
より大きく優れたマシンを手に入れ、
全ての問題がハードウェアとうまくスケールすることを願う手法です。
たとえそれが可能であっても、
結局は使用するハードウェアによって制限を受けることとなります。
その時点に達したら、より可能性が高く、
できればずっと前に全体の小さな部分を担当する
複数の小さなマシンにワークロードを分散させることによって、
水平方向に拡張する必要があります。
どちらの選択肢でもありますが、
基本的には水平方向で考えるのが良いと思いますが、
まっさげにのおしり水平にする方が良いという言い方を
僕はしたいわけではないので、
一応両方考えていいと思っていますが、
垂直にはさすがに、
結局はマシンスペックとか、
ハードウェアの上限という制約があるということを前提で
もちろん考えなければいけないということです。
もし使うサービスとかユーザーとかアクセスが
どんどん上がるということが目に見えていて、
後ほどスケールをもう一回考えなきゃいけないという問題が
もう既にあるというのであれば、
最初から水平方向でもいいと思うんですけど、
そうじゃないんだったら別に水平、
じゃなくて垂直方向、
単純にマシンスペックガッと上げるぐらいで
ちょうどいいんじゃないかなと思ったりしますけども、
などなど、
いろんな考え方がもちろんあると思いますので、
状況によって選択していただければというところですね。
はい、戻りまして、
そこで用語を整理しておきましょう。
レディスクラスターを使うことを決めた場合ですね、
保存するデータを複数のマシンに分散させることにしました。
これをシャーディングと言います。
つまりクラスター内の各レディスインスタンスは
データ全体のシャードとみなされたりもしますと、
これによって新たな問題が発生します。
キーをクラスターにプッシュする場合、
どのレディスインスタンス、いわゆるシャードですね、
がそのデータを保持しているのか、
どうやって知ることができるんでしょうかと。
クラスターとかインスタンスごとで
データの同期性とかをしなきゃいけないけど、
それをどうやってやるのかという話で。
これにはいくつかの方法がありまして、
レディスクラスターではアルゴリズムによって
シャーディングを採用しています。
あるカギのシャードを見つけるためには
そのカギをハッシュ化し、その合計結果を
シャードの数で修正しますと。
はぁ、そんなことやってるの。
そして決定論的ハッシュ関数、
与えられたカギは常に同じシャードにマッピングされる。
そういうハッシュ関数を使って
将来特定のカギを読むときに
そのカギがどこにあるかというのを
推論することができます。
後で新しいシャードをシステムに追加したい場合は
どうすればいいでしょうかと。
このプロセスは再シャーディングと呼ばれたりします。
なるほどね。
結構シンプルというか
無理やりと言えなくもないけど
割とシンプルな構成とか
アルゴリズムになってそうですね。
そういう意味では分かりやすくていいかもですね。
新しいシャードを導入した後、
キー、例えばフーみたいなキーが
シャード0にマッピングされたと仮定しましょう。
そうするとシャード5ですね。
5番目にマッピングされるかもしれません。
06:00
しかし新しいシャードのマッピングを
反映させるためにデータを移動させるのは
やっぱり時間がかかり
システムを迅速に成長させる必要がある場合は
非現実的でなってしまいます。
またレディスクラスターの可用性にも
悪影響があります。
レディスクラスターはこの問題を解決するために
全てのデータがマッピングされる
ハッシュスロットと呼ばれるソリューションを考案しました。
ハッシュスロットは16傾向あります。
1万6千個あるんですね。
これによってクラスター全体に
データを広げる合理的な方法が得られ
新しいシャードを追加する際には
システム間でハッシュスロットを
移動させるだけになります。
こうすることでそのシャードからシャードへ
ハッシュスロットを移動させるだけで良くなり
新しいプライマリインスタンスを
クラスターに追加するプロセスが
簡素化されます。
その場合でもそれぞれのシャードの
スケールもそうだけど
それをマッピングする
ハードウェアとかマシンスペックも
あるので
スピードを求められる
気がするので
そこをちゃんと担保できるのかとは気になりますけどね。
そういう機構になっているとは分かりました。
これはダウンタイムなしで
パフォーマンスへの影響も
最小限に抑えることができます。
例を挙げて説明していきましょう。
まずM12は0から8191までの
ハッシュスロットが含まれます。
2の9乗かな。
嘘つき。
9なわけねえじゃん。
2の何乗だろう。
とりあえず2の何乗かの話ですね。
M2には8192から
16383まで
ハッシュスロットが含まれています。
そこでFooをマッピングするために
キーFooの決定論的
ハッシュを取りそれをハッシュスロットの数
16000で
修正をするとM2という
マッピングになります。
車像的な考え方ですね。
M1からM2への車像と考えればいい。
ここで新しいインスタンスM3を
追加するとしましょう。
新しいマッピングは次のようになります。
M1には0から5460までの
ハッシュスロットが含まれる。
M2には5461から
1922までのハッシュスロット。
M3は1923から
16383までのハッシュスロット。
16000って言ってるけど
約16000でゲーム数は16384
のハッシュスロットを
持ってて新しいスロット
そのスロットの数で割って
それを分配ですね。
なるほどなるほど。
M1のハッシュスロットをマッピングしていたキーが
M2にマッピングされた場合
全てのキーが移動する必要があります。
しかしハッシュスロットの個々の
キーのハッシュっていうのはすでに
ハッシュスロット間で分割されているため
移動する必要はないでしょう。
つまりこの一つのレベルのミスディレクションによって
アルゴリズムシャーディングの
再シャーディングの問題が解決されると。
なるほどねって感じですね。
わざわざ振ったハッシュをそのまま
うまいこと利用して向き先変えるだけで
便利にするという感じですかね。
それができているんだったら
確かにコスト的に安くていいですね。
そうするとそんなにマシンスペックがなくても
良さそうですね。
一回ポッて向き先とか方向を変えるだけでいいので。
続いてゴシッピングっていうセクションですね。
はい。ゴシッピングって
09:00
日本語に訳すとゴシゴシって
アラウ的な擬音語になるんですね。
レディスクラスターっていうのは
クラスター全体の健全性を判断するために
ゴシッピングを利用しますと。
上の図では3つのMノードと
3つのSノードがあります。
図っていうのは僕しか見えてなくて
申し訳ないですけど。
レディスクラスターのところで
M1、M2、M3というものと
S1、S2、S3という
いわゆるゴシッピング用のクラスターが
振られていて、それの画像があると。
そこに対してレプリケーションが
M1からS1、M2からS2、M3からS3
みたいな風に振られているんですけど
点線として
それぞれのM1からS2、S3
とかへの点線も振られているし
その逆もしかしてM3からS1、S2への
点線も振られたりする。
ので、一体
他になっているという感じですね。
一つのMに対してS、ゴシッピングの方は
他です。になっている。そういう対応ですね。
で、これらのノードは常に通信を行い
どのシャードが利用可能で
リクエストに対応できる状態があるか
というのを把握します。M1が応答しないことに
十分な数のシャードが
同意していた場合は
クラスターを健全に保つために
M1のセカンダリ、S1をプライマリに
消化させることを決定できます。
あー、なるほどね。Mがいわゆるプライマリで
S、シャードというのがいわゆるセカンダリ
のことを意味しているんですね。
このトリガーに必要なノード数は
設定可能で、これを正しく行うことが
慣用です。やり方を誤ると
パーティッションの両側が等しい
時にタイを崩せず
クラスターが分裂するような事態に落ちることが
あります。落とし穴じゃん。
この現象をスプリットブレイン
と呼びます。一般的なルールとして
最も堅牢なセットアップのためには
プライマリノードとレプリカを
それぞれ奇数個ずつ用意することが不可欠です。
結果、そういうちょっとした
運用のお話がやっぱり出てくるんですね。
とはいえ、これは
プラットフォーマーとしては仕方ないですよね。
完全に対応するというのは結構難しい問題があるので
ユーザーにも多少はやっぱり
設計を考えてほしいのはやっぱりありますよね。
はい、今のが一応ゴシッピングで
続いて、RELISの
永続化モデルですね。
パーシステンスモデルのお話です。
RELISを使って何らかの
データを安全に保存しようとするならば
RELISがどのようにそれを行っているかを
理解することが重要です。
RELISが保存しているデータが失われたとしても
世界の終わりにはならないような使用例がたくさんあります。
そうなんだ。RELISって
多少揮発性が残っているけど
そのための永続性の話でしょうね。
キャッシュとして使用する場合やリアルタイム分析に
使用する場合、データの損失が発生しても
世界の終わりではありません。
またデータの永続性や復元性をある程度
保証したいシナリオというのも用意していますよと。
一応そういう画像がペッと貼られていますね。
いわゆるスナップショットをとって
それをパーシステントスナップショットとして
RDBに保存をしていくという方法もあれば
Append Only File
ファイルに送るとか
いろんな例が画像として貼られているので
その辺を使ってみてくださいと。
RELISの中でも一応やっているはずなんですけど
今からそれぞれのお話を
具体的に説明されていきますね。
RELISって基本的には高速で
全ての整合性保証というのは
速度に次ぐものですと。
整合性の保証は速度に次ぐんだ。
12:00
やっぱり速度最優先なんですね。
いやー振り切ってていいですね。
これには議論の余地がもちろん
ある話題かもしれませんが
RELISってのはそういうデータベースですよ
という話です。
それを分かって使わないで文句言う人も
なんかいそうな気はしますけどね。
続いて、まず一つ目ですね。
それぞれの永続性の話ですけど
一つ目はNo Persistence、つまりこたわりがない場合ですね。
No Persistenceの場合は
希望すれば永続化を完全に無効することも
一応できますと。
これはRELISを最も早く実行する方法であり
耐久性というのは保証されません。
いわゆるちゃんとインメモリというか
キャッシュとして使うということを
前提で使うんであれば
これが一番RELISとしてパフォーマンスも出るし
本来といいますか
根本的なもともとのRELISの使い方
という感じはしますね。
というので永続性は気にしないというのが
一つの設計ですと。
続いてはRDBファイルズですね。
RDB、いわゆる
REDISデータベースのことですね。
リレーショナルデータベースじゃなくて
REDISデータベースのことです。
RDBの永続化というのは指定された間隔で
データセットのポイントインタイムスナップショット
というのを実行します。
このメカニズムの主な欠点は
スナップショット間のデータが失われることです。
このストレージ機構は
メインプロセスのフォークに依存しており
大きなデータセットでは
リクエストの対応が一瞬遅れることもあります。
とはいえRDBファイルは
スナップよりもメモリーに読み込まれる速度が
はるかに速いよと言っています。
今のがRDB、REDISデータベースファイル
という方向です。
ただそのデータ間での整合性が
外れる可能性が多いので
そこは気を付けてください。
そういう場合は意外と使いたくないかもしれないですね。
結果データが
本来僕らがやりたいアプリケーションとか
システムの根幹になるので
データの整合性が取れないんだとすると
どこを許容するか難しいなと思います。
では続いてAOFです。
AOFというのは
サーバーが受け取る全ての書き込み操作を記録して
サーバーの起動時に再度再生され
元のデータセットを再構築する
AOFです。
これが一番信頼性が高いですね。
この方法でAOFを確保すると
追記型のファイルなので
RDBのスナップショットよりも
はるかに耐久性はあります。
操作が発生すると
それをログにバッファリングしますが
まだAOF化されていない。
ログに書き出すだけだとまだAOF化はしていない。
このログを必要なときに再生できるように
実際に実行したコマンドで構成されている。
そして可能な限り
Fジンクでディスクにフラッシュすること
この実行タイミングは設定可能になります。
Fジンクでディスクにフラッシュして
永続性を保っていく。
欠点は
フォーマットがコンパクトではなく
RDBファイルのディスクを使うことです。
ディスクを使うこともそうだけど
あとスピードじゃないですかね。
本来のパフォーマンスが下がる。
この2つが欠点だと思うので
どこまで永続性とかデータを管理するか
前回読んだ
前半パートで
本番データベースとして使ってもいいよ
と彼らは主張していて
それは確かに納得はできたんですけど
ここまで来ると
普通にRDB
15:00
元々の
データベースでちゃんとデータ管理する方が
良い気もしなくはないですが
それでもレリースの方が早いんでしょうね。
とは思ったりしました。
では続いて
補足として
Fsyncの話が出てきますので
そこもちょっと読んでいこうと思います。
FsyncっていうのはファイルディスクリプターFDで
参照されるファイルの全ての変更された
インクコアデータ
すなわち変更されたバッファキャッシュページ
をディスクデバイス
または他の永続記憶デバイス
にいわゆるフラッシュし
転送してシステムがクラッシュまたは
再起動した場合でも全ての変更情報を
取得することができるようにします。
様々な理由によってファイルに変更が
加えられるとキャッシュに保存され
Fsyncの呼び出しによりディスクに保存され
後でアクセスできるようになります。
というものですね。
では続いて
先ほどの話を読んだ人は
ちょっと予想するというか
思うことがあると思うんですけど
RDBとAOF組み合わせればいいんじゃないの
という話がちょっと予想できますよね。
次のセクションはその話です。
Why not bothですね。
RDBプラスAOFですね。
同じRedisインスタンスでAOFと
RDBを組み合わせることが一応可能ではあります。
ある程度の速度と引き換えに
耐久性がトレードオフになるなら
それを厭わないという話ですね。
Redisの設定方法としては許容範囲内だと思います。
再起動の場合
両方が有効な場合
RedisはAOFを使用してデータを再構築することを
忘れないでください。
それが最も安全なものだからです。
やっぱり完全に保つのであれば
AOFですよということですね。
一応両方組み合わせることもできるので
どこのデータは多少のずれがあっても
後で同期取ればいいじゃんというのが
できるというのは
結構選択肢として与えてますよということですね。
これは結構いい話でした。
では続いてフォーキングですね。
さて、映像化の種類を理解したところで
実際にRedisのようなシングルスレッドアプリケーションで
どのように映像化を行うかについては
説明していきましょうと。
これも一枚ペットから画像が貼られてますね。
結局スナップショットとメモリのお話を
うまいことディスクで
同期取っていくようなお話には見えますね。
Redisの最もクールな部分というのは
フォークとコピーオンライトを活用して
データの映像化をパフォーマンスよく
実現することだと思ってます。
フォークとはオペレーティングシステムが
自分自身のコピーを作成することで
新しいプロセスを作成する方法ですと。
これによって新しいプロセスIDと
他のいくつかの情報と
ハンドルというのを得られ
新しくフォークされたプロセスの子供ですね。
というのは元のプロセスの親と会話できるようになります。
さてここからが面白いんですけど
Redisというのは大量のメモリが
作成されられたプロセスなので
メモリを使い果たさずにコピーを作るには
どうしたらいいんでしょうかと。
プロセスをフォークすると親と子が
メモリを共有しその子プロセスでは
Redisというのはスナップショットですね。
スナップショット括弧Redisと書いてますけど
の処理が開始されます。
これはコピーオンライトと
フォークが作成された時点のメモリへの参照を
渡すと呼ばれるメモリ共有技術によって
実現されています。
子プロセスがディスクに映像化している間に
変更がなければ新たなアプリケーション
18:00
ちゃんと親子間のプロセスの
お話をしっかりマネジメントしています。
変更がもしあった場合は
カーネルというのは各ページへの参照を追跡し
特定のページへの参照が複数ある場合は
変更は新しいページに書き込まれます。
後プロセスは
変更に全く気づかず
一貫したメモリスナップショットを保つことができます。
このため使用されるメモリはほんの一部で
潜在的にギガバイト級のメモリの
ポイントインタイムスナップショット
極めて迅速かつ
効率的に実現することができます。
もしこれを楽しんでいただけたなら
私たちはこのようなコンテンツをもっとたくさん用意しています。
私たちはこのような状態で
微妙なトピックをすべて理解できるようにし
どこで遭遇するのかを
強調するように努めています。
あとトロークしてみて
使ってみてください。
レディスが私たちのシステムどのように動作しているか
何か役立つことを学んでいけたらすごく幸いです。
フィードバックはツイッターの
この中の人のリンクが
貼られているので
そこに直接送ってください。
このところでレディスの
お話は終了になります。
これはあくまでレディスエクスプレイなので
レディスの基本的に
全体的なざっくり説明なんですけど
それ以外にさっきのコピーオンライトもそうですし
フォークもそうですし
クオラムの細かいお話だったり
他のレディス周りの詳しい説明の
記事もいろいろ貼られていますので
興味のある人は見てみてください。
ところで本記事は終了なので
今日の朝からここで終了していきたいと思います。
久しぶりにレディスのお話を読んだんですけど
業務でなかなかレディスを使うことがなくて
あとメムキャッシュもたまに
使いますけどほぼほぼ使わなくなってしまっているので
改めてでもレディスが
こんなに進化しているとは思わなかったので
改めて触ってみたいというか興味を持ってきました。
やっぱり速いって正義だし
データベース周りのところって
エンジニアとしては職人芸じゃないですけど
こだわろうと思ったり
いくらでもこだわれたりするというところもあるので
ここは上手いこと。フロントエンジニアとしては
やっぱりレディスは近いので
領域として。技術として使えるようになって
おきたいなとはつくづく感じました。
というところで改めまして今日の朝方以上になります。
本日の参加者は改めて
しゅうゆせんさんとけんじさんですね。
ご参加いただきありがとうございました。
明日は全然また違う記事を
探してダラダラと読んでいきたいと思いますので
ご興味あれば参加していただければ幸いです。
じゃあ土曜日ですね。
今日明日ですねゴールデンウィーク終わると思いますので
ゆっくり休んでいただいて
また来週から頑張っていけたらなと思います。
じゃあ終了したいと思います。お疲れ様でした。