Locks
The Lock plugin provides exclusive and shared resource locks through RPC. Use it to coordinate access to a resource from multiple PHP workers.
Configuration
Omit the lock section or set driver: memory to use the in-memory backend. Each RoadRunner instance then keeps its own lock state.
Set driver: redis to share locks between RoadRunner instances:
lock:
driver: redis
config:
addrs: ["127.0.0.1:6379"]
username: ""
password: ""
db: 0
master_name: ""
sentinel_password: ""
pool_size: 0
dial_timeout: 5s
read_timeout: 5s
write_timeout: 5s
tls:
root_ca: ""
cert: ""
key: ""The Redis backend requires Redis 7 or later. It uses the go-redis v9 client.
A set master_name selects a failover client for any number of addresses. Without master_name, one address selects a standalone client, and two or more addresses select a cluster client. The db setting applies to a standalone client and to a failover client. A negative db is rejected at startup. A cluster client uses database 0 only. Without master_name, a non-zero db with more than one address is rejected at startup.
Set master_name to use Redis Sentinel. The addrs list then holds the Sentinel addresses. Set sentinel_password when the Sentinel nodes need their own password.
The lock backend accepts password-only Sentinel authentication. Its configuration does not include the sentinel_username option of the Redis KV driver. username and password authenticate against the Redis data nodes.
Set pool_size to size the connection pool for one Redis node. The client opens more connections when the pool is busy. The value 0 selects the go-redis default.
The dial_timeout, read_timeout, and write_timeout settings accept Go durations, such as 5s. Negative values are rejected at startup. Omitted timeouts use the Redis client defaults.
Add the tls block to connect with TLS. Remove the block for a plaintext connection. An empty root_ca selects the system root certificates. Set root_ca to the PEM file of a private certificate authority. Set cert and key together to send a client certificate. The backend reads the pair for each handshake, so a renewed certificate needs no restart. The minimum protocol version is TLS 1.2.
Write at least one key in the tls block. The configuration reader drops a block that has no keys, and the connection then stays plaintext. Write root_ca: "" for a server with a public certificate authority.
The backend does not accept some keys of the RoadRunner Redis plugin. The max_retries key is absent, because a retry after a lost reply reports contention for a lock that the caller now holds. The route_by_latency, route_randomly, and read_only keys are absent, because the lock script writes and must run on the master. The min_retry_backoff, max_retry_backoff, min_idle_conns, max_conn_age, pool_timeout, idle_timeout, and idle_check_freq keys are absent as well.
The lock section requires driver: memory or driver: redis. Invalid configuration and connection failures stop plugin initialization.
The backend stores lock state under the fixed rr:lock: key prefix. The resource name is the namespace. Give resources unique names when different applications share one Redis server. Redis server time controls expiration. Each read lock has its own TTL. A TTL of 0 creates a lock that remains until release.
Redis lock behavior
ForceReleaseremoves all locks on the resource. It returnsOk: trueonly if it removed at least one lock.Both backends refuse a second read lock with the same ID on the same resource. Use
UpdateTTLto extend a held lock.Contention, or an expired wait during an acquisition, returns
Ok: false.A failed Redis command, or a deadline that occurs during a Redis command, returns an RPC error. The lock state is then unknown. Call
ExistsorReleaseto find the state of the lock.A
waitof0on Redis makes one acquisition attempt, bounded byread_timeout, which is 5 seconds by default. The memory backend waits 1 millisecond instead.Stored locks stay in Redis after a RoadRunner restart until release or expiry.
For Release, ForceRelease, Exists, and UpdateTTL, Redis uses wait as the deadline for the command. These calls do not wait for lock contention. A deadline during the command returns an RPC error with an unknown result. All waiting acquisition calls in one RoadRunner instance share one Redis Pub/Sub connection.
PHP client
The RoadRunner lock plugin comes with a convenient PHP package that simplifies the process of integrating the plugin with your PHP application.
Installation
To get started, you can install the package via Composer using the following command:
Usage
After the installation, you can create an instance of the RoadRunner\Lock\Lock class, which will allow you to use the available class methods.
Here is an example:
The RoadRunner\Lock\Lock class provides four methods that allow you to manage locks:
Acquire lock
Attempts to acquire an exclusive lock on a resource. Set a positive waitTTL to wait for a conflicting lock to be released. The method returns a lock ID on success or false on failure. Check the result before accessing the protected resource.
The PHP SDK uses seconds for numeric ttl and waitTTL values. It converts these values to microseconds for RPC. In PHP SDK 1.0.x, waitTTL defaults to 0. The memory backend then uses a one-millisecond acquisition window. The Redis backend makes one acquisition attempt, bounded by read_timeout. Set waitTTL explicitly when you need a longer wait.
These calls show alternative arguments. Use the same success check and release handling for each call:
Acquire read lock
Attempts to acquire a shared lock on a resource. Multiple readers can hold shared locks. An exclusive acquisition must wait until all readers release their locks or its wait expires. Set a positive waitTTL to wait for an existing exclusive lock. lockRead() returns a lock ID on success or false on failure. The PHP time units and default wait are the same as for lock().
These calls show alternative arguments. Check each result before reading the resource:
Release lock
Releases an exclusive lock or read lock on a resource that was previously acquired by a call to lock() or lockRead().
Check lock
Checks if a resource is currently locked and returns information about the lock.
Update TTL
Replaces the remaining TTL with a new duration from the time the server applies the update. It does not add time to the previous expiry. Numeric PHP values use seconds. A shorter value can release the lock before the protected operation finishes. Check the update result. Stop accessing the resource if the update fails. Finish the operation or renew the lock before its TTL expires.
Symfony integration
Installation
You can install the package via composer:
Usage
Read more about using a Symfony Lock component here.
API
Protobuf API
To make it easy to use the Lock proto API in PHP, we provide a GitHub repository, that contains all the generated PHP DTO classes proto files, making it easy to work with these files in your PHP application.
RPC API
RoadRunner provides an RPC API, which allows you to manage locks in your applications using remote procedure calls. The RPC API provides a set of methods that map to the available methods of the RoadRunner\Lock\Lock class in PHP.
Raw RPC requests use microseconds for Request.ttl and Request.wait. For example, wait: 5000000 allows an acquisition wait of five seconds. An omitted or zero wait is not an unlimited wait. The memory backend then uses a one-millisecond acquisition window, and the Redis backend makes one acquisition attempt, bounded by read_timeout. PHP SDK arguments use seconds and are converted before the RPC call.
Lock, LockRead, and UpdateTTL accept ttl values from 0 to 9223372036854775 microseconds. All methods accept wait values in the same range. A value outside the range returns an RPC error and changes no lock state.
For Lock and LockRead, require Response.Ok == true before accessing the resource. A completed RPC call with no error can still return Ok == false, including when the acquisition wait expires.
Lock
Attempts to acquire an exclusive lock. If the resource has a conflicting lock, the call waits until that lock is released or the acquisition deadline expires. Check Response.Ok before entering the protected section.
LockRead
Attempts to acquire a shared lock. Readers can share the resource, but an existing exclusive lock prevents acquisition. The call waits until the conflict ends or the acquisition deadline expires. Check Response.Ok before reading the protected resource. An exclusive acquisition also has a finite wait when readers hold the resource.
Release
Releases an exclusive lock or a read lock on a resource that was previously acquired by a call to Lock or LockRead.
ForceRelease
Releases all locks on a resource, regardless of which process acquired them.
Exists
Checks if a resource is currently locked and returns information about the lock.
UpdateTTL
Replaces the remaining TTL with Request.ttl microseconds from the time the server applies the update. It does not add to the previous expiry. Check Response.Ok to detect a failed update.
Last updated