同じリソース(口座、注文、在庫、バッチジョブなど)を複数のプロセスや複数のサーバーが同時に操作すると競合が発生します。 言語組み込みのミューテックスやセマフォは1つのプロセス内でのみ有効です — プロセスが複数あったり複数の サーバーに分かれていたりする場合は、プロセス境界を越える相互排他の手段が別途必要になります。
Ticketingはまさにこの問題、すなわちプロセス・サーバー境界を越える分散相互排他のためのロックサーバーとクライアント 群です。クライアントはTCPでロックサーバーに接続し、名前付きのキー(key)を取得(acquire)し、クリティカルセクションを 通過した後に解放(release)します。
Ticketingは、JSONではなく固定幅バイナリフィールドで構成されたフレームプロトコルを使用します。opを1バイトで ディスパッチした後、opごとの固定バイト長を読み取り、最後のkeyのみ改行(\n)まで読み取ります。パースは パースというよりオフセットの読み取りに近く、リクエストのたびにJSONをパースする方式よりオーバーヘッドが少なくなります。
ロックを取得するたびに、サーバーは単調増加するu64のフェンシングトークンを一緒に返します。保護対象のリソースが このトークンの単調性を検証するようにしておけば、leaseの失効後に遅れて動き出したクライアントがより低い トークンでアクセスしようとするのを拒否できます。その結果、ロックサーバー自体が常に完全に一貫していなくても 安全性を保つことができます — これは特にフェイルオーバー時に重要です。
サーバー1台だけでも動作しますが(シングルモード)、無停止運用が必要な場合は最小2台でクラスターを構成します。 クラスターは合意(クォーラム)ではなく優先順位ベースでアクティブを1台選出し、残りはリアルタイムでレプリケーションを 受け取るスタンバイになります。アクティブが停止した場合(再起動を含む)やgraceful終了した場合は、スタンバイが 引き継ぎます。詳しい動作は動作原理ページを参照してください。
同一のバイナリプロトコル上に、8言語の公式クライアントを提供しています: Rust、Java/Kotlin、JavaScript/TypeScript、 Python、C#、Go、Ruby、C/C++。言語ごとに、そのエコシステムに自然な方法でAPIを公開します — 例えば async/await系の言語では非同期に、Go/Ruby/Cではブロッキング+バックグラウンドスレッドで。プロトコルはすべての言語で バイト単位で同一です。言語ごとのインストール方法と例はライブラリページで確認してください。