CubicLouve

Spring_MTの技術ブログ

MacでMirageOSを動かしてみる

OCamlと仮想化の勉強のためMirageOSを触ってみることにしました。

setup

mirage.io 通りにやってみる

brew install opam
opam init
opam install mirage

Hello World

mirage.io

git clone https://github.com/mirage/mirage-skeleton.git

noopをやってみる

% cd tutorial/noop
% mirage configure -t unix
% make depend 
% make
% ls -l noop
lrwxr-xr-x  1 foo  1522739515  18  4 28 01:29 noop -> _build/main.native
% ./noop
% echo $?
0

Hello Worldやってみる

% cd tutorial/hello
% mirage configure -t unix
% make depend
% make
%  ./hello
2021-04-28 01:39:04 +09:00: INF [application] hello
2021-04-28 01:39:05 +09:00: INF [application] hello
2021-04-28 01:39:06 +09:00: INF [application] hello
2021-04-28 01:39:07 +09:00: INF [application] hello
%

4回helloがでるのは単純に loopが4回回ったら止まるからですね

github.com

参考

blog.ojisan.io

dev.realworldocaml.org

https://www.eurosys2020.org/wp-content/uploads/2020/04/slides/159_kuo_slides.pdf

データベースシステム 改訂2版の数式でわからなかったところメモ

p 37

集合は波括弧 {...} を用いて集合の要素を明示的に列挙する。

一般に、条件 P(x) があったとき、それをみたす対象だけを全て集めた集合を、

\displaystyle{
\{x \mid P(x)\}
}

と表記する。

a ∈ Aは aはAに属している、aはAの要素である。

∧ は論理積、AND

A ∧ Bは、Aであり、しかもBである。

ja.wikipedia.org

\displaystyle{
\{ (X_1,\cdots,X_n) | X_1 \in S_1 \land \cdots \land X_n \in S_n \}
}

集合 X1,..,Xnは、S1からSnまでの集合の各要素の組を要素する集合であり、これを S1,...,Snの直積集合と呼ぶ。

ja.wikipedia.org

\displaystyle{
S_1 × \cdots × S_n
}

p 39

下記リレーションスキーマが与えられたとき、

\displaystyle{
R(A_1, \cdots, A_n)

(各属性のドメインを D_1, \cdots D_n とする)
}

リレーションをタプル tiの集合 rとして定義する。

\displaystyle{
r = \{t_1 \cdots, t_m \}
}

各タプルtiは以下のような写像

\displaystyle{
t_i : \{ A_1,\cdots,A_n \} \to D_1 \cup \cdots \cup D_n
}

かつ

\displaystyle{
t_i(A_k) \in D_k  (1 \leqq k \leqq n, 1 \leqq i \leqq m)
}

という条件を満たすものとする。

ja.wikipedia.org

http://www.aoni.waseda.jp/sadayosi/course/past/set05/section1.2.pdf

集合 A から集合 B への写像 f とは,A の任意の要素 a に対して B のある要素 b を対応させる規則のことであり,

\displaystyle{
f : A \to B
}

で表す。 a に対応する要素 b は f(a) で表す。

A を f の定義域,B を f の値域という。

Aiは属性名(属性)で、Diは各属性のドメイン(定義域)。

A1からAnの属性名の集合が、D1からDnの和集合の写像であるとしている。

ja.wikipedia.org

継続的デリバリー(Continuous Delivery, CD)について

継続的デリバリー(CD)とはなにか?

根本は アジャイル宣言の背後にある原則 になるかと思います。

顧客満足を最優先し、価値のあるソフトウェアを早く継続的に提供します。

Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.

agilemanifesto.org から引用

書籍 継続的デリバリー でもこの部分を引用して本のタイトルをつけたと書いてあります。

さらにClean Agileからも引用してみます。

変更するたびに本番環境にコードをリリースするプラクティス

Clean Agile p88より

なるほど、わかりやすい。

Continuous Delivery Foundation (CDF)の定義も見てみます。

CD is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time.

