| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Thanks. I will try to make time to play around with this. Session cluster locking would be nice. |
Sorry, something went wrong.
|
Welcome! Let me know if you require any changes, but I do believe the general idea should be safe from a distributed locking standpoint (provided no keys get evicted). |
Sorry, something went wrong.
|
Hi @michael-grunder, did you manage to play with this a bit? |
Sorry, something went wrong.
|
Sorry, I've been swamped. I will give it a test though, it's a useful feature for sure. |
Sorry, something went wrong.
|
I have rebased this on the latest develop:
|
Sorry, something went wrong.
|
Updated the pull request description, the code should now be easier to follow :) |
Sorry, something went wrong.
|
Rebased on latest develop, now using cluster_send_rcmd_ex(c, slot, cmd) |
Sorry, something went wrong.
Adds PHP session locking support to the RedisCluster session save handler. The implementation collocates the session lock on the same slot as the session itself, ensures session lock acquisition is atomic, and any operations on the session are made on the slot owner (replicas cannot guarantee data freshness). These three guarantees enable the cluster session locks to behave like those already set up for standalone Redis.
|
Rebased on latest develop, added the fix for session handlers for php 8.6.0 |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
July 2026 update: I realised my former pull request description read more like a stream of consciousness novel than technical writing, so this should be a better version.
Description
This pull request adds PHP session locking support to the RedisCluster session save handler.
The implementation collocates the session lock on the same slot as the session itself, ensures session lock acquisition is atomic, and any operations on the session are made on the slot owner (replicas cannot guarantee data freshness). These three guarantees enable the cluster session locks to behave like those already set up for standalone Redis.
The implementation purposely avoids using any general distributed lock mechanism (i.e. Redlock) given that sessions themselves are already sharded (though both the session and its lock may be replicated). It adds a LUA script for lock acquisition, but defaults to the already existing LUA conditional delete (both Valkey and Redis conditional delete commands are supported as opt-in).
Implementation
Most of the code is a mirror copy of the standalone Redis flow, adapted to work on RedisCluster. The real work lies in a few notable changes that require attention.
added the redis_cluster_session struct
The cluster handle is bundled with the lock status, mirroring the redis_pool struct
added generate_cluster_lock_key and select_cluster_lock_key_form functions
The cluster lock key uses Redis Cluster Hash tags which basically wraps the session key around braces (thus creating a hash tag) and adds a _LOCK suffix, like so:
SESSIONKEY -> {SESSIONKEY}_LOCKThe code also autodetects the case in which there is already a tag inside the session key itself, like so:
{TAG}SESSIONKEY -> {TAG}SESSIONKEY_LOCKThe latter use case is strongly discouraged in the README.md, but support is there as one may imagine someone might want to force all sessions to go to a specific slot.
The select_cluster_lock_key_form function was adapted from the Redis source code keyHashSlot(). It is O(n) so impact is negligible.
added LOCK_RW_LUA_STR Lua script
The Lua script is the basis of the aforementioned atomic operation. It acquires the lock and reads the session data in a single call. The actual ordering of the operations is in reverse to prevent Redis from doing a SET on the lock if the session data GET fails (Redis does not rollback all operations within a LUA script).
The script will use GETEX to refresh the session TTL if set, fallback to regular GET. It supports setting the lock with a TTL and without, but cluster_lock_acquire_and_read sets the lock TTL to max_execution_time if redis.session.lock_expire is set to 0. To note: the lock TTL is defined in seconds, but written in milliseconds.
The reason the cluster lock key uses hash tags is so this script does not trip CROSSSLOT and fail.
operations sent to master slot
Due to possible stale data, the code ensures operations are sent to the master slot by setting:
That being said, any failover should be automatically handled by following Redis MOVED errors (unless the lock was lost in the failover). This should also work on AWS ElastiCache Serverless (though I would personally not set up sessions on such a cluster).
support for multiple lock release commands
Depending on the configured options, cluster_lock_release may call:
table of function equivalence
Most of the locking functions are a mirror of the standalone session handling code. This is on purpose as I copied them over before adapting them to work on the cluster, so if you are used to reading the session handling code, this should be functionally identical.
Note: cluster_send_release_cmd, cluster_read_session_data, and cluster_lock_acquire_and_read are all implemented inline in the standalone flow.
Tests
All the tests for session locking on the cluster have been uncommented and helpers have been slightly adapted where necessary.
I have also tested this against both Redis and Valkey clusters in multiple Docker environments, but those tests have not been included as I do not see the repo managing any Docker tests.
Backport on 6.3.0
This feature has also been backported on top of 6.3.0, code is in the 6.3.0_cluster_session_lock branch