Firebase Realtime Databaseとはなんなのか？

# Firebase Realtime Databaseとはなんなのか？

Firebase Realtime Databaseは操作は非常い簡単ですが、今までMySQLなどで設計していた人にはとっつきにくいです。
なぜなら、一般的にDatabase（MySQLなど）と呼ばれていたものが特性的にFirebase Realtime Databaseから遠い存在だからです。この特性について__Database__のことを少し掘り下げると、Firebase Realtime Databaseの特徴を理解し、扱いやすい__Database__に変わってくるはずです。
また、ここではDatabase単体の特性について言及する訳ではなく、クラウドシステム（分散システム）におけるDatabaseの特性を説明します。

---

### 結論
- __Firebase Realtime Databaseは一貫性を犠牲にすることで、可用性と分断耐性に優れたクラウドシステムである。__
    - CAP定理を全て満足したクラウドシステムは存在しない。
    - サービスを運用するためには、CAP定理からいずれかの特性を犠牲にして重要な特性を選択する必要がある。
    - Firebaseは一貫性を犠牲にすることでクラウドシステムとして重要な特性が備わっている。
    - 一貫性を犠牲にすると言っても、トランザクションの機能は提供されている。
    - Firebaseは緩やかな一貫性の上に成り立っている


- __クラウドシステムに接続されたモバイルアプリを運用する場合は、BASE特性を基に設計すべきである。__
    - 不安定な接続環境下では分断耐性が必須である。
    - 可用性がないことはユーザービリティーを損ねている。
    - 一貫性が必要なポイントは多くない。
    - Firebaseが提供するトランザクションはACID特性を持っているので一貫性保つことも可能。

※ `CAP定理` `一貫性` `可用性` `分断耐性` `BASE`については下記で説明します。

---

## クラウドシステムの基礎知識
なぜクラウド上でリレーショナルデータベースの実装は難しいのでしょう？
その理由はシステムの特性とトレードオフにあります。

