LASSIC Media らしくメディア
分散ロックとは|複数サーバでの排他制御
複数のサーバで動くシステムで、同じ在庫を二重に引き当ててしまった。あるいは、同じ夜間バッチが二重に走ってしまった——。サーバを複数台に増やして処理を分散させると、こうした「同時に同じものを触ってしまう」トラブルに悩まされることがあります。これを防ぐ仕組みが「分散ロック」です。複数のサーバがひとつの資源を奪い合わないよう、共有の「鍵」を一度に一つだけ持たせて、順番に処理させる——そんな交通整理の役割を果たします。
専門的な用語ですが、考え方は「鍵はひとつ、持てるのは一人」という、身近なたとえで捉えられます。本記事では、システムの企画や運用に関わる情報システム部門の担当者に向けて、分散ロックとは何か、ふつうのデータベースのロックとどう違うのか、どんな場面で要るのか、注意点や外注の勘所を整理します。
目次
分散ロックとは——鍵はひとつ、持てるのは一人
分散ロックとは、複数のサーバやサービスにまたがる環境で、同じ資源を同時に触られないよう、順番を守らせる仕組みを指します。ここでいう資源とは、在庫の数、ファイル、あるいは「この処理は一度だけ動かしたい」といった対象のことです。ポイントは、みんながアクセスできる場所に「鍵」をひとつだけ置いておき、その鍵を取れたサーバだけが処理を進められる、という約束にあります。鍵を取れなかったサーバは、順番が来るまで待つ。こうして、同時に触ってしまう事故を防ぐわけです。
身近なたとえでいえば、会議室の使い方に似ています。部屋の鍵はひとつだけ。その鍵を持っている人だけが部屋を使え、ほかの人は空くのを待ちます。鍵がなければ、二組が同じ部屋で鉢合わせしてしまうかもしれません。分散ロックも、これと同じ発想です。多くの場合、この「鍵置き場」には、すばやく読み書きできるRedisのようなデータストアやZooKeeperといった仕組みが使われます。とはいえ、利用する側が意識すべきは、道具の名前よりも「鍵はひとつ、持てるのは一人」という考え方のほうでしょう。
この記事のポイント
- 分散ロックは、複数のサーバが同じ資源を同時に触らないよう、共有の鍵で順番を守らせる仕組みです。
- ひとつのデータベース内の排他制御とは異なり、サーバやサービスをまたいで効きます。
- 鍵の有効期限や解放漏れ、鍵置き場の停止といった難所があり、冪等な設計との併用が現実的です。
単一データベースのロックとの違い
「ロック」という言葉は、データベースの世界でもよく使われます。分散ロックと混同されがちなので、違いを押さえておきましょう。全体像は図のとおりです。
ひとつのデータベースの中で、同じデータを同時に更新させないための工夫が、楽観ロックと悲観ロックです。これらは、そのデータベースが面倒を見てくれる範囲、つまり「ひとつの箱の中」での排他制御にあたります。ところが、システムを複数のサーバに分けて動かすと、話が変わってきます。処理があちこちのサーバで並行して走るため、ひとつのデータベースのロックだけでは、サーバをまたいだ同時実行までは抑えきれないのです。そこで登場するのが分散ロックです。データベースの外側、みんなが見に行ける共有の場所に鍵を置くことで、どのサーバから来ても「順番はひとつ」を守らせます。要するに、単一データベースのロックが「箱の中」の交通整理なら、分散ロックは「箱をまたいだ」交通整理だ、と捉えると分かりやすいでしょう。
どんな場面で要るのか
分散ロックが要るのは、「複数のサーバが動いていて、かつ、同じことが同時に起きると困る」場面です。代表的なところを見ていきます。ひとつは、在庫や残高のように、数を正確に保ちたい処理です。複数のサーバが同時に在庫を引き当てると、実際より多く売ってしまう、といった事故が起こりえます。もうひとつは、「一度だけ動かしたい処理」です。たとえば、複数台で動く仕組みのなかで、夜間の集計バッチを一度だけ走らせたい、定期処理が重複しないようにしたい、といった場面が挙げられます。鍵を取れた一台だけが実行するようにすれば、二重起動を避けられるのです。逆にいえば、サーバが一台しかない場合や、同時に起きても支障のない処理では、分散ロックは要りません。仕組みが増えるほど運用も複雑になるため、本当に必要な場面を見極めて使うことが肝心です。
基本の流れ
分散ロックの動きは、三つの段階で捉えられます。手順を整理しました。
| 段階 | すること | ねらい |
|---|---|---|
| ① 鍵を取る | 共有の場所で鍵の取得を試みる | 自分が処理してよいか確かめる |
| ② 処理する | 鍵を持っている間だけ資源を扱う | ほかと重ならず進める |
| ③ 鍵を返す | 処理を終えたら鍵を解放する | 次の処理へ順番を渡す |
まず、共有の鍵置き場で鍵の取得を試みます。取れれば処理に進み、取れなければ、空くまで待つか、いったん諦めて後で試すか、という判断になるでしょう。次に、鍵を持っているあいだだけ、目的の資源を扱います。この間はほかのサーバが割り込めないため、危なげなく処理を進められるわけです。そして最後に、処理を終えたら鍵を返します。返し忘れると次の順番が回らなくなるため、この解放は欠かせないのです。三つの段階のどれも大切ですが、とりわけ「きちんと鍵を返すこと」が、分散ロックを安定して運用する勘どころになります。
つまずきやすい難所
分散ロックは便利な一方で、扱いを誤るとかえって厄介です。あらかじめ知っておきたい難所を挙げます。一つ目は、鍵の返し忘れです。処理の途中でサーバが落ちるなどして鍵が返されないと、その鍵は誰にも取れなくなり、以後の処理が止まってしまいます。これを避けるため、鍵に「有効期限(TTL)」を設けて、一定時間で自動的に外れるようにするのが定石です。二つ目は、その有効期限の長さの見極めです。短すぎると処理の途中で鍵が外れ、長すぎると障害時の待ちが延びます。処理時間に見合った設定が要ります。三つ目は、鍵置き場そのものが止まるリスクです。鍵を預かる仕組みが単一だと、そこが停止すれば全体が止まりかねません。四つ目は、万全の保証は難しい、という前提です。ネットワークの遅延やサーバ間の時計のずれなどにより、まれに二重に処理が走る可能性は残ります。だからこそ、同じ処理が二度実行されても結果が変わらない冪等な設計と組み合わせておくと、より心強いといえます。
外注時に確認しておきたい点
分散ロックの実装や設計を外部に委託する場合は、次の点をすり合わせておくと、認識のずれを防ぎやすくなります。まず、そもそも分散ロックが要る場面なのか、という見極めです。サーバが一台で足りる、あるいは競合状態が起きても支障がないなら、無理に導入する必要はありません。仕組みを増やせば運用は複雑になるため、本当に要るのかを一緒に確かめたいところです。ここが曖昧なまま作り込むと、必要以上に手のかかるシステムになりかねません。
次に、難所への備えです。鍵の有効期限をどう決めるか、鍵置き場が止まったときにどう振る舞うか、そして二重実行が起きても問題が出ないよう冪等な設計を併せるか——こうした「うまくいかないとき」の設計まで含めて相談できると、実運用で慌てずに済みます。あわせて、鍵置き場に何を使うのか、その運用や監視をどうするのかも決めておくとよいでしょう。仕組みの選定から、難所への備え、運用までを見通して設計してもらえると、任せたあとのつまずきを抑えやすくなります。
まとめ:分散ロックで押さえる3つの視点
分散ロックは、複数のサーバが同じ資源を奪い合わないよう、順番を守らせるための仕組みです。押さえておきたい視点は3つに整理できます。第一に、分散ロックは共有の鍵を一度に一つだけ持たせ、サーバやサービスをまたいで同時実行を防ぐものであり、ひとつのデータベース内で働く楽観ロック・悲観ロックとは、及ぶ範囲が違うこと。第二に、在庫の正確な管理や、処理を一度だけ動かしたい場面などで要る一方、サーバが一台なら不要であり、必要な場面を見極めて使うべきだということ。第三に、鍵の返し忘れや有効期限、鍵置き場の停止といった難所があり、万全の保証は難しいため、冪等な設計と組み合わせるのが現実的だということです。この3点を押さえておけば、「複数サーバでの同時処理」という悩みに、落ち着いて向き合えます。設計や実装に不安があれば、外部の手を借りるのも一つの選択肢です。
よくある質問
分散ロックと、データベースの楽観ロック・悲観ロックは違うのですか。
及ぶ範囲が異なります。楽観ロックや悲観ロックは、ひとつのデータベースの中で同じデータの同時更新を防ぐ仕組みです。分散ロックは、データベースの外側の共有の場所に鍵を置き、複数のサーバやサービスをまたいで順番を守らせます。単一の箱の中の交通整理か、箱をまたいだ交通整理か、という違いだと捉えてください。
どんなときに分散ロックが必要ですか。
複数のサーバが動いていて、同じことが同時に起きると困る場面で必要になります。在庫や残高の数を正確に保ちたい処理や、夜間バッチを一度だけ走らせたい処理などが代表例です。逆に、サーバが一台しかない場合や、同時に起きても支障のない処理では要りません。必要な場面を見極めて使うことが大切です。
鍵を返し忘れると、どうなりますか。
その鍵が誰にも取れなくなり、以後の処理が止まってしまうおそれがあります。処理の途中でサーバが落ちる場合などに起こりえます。これを避けるため、鍵に有効期限(TTL)を設け、一定時間で自動的に外れるようにするのが定石です。有効期限は、処理にかかる時間に見合った長さに調整する必要があります。
分散ロックがあれば、二重実行は防ぎきれますか。
すっかり防ぎきるのは難しいのが実情です。ネットワークの遅延やサーバ間の時計のずれなどにより、まれに二重実行が起きる可能性は残ります。そのため、同じ処理が二度実行されても結果が変わらない冪等な設計と組み合わせておくと、より心強いはずです。ロックだけに頼りきらない備えが現実的といえます。
鍵置き場には何を使うのですか。
すばやく読み書きでき、みんなが共有できるデータストアがよく使われます。代表的にはRedisのようなインメモリのデータストアや、ZooKeeperといった仕組みが挙げられます。ただ、利用する側がまず押さえるべきは、道具の名前よりも「鍵はひとつ、持てるのは一人」という考え方と、有効期限などの注意点のほうでしょう。
著者:テレリモ総研編集部 鈴木 亮佑
分散システムの設計・実装のご相談はLASSICへ
元請(プライムベンダー)として、分散ロックが要るかの見極めから、難所への備え・冪等な設計・運用まで、貴社のシステムに合わせてご提案します。まずはお気軽にご相談ください。
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 参考:Redis「Distributed Locks with Redis」(https://redis.io/docs/latest/develop/use/patterns/distributed-locks/)。分散ロックの一般的な解説の参考として。