CDは、チームが短いサイクルでソフトウェアを生産し、いつでも確実にソフトウェアをリリースできるようにするソフトウェアエンジニアリングのアプローチです。

github.com

コード、ソフトウェアという言葉が多く見受けられるが、データのリリースはどうなのだろうか?という疑問が若干わきます。

自分の中では価値を提供する変更のデリバリーであれば全部含むという認識でいるので、データのリリースも含めて考えます。

(ゲームでいうマスターデータとかの話)

継続的にという言葉の通り連続することが重要なのですが、それぞれの間隔を長くすることは無意味なので、デリバリーする間隔を短くするプラクティスということが暗黙的にあります。

コードの変更から本番環境へのリリースの間隔を短くしていく取り組みとも言えます。

なぜCDを行うのか?

リリースの間隔が短くリリース頻度が多いチームは逆のチームに比べて、平均修復時間が小さいこと、変更失敗率が低いことが調査でわかっています。

下記を参照のこと

www2.slideshare.net

speakerdeck.com

LeanとDevOpsの科学

ここで注目したいのは、加速化を推進してもパフォーマンス改善以外の項目に対してトレードオフが発生しないということです。(LeanとDevOpsの科学 p27あたり)

リリースを頻繁に行うためには、下記の取り組みが必要になってきます。

  • リリースに伴う各ステップのリードタイムを短くする
  • リリース単位を小さくする

これらの取り組みの結果、最終的にパフォーマンスがよくなります。

CDを行うための準備

プロセスを整理する

コードの変更、コードのpush、テスト、PR、マージ、deployのstepにおいて、どのような処理を行うのかなどを整理し、自動化をできるように整備します。

自動化の取り組み

継続的にそして、素早くデリバリするために各ステップの自動化は必須です。

自動化としては下記が挙げられると思います。

  • ユニットテストの自動化
  • ビルドの自動化
  • 受け入れテストの自動化
  • リリースの自動化

現状の分析

構成管理やリリース管理の成熟度

継続的デリバリー p487 に成熟とのレベルの定義があるのでこれで分析してみましょう

  • レベル3 : 最適化 プロセスの改善に注力する

  • レベル2 : 定量的な管理 プロセスが計測可能で制御されている

  • レベル1 : 一貫している 自動化されたプロセスがアプリケーションのライフサイクルに適用される

  • レベル0 : 繰り返し可能 プロセスは文書化され、一部は自動化されている

  • レベル-1 : リグレッションエラー多発 プロセスは繰り返せず管理も貧弱、そして対処療法を行っている

これらを使って分析し、step by stepで対応していくのがよいでしょう。

自分のプロジェクトを分析した結果を残しておきます。

ラクティス ビルド管理および
継続的インテグレーション
テスト データ管理 環境およびデプロイメント
レベル2
ビルドメトリクスを収集して可視化し、
それに基づいて作業する。
ビルドを壊れたままにしない
レベル2くらい
本番環境への変更の取り消しは滅多に発生しない
問題があればすぐに見つかり、すぐに修正される。
非機能要件の定義は甘い
受け入れテストは自動化されていない。
レベル2くらい
データベースの更新やロールバックはデプロイのたびにテストされる。
データベースのパフォーマンスを管理、最適化する。
レベル1くらい?
一部の環境ではデプロイを自動化する。
新しい環境は手軽に作成する。
全ての構成情報を外に出してバージョン管理できてる
全ての環境に対して同じ手順でデプロイする
ボタンを押すだけでは完結していない。。

今できてないことは、受け入れテストの自動化、デプロイメントの自動化になります。

自分たちの課題の分析

受け入れテストの自動化

QAチームで今は手動テストを行っている。

シフトレフトしていきたいが取り組みとしては滞っている。

機能テストをよりリッチにしていくなども考えている。

受け入れテストの自動化ができていないことがデプロイの自動化に踏み込めない原因でもある

デプロイの自動化

本番環境へのデプロイ環境への自動化はできていない。(検証環境はできている)