クラウドシステムの特性はすでに偉い人（Eric Brewer）によって[提唱](https://people.eecs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf)されています。

---

#### ACID
リレーショナルデータベースは、「ACID」と呼ばれる特性を備えています。ACIDとはトランザクションに対する以下の4要件の頭文字を指します。

|性質|説明|
|---|---|
|Atomicity: 原子性|トランザクションが実行されるか、全くされないかのどちらかである。|
|Consistency: 一貫性|データベースの関係制約を保証する。|
|Isolation: 独立性|トランザクション中に経過が他トランザクションから参照出来ない。隔離性があるということ。|
|Durability: 永続性|トランザクション完了後、データは失われない。耐障害性があるということ。|

分散システムでACIDのCとIを実現しようとすると、それと引き替えに可用性や品質、性能が損なわれます。
またACIDと対をなす特性としてBASEがあります。

---

#### BASE
一方Firebaseは「BASE」と呼ばれる特性を備えています。

|性質|説明|
|---|---|
|Basically Available|可用性が高く、常に利用可能である。|
|Soft-State|ステータスは厳密ではない。外部から送られる情報により変化する。|
|Eventually Consistent|最終的には一貫性が保たれる。ある時点では更新されていないケースがある。（緩やかな一貫性）|

[Cloud技術的特徴について](http://qcontokyo.com/tokyo-2009/pdf/GeneralSession-Day2-Maruyama.pdf)

---

### CAP定理
```
CAP定理はブリュワーの定理とも呼ばれ、分散コンピュータシステム（クラウドシステム）のマシン間の情報複製に関する定理。
```
|定義| 説明　|
| --- | --- |
| 一貫性 (Consistency) | 単一の最新データを持っていること。 |
| 可用性 (Availability) | システムが継続して稼働できる能力のこと。 |
| 分断耐性 (Partition-tolerance) | ネットワーク上で分断が発生してもそれを許容する能力のこと。 |

分散システムはこの3つの保証のうち、同時に2つの保証を満たすことはできるが、同時に全てを満たすことはできません。

[CAP定理 - Wikipedia](https://ja.wikipedia.org/wiki/CAP%E5%AE%9A%E7%90%86)
![20151013140256.png](https://qiita-image-store.s3.amazonaws.com/0/80287/49a70926-d4a7-4648-42de-d3817a5f740d.png)

---

##### __一貫性＋可用性（CA）__

- 一部のシステムに障害が発生してもデータ一貫性が取れるシステム。
- ネットワーク分断が発生した際は、片方を切り捨てる

---

##### __可用性＋分断耐性（AP）__

- ネットワーク分断が発生しても、全てのノードがリクエストを受理し続ける
- 結果として更新前の古いデータを読み出してしまったり、分断されたグループ間でデータに相違が生じる可能性がある
- システム全体としての整合性を犠牲にする代わりに可用性を保つ
- 一定時間以内に一貫性を成立させるシステム(結果整合性; eventually consistent）を用いることが多い
- 3種の中ではこの方式が最も障害に強い

---

##### __一貫性＋分断耐性（CP）__

- ネットワーク分断が発生した場合、どれか1つのグループのみでリクエストを受理し、残りのグループは参照も更新もできないようにする
- 一部のグループの可用性を犠牲にする替わりにシステム全体として整合性を保つ

---

## クラウドシステムで起こりがちな問題

ややこしい定理は、なんとなく理解しておいて実際にどんな問題に我々は直面したことがあるか見てみましょう。
そして実際にその問題にFirebase Realtime Databaseであればどのように対処するのかを紹介します。

---

### コンフリクト
一貫性と可用性の問題です。
複数のユーザーから同じレコードに同時に書き込みがあった場合、一般的に`トランザクション`を行います。
トランザクションはレコードをロックすることで一貫性を保つ機能です。ロック中にリクエストがあった場合そのリクエストは失敗します。ことのきシステムは可用性を犠牲にしていることになります。

<img width="600" alt="スクリーンショット 2017-03-27 15.43.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/80287/749d0ea7-a599-5f7f-b10a-89fbed63ba1e.png">

MySQLでは一般的にレコードに対してUpdateを行います。複数のユーザーが同じレコードをUpdateしようした場合、どちらかのデータがいずれかのデータによって上書きされることになります。またトランザクションによりいずれかが失敗します。

Firebase Realtime Databaseではコンフリクトが起こらないリクエストをすることが可能です。

Firebaseの場合は次のようになります。Updateしたいノードを絞ってリクエストすることでロックを行わず値を更新します。また、`users.2.last_name`などの末端のノードでだけでなく`users.2`で以下のノードをロックしトランザクションで更新することも可能です。
<img width="500" alt="スクリーンショット 2017-03-27 16.06.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/80287/e0bbc169-5bf9-273d-3453-16344c4c989f.png">

---

### トンネル・地下鉄
これは分断耐性の問題です。サービスを運用する以上、ユーザーが通信環境の悪い場所に行くことは避けられません。
REST APIにサービス設計の場合、ネットワークが切れるとリクエストは失敗します。解決策は、ユーザーにリトライを促すことです。

Firebaseでは、ネットワーク接続再開された時に自動でリクエストを送信します。
リクエストをすると考えるより自動で同期していると考えた方がわかりやすいと思います。自動同期によって緩やかな一貫性が保たれています。

<img width="600" alt="スクリーンショット 2017-03-27 16.16.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/80287/c0ef5b46-59da-fe2f-b19b-54f0004ad3f9.png">

---

古い記事になりますが、__Cloud Firestore__もほぼ同じ特性を持っていると考えてもらって大丈夫です。

__参考資料__
[Firebase Realtime DBを実践投入するにあたって考えたこと](http://qiita.com/1amageek/items/64bf85ec2cf1613cf507)
[Firebase Cloud Functionsを使ってFacebook AccountKitをFirebase Authと連携する](http://qiita.com/1amageek/items/c7adbd9f2bbf3a57d352)

[クラウドでの新しいACID、そしてBASEトランザクションとCAP定理](http://www.publickey1.jp/blog/09/_basecap.html)
[CAP定理を見直す。](http://www.publickey1.jp/blog/13/capcap32.html)
[CAP定理, BASEのまとめ](http://shmachid.com/database/135/)
[CAP定理](http://portaltan.hatenablog.com/entry/2015/10/13/140331)
[分散システムの一貫性に関する動向について](https://techblog.yahoo.co.jp/architecture/2015-04-ditributed-consistency/)
[Towards Robust Distributed Systems](https://people.eecs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf)