トランザクション

Kii Cloud のデータ管理機能ではトランザクションをサポートしていないため、設計には工夫が必要です。

トランザクションは、データの一貫性を保持することを目的として、特にリレーショナルデータベース(RDB)でサポートされている機能です。Kii Cloud は、「NoSQL」と呼ばれる次世代データベースと同様に、スケーラビリティや高可用性を重視しているため、トランザクションをサポートしていません。そのため、このページに記載されている内容を考慮して、モバイルアプリの設計を工夫し、データの一貫性を保持する必要があります。

現バージョンの Kii Cloud ではトランザクションをサポートしないため、オンライン銀行のように、強固な一貫性を絶対的に確保しなければならないアプリケーションを構築することはおすすめできません。

トランザクションとは

トランザクションとは特定の目的を持つ複数の処理を、不可分の処理として扱う機能です。一貫性の観点からは、処理をアトミックに扱えることが重要な要件となります。アトミックな処理とは、関連する処理の結果がすべて成功するか、すべて失敗するかのいずれかをとり、一部だけが成功するような状態にならないことを意味します。

例として、銀行の口座間の振り込みを挙げます。振り込みを実現するには、2 つの口座の間で残高のマイナス操作とプラス操作を行いますが、それらはアトミックである必要があります。つまり、結果は両方が成功するか、両方が失敗するかのいずれかでなければなりません。もし、片方だけが成功すると、残高の消失などの問題が発生します。

RDB では、この問題に対処するため、トランザクション機能を利用できます。トランザクションの内部で実行された操作は、最終的にコミットまたはロールバックが選択できます。コミットを実行するとすべての操作は確定されます。ロールバックを実行するとすべての操作は取り消されます。

Kii Cloud ではリクエストごとに変更内容が確定します。上の例と同じ処理を Kii Cloud で実装した場合、処理中に通信圏外になると一貫性は失われてしまいます。同様の問題は、モバイルアプリの終了やユーザーによる処理の中断などでも起こりえます。モバイルアプリではこうした現象を考慮して、データ設計を行う必要があります。

一貫性確保のためのヒント

Kii Cloud では、様々な工夫によって、完全ではないまでも許容できる程度にまで一貫性を確保する必要があります。多くのサービスでは、口座間取引のような強固な一貫性が要求されることはそれほど多くありません。データの持ち方によって問題の発生を回避したり、再試行できるロジックにしたりすることによって、最終的な一貫性を確保できます。

ここでは、いくつかの方法をヒントとして示します。一般的な NoSQL データベースでも同様の設計技法が求められるため、ここに示したトピック以外でもさまざまな工夫を行うことができます。

サーバー機能拡張を利用する方法

サーバー機能拡張は、独自のコードを Kii Cloud のサーバー上で動作させる機能です。JavaScript で記述したプログラムによって、モバイルアプリと同様のモデルでサーバーコードを実行できます。

モバイルアプリで一貫性が崩れる最大の原因は、前述のようなネットワークエラーやアプリの終了によるものです。サーバー機能拡張を使うと、そのリスクを軽減できます。

次の実現例では、モバイルと Kii Cloud 間の通信 2 回を、サーバー機能拡張 1 回の呼び出しにしています。一旦リクエストを行うと、サーバー機能拡張はそのまま実行を続けるため、モバイル側の影響を受けません。

この方法では 一般的なモバイルアプリが要求する程度に、問題の発生頻度を下げる効果は期待できますが、次のような状況で処理が完全に実行できない可能性も残ります。

  • 突発的な事象により、サーバーでの処理がサーバー機能拡張に許可された最大実行時間を超えたとき。

  • サーバーのメンテナンス等でプロセスが突然終了したとき。

  • サーバー間での通信で予期しないエラーが発生したとき。

  • サーバーでの処理中に何らかの予期しない例外が発生したとき。

1 つのデータ単位を大きくする方法

KiiObject 1 件の更新ではアトミックな動作が期待できるため、できるだけ 1 つのオブジェクトに詰め込んでまとめて更新するほうがトラブルを避けられます。保存したいデータが KiiObject 1 個に格納できる程度のサイズに収まるなら、1 回の更新で状態をまとめて書き換える設計のほうが一貫性を確保しやすくなります。

通常、RDB ではできるだけ項目を正規化して、1 つのレコードでは 1 つの関係しか表現しないようにするのが定石でした。しかし、このような設計では、更新回数が増える傾向があるため、一貫性が失われる機会が増えてきます。

逆に Kii Cloud では、非正規化や、オブジェクト内での繰り返し構造/階層構造の採用によって、更新回数を少なくする工夫が有効です(ただし、データの非正規化により、更新の影響が複数のオブジェクトに及ぶことがあるため、モバイルアプリの機能性も検討する必要があります)。

たとえば、ゲームプレイヤーの情報を KiiObject に格納するときのデータ設計を考えます。1 人のプレイヤー(KiiUser)が、勇者、戦士、魔法使いという 3 人のキャラクターを操作できる場合、以下の 2 通りの設計が考えられます。一貫性の観点からは、一度で更新が行える設計 1 を採用した方が安全に更新できます。

設計 1:1 つの KiiObject に 3 キャラクター分のデータを格納する

設計 2:KiiObject ごとに 1 キャラクター分のデータを格納する

自動的に再試行できるように工夫する方法

再試行を前提としたロジックとしたり、更新順序を工夫したりして、問題のあるデータを自動的に回復できるように工夫します。つまり、一貫性が崩れる状態を前提として、矛盾の発見をエラー停止とするのではなく、自己修復するように実装することを検討します。

たとえば、2 つ KiiObject の間に双方向のリンクを生成したい場合、片方向しかリンクがないとき、双方向のリンクとして修復できるようなロジックにします。

このような問題は、いつどこで発生するか分からないため、実装は困難ですが、回復用の処理をまとめて一定のタイミングでチェックするなどの工夫により、ある程度の問題解決が望めます。