手順はこんな感じでやっている

  1. Docker imageはmasterにmergeされると全部buildされてpushされている
  2. QAはどのimageを使うかを選んで反映しておく。
  3. QAチームからサインオフがでる *ここでDocker imageのハッシュ値が決まる
  4. 本番環境のdeployサーバーにsshする
  5. deployコマンドを打つ
    • この中で DB schemaの変更を行う専用のPodのimageを先に更新して、このPodに入ってスクリプトと叩く
    • kubectl apply(をラップしたコマンド)でimageを更新を含むkubernetesの更新を行う。

自動化できていない原因は下記の通り

受け入れテストの整備

反映後の受け入れテストの自動テストが整備されていないため切り戻しが自動でできない。

DBのschemaアプライ

DB schemaのアプライが同期的に実行できない場合もあるので、ここを順々に実行する方法を探している

だた、基本的には後方互換性を担保して開発しているので問題が起きにくい状態ではある。。

監査、RBAK

特に操作ログの保持が難しい。(改ざんをどう防ぐかとか)

このような分析をもとに次につなげていく。

さらに少し考えてみた

大規模サービスにおいて、継続的デリバリをするのであれば、継続的デリバリの中からデータベースの管理は切り離さないとだめだと思う。

データベースのバージョン管理はしつつ、デリバリする際にバージョンが該当のものでなければ止めるという制御を入れる。

ALTERとかカラム追加で時間がダウンタイムが発生する場合、デリバリするタイミングで気がつくとそれはもう手遅れなので前もって気がつくのがいいが、デリバリを止められる仕組みさえあればいい。

と考えてみたが、継続的デリバリ12章に理想が書いてあった。。

受け入れテストまで整備するべきかどうかもあるけど、正直エラーがあったら切り戻すで割り切らないと多分一生できん気がする

Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databasesを読む(その4の補足資料)

MySQLは8.0.19を使っています。

LSN

LSNとは Log Sequence Number の略で、単調増加する値で、redoログに書き込まれたバイト数分だけLSNが増えます。

dev.mysql.com

MySQLでは SHOW ENGINE INNODB STATUS でLSNを確認できます。

---
LOG
---
Log sequence number          137326682480
Log buffer assigned up to    137326682480
Log buffer completed up to   137326682480
Log written up to            137326682480
Log flushed up to            137326682480
Added dirty pages up to      137326682480
Pages flushed up to          137326682480
Last checkpoint at           137326682480
13 log i/o's done, 0.00 log i/o's/second

これらの値は、下記で定義されています。

github.com

INSERTするときのLSNが増える様子を示します。

SQL LSN comments
---
LOG
---
Log sequence number 137326682480
Log buffer assigned up to 137326682480
Log buffer completed up to 137326682480
Log written up to 137326682480
Log flushed up to 137326682480
Added dirty pages up to 137326682480
Pages flushed up to 137326682480
Last checkpoint at 137326682480
13 log i/o's done, 0.00 log i/o's/second
BEGIN; ---
LOG
---
Log sequence number 137326682480
Log buffer assigned up to 137326682480
Log buffer completed up to 137326682480
Log written up to 137326682480
Log flushed up to 137326682480
Added dirty pages up to 137326682480
Pages flushed up to 137326682480
Last checkpoint at 137326682480
13 log i/o's done, 0.00 log i/o's/second
BEGINではLSNは増えない
INSERT INTO innodb_auto_increment_small VALUES(); ---
LOG
---
Log sequence number 137326682671
Log buffer assigned up to 137326682671
Log buffer completed up to 137326682671
Log written up to 137326682671
Log flushed up to 137326682671
Added dirty pages up to 137326682671
Pages flushed up to 137326682671
Last checkpoint at 137326682671
17 log i/o's done, 0.36 log i/o's/second
COMMIT; ---
LOG
---
Log sequence number 137326682878
Log buffer assigned up to 137326682878
Log buffer completed up to 137326682878
Log written up to 137326682878
Log flushed up to 137326682878
Added dirty pages up to 137326682878
Pages flushed up to 137326682878
Last checkpoint at 137326682878
19 log i/o's done, 0.13 log i/o's/second

