From e14709dc027f631753fc389a40f6e26faa90afbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Mon, 1 May 2017 17:24:16 +0200 Subject: [PATCH] Remove Lock component --- components/lock.rst | 258 -------------------------------------------- 1 file changed, 258 deletions(-) delete mode 100644 components/lock.rst diff --git a/components/lock.rst b/components/lock.rst deleted file mode 100644 index cf9c174781a..00000000000 --- a/components/lock.rst +++ /dev/null @@ -1,258 +0,0 @@ -.. index:: - single: Lock - single: Components; Lock - -The Lock Component -================== - - The Lock Component creates and manages `locks`_, a mechanism to provide - exclusive access to a shared resource. - -.. versionadded:: 3.3 - The Lock component was introduced in Symfony 3.3. - -Installation ------------- - -You can install the component in 2 different ways: - -* :doc:`Install it via Composer ` (``symfony/lock`` on `Packagist`_); -* Use the official Git repository (https://github.com/symfony/lock). - -.. include:: /components/require_autoload.rst.inc - -Usage ------ - -Locks are used to guarantee exclusive access to some shared resource. In -Symfony applications, you can use locks for example to ensure that a command is -not executed more than once at the same time (on the same or different servers). - -In order to manage the state of locks, a ``Store`` needs to be created first -and then use the :class:`Symfony\\Component\\Lock\\Factory` class to actually -create the lock for some resource:: - - use Symfony\Component\Lock\Factory; - use Symfony\Component\Lock\Store\SemaphoreStore; - - $store = new SemaphoreStore(); - $factory = new Factory($store); - -Then, a call to the :method:`Symfony\\Component\\Lock\\LockInterface::acquire` -method will try to acquire the lock. Its first argument is an arbitrary string -that represents the locked resource:: - - // ... - $lock = $factory->createLock('pdf-invoice-generation'); - - if ($lock->acquire()) { - // The resource "pdf-invoice-generation" is locked. - // You can compute and generate invoice safely here. - - $lock->release(); - } - -If the lock can not be acquired, the method returns ``false``. The ``acquire()`` -method can be safely called repeatedly, even if the lock is already acquired. - -.. note:: - - Unlike other implementations, the Lock Component distinguishes locks - instances even when they are created for the same resource. If a lock has - to be used by several services, they should share the same ``Lock`` instance - returned by the ``Factory::createLock`` method. - -Blocking Locks --------------- - -By default, when a lock cannot be acquired, the ``acquire`` method returns -``false`` immediately. To wait (indefinitely) until the lock -can be created, pass ``true`` as the argument of the ``acquire()`` method. This -is called a **blocking lock** because the execution of your application stops -until the lock is acquired. - -Some of the built-in ``Store`` classes support this feature. When they don't, -they can be decorated with the ``RetryTillSaveStore`` class:: - - use Symfony\Component\Lock\Factory; - use Symfony\Component\Lock\Store\RedisStore; - use Symfony\Component\Lock\Store\RetryTillSaveStore; - - $store = new RedisStore(new \Predis\Client('tcp://localhost:6379')); - $store = new RetryTillSaveStore($store); - $factory = new Factory($store); - - $lock = $factory->createLock('notification-flush'); - $lock->acquire(true); - -Expiring Locks --------------- - -Locks created remotely are difficult to manage because there is no way for the -remote ``Store`` to know if the locker process is still alive. Due to bugs, -fatal errors or segmentation faults, it cannot be guaranteed that ``release()`` -method will be called, which would cause the resource to be locked infinitely. - -The best solution in those cases is to create **expiring locks**, which are -released automatically after some amount of time has passed (called TTL for -*Time To Live*). This time, in seconds, is configured as the second argument of -the ``createLock()`` method. If needed, these locks can also be released early -with the ``release()`` method. - -The trickiest part when working with expiring locks is choosing the right TTL. -If it's too short, other processes could acquire the lock before finishing the -job; it it's too long and the process crashes before calling the ``release()`` -method, the resource will stay locked until the timeout:: - - // ... - // create an expiring lock that lasts 30 seconds - $lock = $factory->createLock('charts-generation', 30); - - $lock->acquire(); - try { - // perform a job during less than 30 seconds - } finally { - $lock->release(); - } - -.. tip:: - - To avoid letting the lock in a locking state, it's recommended to wrap the - job in a try/catch/finally block to always try to release the expiring lock. - -In case of long-running tasks, it's better to start with a not too long TTL and -then use the :method:`Symfony\\Component\\Lock\\LockInterface::refresh` method -to reset the TTL to its original value:: - - // ... - $lock = $factory->createLock('charts-generation', 30); - - $lock->acquire(); - try { - while (!$finished) { - // perform a small part of the job. - - // renew the lock for 30 more seconds. - $lock->refresh(); - } - } finally { - $lock->release(); - } - -Available Stores ----------------- - -Locks are created and managed in ``Stores``, which are classes that implement -:class:`Symfony\\Component\\Lock\\StoreInterface`. The component includes the -following built-in store types: - - -============================================ ====== ======== ======== -Store Scope Blocking Expiring -============================================ ====== ======== ======== -:ref:`FlockStore ` local yes no -:ref:`MemcachedStore ` remote no yes -:ref:`RedisStore ` remote no yes -:ref:`SemaphoreStore ` local yes no -============================================ ====== ======== ======== - -.. _lock-store-flock: - -FlockStore -~~~~~~~~~~ - -The FlockStore uses the file system on the local computer to create the locks. -It does not support expiration, but the lock is automatically released when the -PHP process is terminated:: - - use Symfony\Component\Lock\Store\FlockStore; - - // the argument is the path of the directory where the locks are created - $store = new FlockStore(sys_get_temp_dir()); - -.. caution:: - - Beware that some file systems (such as some types of NFS) do not support - locking. In those cases, it's better to use a directory on a local disk - drive or a remote store based on Redis or Memcached. - -.. _lock-store-memcached: - -MemcachedStore -~~~~~~~~~~~~~~ - -The MemcachedStore saves locks on a Memcached server, it requires a Memcached -connection implementing the ``\Memcached`` class. This store does not -support blocking, and expects a TTL to avoid stalled locks:: - - use Symfony\Component\Lock\Store\MemcachedStore; - - $memcached = new \Memcached(); - $memcached->addServer('localhost', 11211); - - $store = new MemcachedStore($memcached); - -.. note:: - - Memcached does not support TTL lower than 1 second. - -.. _lock-store-redis: - -RedisStore -~~~~~~~~~~ - -The RedisStore saves locks on a Redis server, it requires a Redis connection -implementing the ``\Redis``, ``\RedisArray``, ``\RedisCluster`` or -``\Predis`` classes. This store does not support blocking, and expects a TTL to -avoid stalled locks:: - - use Symfony\Component\Lock\Store\RedisStore; - - $redis = new \Redis(); - $redis->connect('localhost'); - - $store = new RedisStore($redis); - -.. _lock-store-semaphore: - -SemaphoreStore -~~~~~~~~~~~~~~ - -The SemaphoreStore uses the `PHP semaphore functions`_ to create the locks:: - - use Symfony\Component\Lock\Store\SemaphoreStore; - - $store = new SemaphoreStore(); - -.. _lock-store-combined: - -CombinedStore -~~~~~~~~~~~~~ - -The CombinedStore is designed for High Availability applications because it -manages several stores in sync (for example, several Redis servers). When a lock -is being acquired, it forwards the call to all the managed stores, and it -collects their responses. If a simple majority of stores have acquired the lock, -then the lock is considered as acquired; otherwise as not acquired:: - - use Symfony\Component\Lock\Strategy\ConsensusStrategy; - use Symfony\Component\Lock\Store\CombinedStore; - use Symfony\Component\Lock\Store\RedisStore; - - $stores = []; - foreach (array('server1', 'server2', 'server3') as $server) { - $redis= new \Redis(); - $redis->connect($server); - - $stores[] = new RedisStore($redis); - } - - $store = new CombinedStore($stores, new ConsensusStrategy()); - -Instead of the simple majority strategy (``ConsensusStrategy``) an -``UnanimousStrategy`` can be used to require the lock to be acquired in all -the stores. - -.. _`locks`: https://en.wikipedia.org/wiki/Lock_(computer_science) -.. _Packagist: https://packagist.org/packages/symfony/lock -.. _`PHP semaphore functions`: http://php.net/manual/en/book.sem.php