Symfony Component Advent Calendar 2023の12日目の記事です。
処理をロック、"Lock"
Lockは、ある処理を重複して実行させない(排他処理)ようにします。Symfony以外でも使えます。
インストール
composer require symfony/lock
使い方
LockFactory
オブジェクトを使り、createLock('{ロック名}')
メソッドを実行してロックオブジェクトを取得します。'acquire()`メソッドでロックが取得できればtrueを返します。falseを返せば他で処理が実行されているということになります。
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\SemaphoreStore;
$store = new SemaphoreStore();
$factory = new LockFactory($store); // Factory作成
$lock = $factory->createLock('sample'); // ロック
if ($lock->acquire()) { // ロックされてない
// 排他処理したいロジック
$lock->release(); // ロック解除
} else { // ロックされてる
}
有効期限
createLock()
時にttlを渡すことで有効期限が設定できます。この際、同じく引数にautoRelease
を設定することで、処理が終わっても自動でロックを解除しないようにできます。(通常は自動でロック解除されます)
また、acquire(true)
と引数にtrueを渡すと、処理が終わるまで待機します。これをブロッキングと呼びます。
$memcached = new \MemCached();
$memcached->addServer('localhost', 11211);
$store = new MemcachedStore($memcached);
$factory = new LockFactory($store); // Factory作成
$lock = $factory->createLock(
'sample',
ttl: 30, // 有効期限(秒)
autoRelease: false // 自動で解除するか
);
if ($lock->acquire(true)) { // 別の処理でロックが解除されるまで待機
// 排他処理
}
共有ロック
ロックは共有ロックがあり、読み込みはできるけど書き込みはできないと言った処理が可能になります。acquireRead()
で読み込みロックを取得できます。書き込みロックにしたい場合は今まで通りacquire()
を呼び出します。いずれもブロッキングが可能です。
$lock = $factory->createLock('sample');
$lock->acquireRead(true); // 読み込みモードでロック取得。ブロッキングなので他のロックが解除されるまで待機
// 読み込み時にやりたい処理
$lock->aquire(true); // 書き込みモードに変更。同じくブロッキング
// 書き込みモードでやりたい処理
$lock->relase();
ストア
ロックはStore
と呼ばれる箇所にロック情報が作成されます。このStore
により、できることが変わってくるのでシーンに合わせたStore
を選択する必要があります。
Store | Scope | Blocking | Expiring | Sharing |
---|---|---|---|---|
FlockStore | local | yes | no | yes |
MemcachedStore | remote | no | yes | no |
MongoDbStore | remote | no | yes | no |
PdoStore | remote | no | yes | no |
DoctrineDbalStore | remote | no | yes | no |
PostgreSqlStore | remote | yes | no | yes |
DoctrineDbalPostgreSqlStore | remote | yes | no | yes |
RedisStore | remote | no | yes | yes |
SemaphoreStore | local | yes | no | no |
ZookeeperStore | remote | no | no | no |
※MemcachedStoreはBlockingいけると思う
まとめ
今回はLock
でした。排他処理ではお世話になる機能ですが、ストアやサーバの構成などの設定を誤るとロックされない状況になるので、使う際は必ず本番環境(や同等の環境)で試してからお使いください。