トランザクション中でもLSNは増加します。

このあたりはredoログの実装周りを見ればよいかなと思います。

dev.mysql.com

MTR

ごく僅かな一連のデータベージへの変更を記録したもの。

redoログは512バイトのブロックの連続で、個々のMTRはブロックをまたいで記録されることもある。

dev.mysql.com

(詳解 MySQL5.7 p 126)

AuroraのLSN関連の概念

Name Full Name description
VCL Volume Complete LSN すべてのログレコードの可用性を保証できる一番大きいLSN
SCL Segment Complete LSN セグメントの中の最大のLSN、セグメントの穴を探すのに使われる
PGCL Protection Group Complete LSN PG内の最大のLSN
CPLs Consistency Point LSNs 一つのMTRのなかの最後のログレコードのLSN
VDL Volume Durable LSN VCLより小さいが最も大きいCPLMTRが完了したことを示している
PGMRPL Protection Group Min Read Point LSN データ読み込済みのPGごとの最小のLSN

ストレージの一貫性のポイントの例

f:id:Spring_MT:20210322162847p:plain

書き込み、Commitをする場合

f:id:Spring_MT:20210323040453p:plain f:id:Spring_MT:20210323040611p:plain

最後は、最新のVDLがトランザクションのコミットLSN以上になったのでクライアントにackを送る。

読み込み

f:id:Spring_MT:20210323162524p:plain

read replica

f:id:Spring_MT:20210323174517p:plain

Recovery

f:id:Spring_MT:20210324165018p:plain f:id:Spring_MT:20210324165046p:plain

Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databasesのまとめ

Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases の翻訳まとめページ

https://www.allthingsdistributed.com/files/p1041-verbitski.pdf

翻訳内容

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

spring-mt.hatenablog.com

Auroraについて

mrasu.hatenablog.jp

qiita.com

www.slideshare.net

https://pages.awscloud.com/rs/112-TZM-766/images/B3-05.pdf

https://pages.awscloud.com/rs/112-TZM-766/images/B3-06.pdf

https://pages.awscloud.com/rs/112-TZM-766/images/D2-05.pdf

dev.classmethod.jp

www.slideshare.net

speakerdeck.com

www.slideshare.net

dev.classmethod.jp

aws.amazon.com

その他参考

www.slideshare.net

qiita.com

www.planetscale.com

speakerdeck.com

Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databasesを読む(その9 CONCLUSION)

9 CONCLUSION

Auroraは,クラウドの環境で、可用性も耐久性も妥協しない、高スループットのOLTPデータベースとして設計した。

この大きなアイデアは、伝統的なデータベースのモノリシックなアーキテクチャからの脱却と、ストレージをコンピュートの分離であった。

特に、ログやストレージを管理するデータベースの重要な部分の下位1/4を、独立したスケーラブルな分散型サービスに移行した。

すべてのI/Oがネットワーク越しに行われるため、主な制約はネットワークになった。

そのため、ネットワークの負担を軽減し、スループットを向上させる技術に注力した。

私たちは、下記に依存している。

  • クオラムモデル
    • 大規模なクラウド環境で発生する複雑で相関性のある障害をうまく処理し、外れ値のパフォーマンスペナルティを回避する
  • ログ処理
    • 集約されたI/Oの負担を軽減する
  • 非同期的な合意
    • 通信が多くでコストが掛かる多相同期プロトコル(XAとかのことかな)、オフラインでのクラッシュリカバリ、分散ストレージのチェックポイント作成を排除する

これらのアプローチは、複雑さを減らしたシンプルなアーキテクチャを実現し、拡張性に優れているだけでなく、将来の進歩のための基盤となっている。

Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databasesを読む(その7 LESSONS LEARNED)

7 LESSONS LEARNED

ここでは、クラウドで一般的なシナリオとそれに求める期待にフォーカスして、新たな方向性を導き出す。

7.1 マルチテナンシーとデータベースの統合

AWSのユーザーの多くは、SaaSビジネスを展開している。

SaaSでは、一般的にschema/databaseをテナントの単位として、異なる顧客を単一のインスタンスにまとめている。

すべての顧客が一度にアクティブになることはないので、顧客ごとに専用のインスタンスを購入する必要がないので、コストとの削減ができている。

(このモデルは、Salesforce.com のような有名なマルチテナントアプリケーションとは大きく異なる。Salesforce.comでは、マルチテナント・データ・モデルを使用し、複数の顧客のデータを単一のスキーマで統一されたテーブルにまとめ、テナントは行ごとに識別される。)

その結果、多数のテーブルを含むデータベースになる。

小規模なデータベースであっても、150,000テーブルを超える場合もよくある。

これは、dictionaryキャッシュなどのメタデータを管理するコンポーネントに負担がかかる。

さらに重要なのは、このようなお客様が必要としているのは、

  1. 高レベルのスループットと多くの同時接続を維持すること
  2. データが使用されたときにのみプロビジョニングされ、支払いが行われるモデル、
  3. ジッターの低減( 一つのテナントのスパイクが他のテナントに与える影響を最小限になる)

Auroraはこれらをサポートしており、このようなSaaSアプリケーションに非常に適している。

7.2 同時接続が多い状態でのオートスケーリング

突然の予期せぬイベントによるトラフィックのスパイクに対応する必要がある。

ある大手のお客様は、データベースに負荷をかけることなく、通常のピークのスループットを大幅に超えるスパイクが発生した。

このようなスパイクに耐えられるためには、データベースは同時接続の増大をうまくハンドリングすることが重要になる。

Auroraでは、基盤となるストレージシステムが非常にスケーラブルなので、このアプローチは実現可能である。

Auroraのユーザーの中には、毎秒8000以上の接続がある人もいる( per instanceだと思うけどインスタンスサイズの記載がない )

7.3 スキーマの進化

Ruby on Railsのような最新のWebアプリケーションフレームワークは、ORMと深く結合している。

その結果、アプリケーション開発者は簡単にかつ頻繁にデータベースのスキーマを変更できる。

MySQLは自由なスキーマ変更ができる仕組みを提供しているが、殆どのスキーマ変更の実装はテーブルのfullコピーが前提のため、スキーマの変更は辛いものである。

これは実際的な問題なので、Auroraでは効率的なオンライン DDL を実装した。

この実装は下記の通り

  1. ページ単位でスキーマをバージョン管理し、スキーマ履歴を使って個々のページを必要に応じてデコードする
  2. modify-on-write (書き込み時に修正するCoWのもじりかな。。。)を使用して個々のページを最新のスキーマに遅延アップグレードする

dev.classmethod.jp

blog.father.gedow.net

7.4 可用性とソフトウェアのアップグレード

ユーザーはクラウドネイティブなデータベースに高い期待を寄せていますが、それはAWSインスタンス群の運用やサーバーへのパッチ適用の頻度と相反することがある。

ユーザーはAuroraを主に本番アプリケーションを支えるOLTPサービスとして使用しているの、中断が発生するとそれはトラウマを引き起こす。

多くのユーザーは、たとえ6週間に1度30秒程度の計画ダウンタイムであっても、私たちが行うデータベースソフトウェアのアップデートに対してひどく脆弱である。

なので、AuroraではZDP(Zero Downtime Patch)機能をリリースした。

これにより、動作中のデータベース接続に影響を与えることなく、パッチを適用することができる。

図12に示すように、ZDPは、アクティブなトランザクションがない瞬間を探し、その瞬間にアプリケーションの状態をローカルのエフェメラルストレージに一時的に保存し、データベースエンジンにパッチを当てた後、アプリケーションの状態を再ロードするという仕組みになっている。

スプーリング - Wikipedia

このプロセスでは、ユーザー・セッションはアクティブなままで、エンジンが変更されたことに気がつくことはない。

f:id:Spring_MT:20210317174302p:plain

docs.aws.amazon.com