A Redis-backed PHP session handler with optimistic locking

Overview

php-redis-session-abstract

A Redis-based session handler with optimistic locking.

Features:

  • When a session's data size exceeds the compression threshold the session data will be compressed.
  • Compression libraries supported are 'gzip', 'lzf', 'lz4', and 'snappy'.
    • Gzip is the slowest but offers the best compression ratios.
    • Lzf can be installed easily via PECL.
    • Lz4 is supported by HHVM.
  • Compression can be enabled, disabled, or reconfigured on the fly with no loss of session data.
  • Expiration is handled by Redis; no garbage collection needed.
  • Logs when sessions are not written due to not having or losing their lock.
  • Limits the number of concurrent lock requests.
  • Detects inactive waiting processes to prevent false-positives in concurrency throttling.
  • Detects crashed processes to prevent session deadlocks (Linux only).
  • Gives shorter session lifetimes to bots and crawlers to reduce wasted resources.
  • Locking can be disabled entirely

Locking Algorithm Properties:

  • Only one process may get a write lock on a session.
  • A process may lose it's lock if another process breaks it, in which case the session will not be written.
  • The lock may be broken after BREAK_AFTER seconds and the process that gets the lock is indeterminate.
  • Only MAX_CONCURRENCY processes may be waiting for a lock for the same session or else a ConcurrentConnectionsExceededException will be thrown.

Compression

Session data compresses very well so using compression is a great way to increase your capacity without dedicating a ton of RAM to Redis and reducing network utilization. The default compression threshold is 2048 bytes so any session data equal to or larger than this size will be compressed with the chosen compression_lib which is gzip by default. Compression can be disabled by setting the compression_lib to none. However, both lzf and snappy offer much faster compression with comparable compression ratios so I definitely recommend using one of these if you have root. lzf is easy to install via pecl:

sudo pecl install lzf

NOTE: If using suhosin with session data encryption enabled (default is suhosin.session.encrypt=on), two things:

  1. You will probably get very poor compression ratios.
  2. Lzf fails to compress the encrypted data in my experience. No idea why...

If any compression lib fails to compress the session data an error will be logged in system.log and the session will still be saved without compression. If you have suhosin.session.encrypt=on I would either recommend disabling it (unless you are on a shared host since Magento does it's own session validation already) or disable compression or at least don't use lzf with encryption enabled.

Bot Detection

Bots and crawlers typically do not use cookies which means you may be storing thousands of sessions that serve no purpose. Even worse, an attacker could use your limited session storage against you by flooding your backend, thereby causing your legitimate sessions to get evicted. However, you don't want to misidentify a user as a bot and kill their session unintentionally. This module uses both a regex as well as a counter on the number of writes against the session to determine the session lifetime.

Using with Cm_Cache_Backend_Redis

Using Cm_RedisSession alongside Cm_Cache_Backend_Redis should be no problem at all. However, it is strongly advised to run two separate Redis instances even if they are running on the same server. Running two instances will actually perform better since Redis is single-threaded so on a multi-core server is bound by the performance of a single core. Also it makes sense to allocate varying amounts of memory to cache and sessions and to enforce different "maxmemory" policies. If you absolutely must run one Redis instance for both then just don't use the same 'db' number. But again, just run two Redis instances.

License

@copyright  Copyright (c) 2013 Colin Mollenhour (http://colin.mollenhour.com)
This project is licensed under the "New BSD" license (see source).
Comments
  • Implement write lock instead of read lock

    Implement write lock instead of read lock

    This module does not implement write lock, but read lock instead.

    The lock is currently taken when the session is first read and released when written.

    You can actually prove this misconception by simply reading the first comment of the read method on this line https://github.com/colinmollenhour/php-redis-session-abstract/blob/master/src/Cm/RedisSession/Handler.php#L429

    This causes bad performance on numerous Magento projects (if not all), since there are multiple HTTP requests running in parallel that need to read the session (furthermore when combining AJAX and non-AJAX requests, and especially in the checkout, or in development mode where the static file symlinking process needs to read the session).

    This issue is causing more problems as the number of AJAX requests and their duration are growing.

    The lock should be taken just before writing and released immediately after.

    To avoid concurrency issues, a "diff" must be calculated by comparing the first session read and the session that is programmed to be written, and applied to a fresh session that is fetched just after taking the lock, then write the merged result.

    I am preparing a patch to overcome this situation.

    opened by Yonn-Trimoreau 17
  • Credis (https://github.com/colinmollenhour/credis) Release 1.9.0

    Credis (https://github.com/colinmollenhour/credis) Release 1.9.0

    PHP Notice for undefinded Index with Credis Release 1.9.0 (https://github.com/colinmollenhour/credis/releases/tag/1.9.0)

    response from client is now a key/value array instead of values only

    https://github.com/colinmollenhour/php-redis-session-abstract/blob/7e961834e1373058213765e7a3e391184282d863/src/Cm/RedisSession/Handler.php#L548

    opened by tkd-hgoertz 8
  • Add ability to disable locking for bots only

    Add ability to disable locking for bots only

    In New Relic I frequently see slow requests stuck trying to read the session due to being caught on the lock. Most of the time these are from bots as they crawl the site at speed.



    I was thinking that the artificially slow request could potentially have some negative SEO effects, especially on Product pages and similar.



    If we had the ability to disable session locking for bots only we could prevent this issue.

    I have not had success previously with disabling session locking entirely so was thinking a little more granular control at this level could help out.

    Let me know what you think of this idea.

    opened by convenient 7
  • Incompatible version constraint 1.5.0 for Magento 2.4.5

    Incompatible version constraint 1.5.0 for Magento 2.4.5

    The PHP 8.1 compatibility release 1.5.0 is not installable with Magento 2.4.5 because it uses the version constraint "colinmollenhour/php-redis-session-abstract": "~1.4.5",.

    Looking at the CHANGELOG of php-redis-session-abstract from 1.4.5 to 1.5.0, but I do not see a reason why the minor version needs to be bumped to 5.
    Could you please tag the same release as 1.4.6?

    opened by Vinai 4
  • Remove dependency on zend framework

    Remove dependency on zend framework

    As I see, Zend framework is actually never used in v1.2.x of this library and already dropped in the v1.3.x. It would be nice to remove this dependency for v.1.2.x too as it locks specific zend framework version without a reason.

    opened by igrybkov 2
  • PHP 7.1 support for version 1.2

    PHP 7.1 support for version 1.2

    Hi,

    The version 1.3 contains backward incompatible change (a new method has been added to the interface Cm\RedisSession\Handler\ConfigInterface. It is the undesirable side effect when we only want to make our code compatible with PHP 7.1.

    I've checked the code for the version 1.2 and didn't find any incompatibility, so the only thing which is required to make it works with PHP 7.1 is to add this version as supported into composer.json.

    But, as there is no branch for that specific version, I cannot send you a pull request with a fix.

    Can you please make a new release v1.2.1 with added PHP 7.1 support in the composer.json?

    opened by igrybkov 2
  • Minimum PHP version

    Minimum PHP version

    Inside the README file it states:

    Requires PHP >= 5.3. Yes, this is a feature. You're welcome. ;)

    However in composer.json the minimum PHP version is set to 5.5 here: https://github.com/colinmollenhour/php-redis-session-abstract/blob/master/composer.json#L13

    Which is correct?

    opened by adamj88 2
  • Fix PHP 8.1 warning with sentinel

    Fix PHP 8.1 warning with sentinel

    Resolve warning: Deprecated Functionality: preg_split(): Passing null to parameter #3 ($limit) of type int is deprecated in /Cm/RedisSession/Handler.php on line 300

    EDIT: on Redis 6 the error message returned when AUTH is not set on sentinels is different, so add it to check

    opened by zamu87 1
  • PHP 8.1 Return type compatibility

    PHP 8.1 Return type compatibility

    In PHP 8.1, >> non-final internal methods now require overriding methods to declare a compatible return type, otherwise a deprecated notice is emitted during inheritance validation. RFC: https://wiki.php.net/rfc/internal_method_return_types

    Because of this, we receive a deprecation notice when running our code with PHP8.1.

    This PR adds #[ReturnTypeWillChange] attribute where it is needed, in order to avoid the described problem and keep backward compatibility.

    opened by karyna-tsymbal-atwix 1
  • Remove useless php 7.1 an 7.2 sections in composer.json

    Remove useless php 7.1 an 7.2 sections in composer.json

    "php": "^5.5 || ^7.0" allows to install any 7.x version, more info https://getcomposer.org/doc/articles/versions.md#caret-version-range-

    opened by ihor-sviziev 1
  • replace

    replace "DEL" Commands with "UNLINK"

    This PR replaces DEL Command with UNLINK command.

    Details about UNLINK can be found here https://redis.io/commands/unlink .

    As noticed here redis/redis#1748 (comment) this will not change the behavior.

    As there is no check of Redis version included, it will break Redis Versions < 4.0 through.

    As Redis 4.0 was released on 2017-07-14 and Redis 3 went EOL with the Redis 5 on 2018-10-17, I don't expect this being an issue.

    See also https://github.com/colinmollenhour/Cm_Cache_Backend_Redis/issues/158 for details.

    opened by jonashrem 1
  • PHP8 issue

    PHP8 issue

    Exception #0 (Exception): Deprecated Functionality: preg_split(): Passing null to parameter #3 ($limit) of type int is deprecated in /var/www/html/vendor/colinmollenhour/php-redis-session-abstract/src/Cm/RedisSession/Handler.php on line 300
    
    opened by Nuranto 1
  • Sentinel config, Round-Robin, Sentinel Server not reachable

    Sentinel config, Round-Robin, Sentinel Server not reachable

    Hello,

    when using Redis-Sentinel settings in Magento 2.3.x for example in the Config-Section 'session' => [ 'save' => 'redis', 'redis' => [ 'sentinel_servers' => 'tcp://10.0.0.30:26379,tcp://10.0.0.31:26379,tcp://10.0.0.32:26379',

    and one of the Sentinel-Servers is not reachable for some reason, for ex. the first 10.0.0.30 (this is also the Server used through your program logic), see Link: https://github.com/colinmollenhour/php-redis-session-abstract/blob/8d684bbacac99450f2a9ddf6f56be296997e2959/src/Cm/RedisSession/Handler.php#L303

    nothing works anymore, because of the not correct CredisException handlig.

    If the Sentinel-Server is not reachabel, the Credis Client.php (see Link: https://github.com/colinmollenhour/credis/issues/new?permalink=https%3A%2F%2Fgithub.com%2Fcolinmollenhour%2Fcredis%2Fblob%2F464804e67d0fe5707c9035c986f3850f83d9d177%2FClient.php%23L497 )

    throws the Error but does not include the Error-Number (111) which can be used in Handler.php on Line https://github.com/colinmollenhour/credis/issues/new?permalink=https%3A%2F%2Fgithub.com%2Fcolinmollenhour%2Fcredis%2Fblob%2F464804e67d0fe5707c9035c986f3850f83d9d177%2FClient.php%23L497

    Your Line: throw new CredisException("Connection to Redis {$this->host}:{$this->port} failed after $failures failures." . (isset($errno) && isset($errstr) ? "Last Error : ({$errno}) {$errstr}" : ""));

    My Line: throw new CredisException("Connection to Redis {$this->host}:{$this->port} failed after $failures failures." . (isset($errno) && isset($errstr) ? "Last Error : ({$errno}) {$errstr}" : ""), $errno);

    How the "Round-Robin" for-loop should work, i don't know...

    And if the rest works (Sentinel without Pass) i haven't tested

    opened by bst2002git 1
  • Add support for zstd

    Add support for zstd

    For compression multiple compression libraries are supported. For the Cm_Cache_Backend_Redis the zstd library has been added in 2018 (https://github.com/colinmollenhour/Cm_Cache_Backend_Redis/commit/a9c4a5ae6001e04097aa7302abd89c9496c563e0) which IMHO gives a slightly better compression at a better speed. It would be beneficial to add zstd for the Redis session module as well.

    opened by phoenix-bjoern 0
  • Does/will it support primary/replica cluster for AWS ElastiCache?

    Does/will it support primary/replica cluster for AWS ElastiCache?

    Hey,

    I know it may be not a good place to ask this question but I can't find anywhere else to ask it.

    I see the package https://github.com/colinmollenhour/Cm_Cache_Backend_Redis support the ElastiCache (cluster disabled mode), and that is for Magento2 cache. However, the session only has Redis Sentinel relevant configurations. Why?

    Thanks

    opened by debuggeryang 1
  • Sentinel Auth

    Sentinel Auth

    Using sentinel configuration is not possibile to disable sentinel auth keeping master node auth enabled or to specify different passwords.

    The problem is in Handler.php file because the same variable $pass si evaluated for $sentinelClient->auth and $redisMaster->auth

    306   $sentinelClient = new \Credis_Client($server, NULL, $timeout, $persistent);
    307   $sentinelClient->forceStandalone();
    308   $sentinelClient->setMaxConnectRetries(0);
    309   if ($pass) $sentinelClient->auth($pass);
    310   
    311   $sentinel = new \Credis_Sentinel($sentinelClient);
    312   $sentinel
    313      ->setClientTimeout($timeout)
    314      ->setClientPersistent($persistent);
    315   $redisMaster = $sentinel->getMasterClient($sentinelMaster);
    316   if ($pass) $redisMaster->auth($pass);
    
    opened by zamu87 5
Releases(v1.5.1)
Owner
Colin Mollenhour
Colin Mollenhour
Redis-based session handler for Magento with optimistic locking

Cm_RedisSession A Redis-based session handler for Magento with optimistic locking. Features: Falls back to mysql handler if it can't connect to Redis.

Colin Mollenhour 216 Jan 5, 2023
A Redis-based session handler for Magento with optimistic locking.

Cm_RedisSession A Redis-based session handler for Magento with optimistic locking. Features: Falls back to mysql handler if it can't connect to Redis.

Colin Mollenhour 215 Jan 28, 2022
AWS DynamoDB session handler for Magento (experimental!)

Magento Session Handler for AWS DynamoDB Author: Fabrizio Branca TODO: disable automatic gc create cron that does gc how does it keep track of lifetim

AOE 5 Apr 6, 2017
A super simple, clean and pretty error handler that replace the default error handler of PHP. You need only include this file!

php-custom-error-handler A super simple, clean and pretty error handler that replace the default error handler of PHP. You need just include only this

null 6 Nov 7, 2022
This is a plugin for pocketmine-mp, when locking a player's items helps players not to lose items or throw things around causing server lag.

[] LockedItem| v1.0.0 Player's item lock Features Player's item lock Players aren't afraid of losing items For Devolopers You can access to LockedItem

JeroGamingYT 3 Jan 4, 2022
The SOLID principles demonstrated in PHP as seen on Elaniin's SOLID Booster Session.

SOLID Principles SOLID is the mnemonic acronym that represents 5 design principles that aim to make software designs more understandable, flexible, an

Vlass Contreras 5 Aug 24, 2022
Learning about - Basic HTML & CSS, JSON, XML, Session & Cookies, CRUD Operations in Php using MySQL and Create MVC from scratch

This Project is based on course CSC 3215. Learning about - Basic HTML & CSS, JSON, XML, Session & Cookies, CRUD Operations in Php using MySQL and Create MVC (Model–View–Controller) from scratch. Just learning about web technologies, Not focusing on UI (Bootstrap or other 3rd-Party UI libraries or frameworks).

Alvi Hasan 5 Sep 21, 2022
Block Session Hijacking in php.

Block Session Hijacking in php. How Does it work? This is an incredibly simple example, that is meant to be worked on. Please Do NOT use this from sto

null 0 Dec 25, 2021
A Simple MVC PHP Framework, integrated with lot of features such as Session, Cookies, Migrations, Database, Factories, Seeding, Bootstrap and Tailwind CSS

Navite A Simple MVC PHP Framework, integrated with lot of features such as Session, Cookies, Migrations, Database, Factories, Seeding, Bootstrap and T

Celionatti 2 Aug 22, 2022
Web app for kick session in a server 1C use rac/ras

Server requirement OS: Ubuntu 20.04 Usage Update adm1c nano adm1c You should change server_name adm1c.example.com to your name Update index.php nano

null 10 Dec 5, 2022
This Magento extension provides a Real Full Page Caching for Magento powered by Varnish with support of Session-Based information caching (Cart, Customer Accounts, ...) via ESI includes

This Magento extension provides a Real Full Page Caching (FPC) for Magento powered by Varnish with support of Session-Based information caching (Cart, Customer Accounts, ...) via ESI includes

Hugues Alary 95 Feb 11, 2022
Personal PHP MySQL query handler based on Eloquent using PDO.

?? Equivoluent Welcome to "Equivoluent" my personal PHP MySQL query handler using PDO. Equivoluent is based on Laravel's Eloquent. The goal of "Equivo

Wob Jelsma 2 Sep 7, 2022
Error handler with PSR-7 support

Jasny Error Handler Error handler with PSR-7 support. Installation The Jasny Error Handler package is available on packagist. Install it using compose

Arnold Daniels 6 Jun 23, 2022
think-exception-handler

ThinkPHP6.0 exception 异常插件 安装 composer require tinywan/think-exception 配置 发布配置 php think tinywan:exception 这将自动生成 config/exception.php 配置文件。 配置异常类 a

 ShaoBo Wan(無尘) 4 Dec 27, 2022
Phalcon - 📕 基于Phalcon集成Composer,事件监听,中间件,MongoDB,Redis

About Phalcon 基于Phalcon的高性能PHP框架,集成Composer 支持MongoDB Redis操作,监听器,中间件,以及多语言支持 A framework which use phalcon High performance Composer Database support

X.T 35 Nov 1, 2022
A Zend_Cache backend for Redis with full support for tags (works great with Magento)

Zend_Cache backend using Redis with full support for tags This Zend_Cache backend allows you to use a Redis server as a central cache storage. Tags ar

Colin Mollenhour 389 Jan 4, 2023
Magento2 + Varnish + PHP7 + Redis + SSL (cluster ready)

Docker Magento2: Varnish + PHP7 + Redis + SSL cluster ready docker-compose infrastructure Infrastructure overview Container 1: MariaDB Container 2: Re

Fabrizio Balliano 332 Dec 30, 2022
This is an implementation of PSR specification. It allows you to send and consume message with Redis store as a broker.

This is an implementation of PSR specification. It allows you to send and consume message with Redis store as a broker.

Enqueue 35 Nov 4, 2022
Pika is a nosql compatible with redis, it is developed by Qihoo's DBA and infrastructure team

Introduction中文 Pika is a persistent huge storage service , compatible with the vast majority of redis interfaces (details), including string, hash, li

OpenAtomFoundation 4.9k Jan 6, 2023