Luther Monson, Staff Software Engineer at SUSE

Luther Monson

Go by way of PHP · Containers · VMs · Windows · Kubernetes

A Lock Is Only as Good as Its Release

SETNX gets all the attention, but most of the bugs in ePHPm's KV locks were on the release side. This is how blind deletes, a missing compare-and-delete and a cluster where two nodes could both win got fixed.

9-Minute Read

Timeline: request A's lock expires, B acquires it, A's blind DEL frees B's lock and C gets in

Every “build a lock on Redis” tutorial spends its time on acquisition: SET key value NX PX 30000, one winner, done. The release gets one line, DEL key. That line is where most of the lock bugs I’ve had in ePHPm lived. Over about three months the same mistake showed up in three places. First the native session handler, then two of the Composer wrapper packages, and finally the cluster. Each time it wore a slightly different costume.

Calling Rust From PHP Without a Socket, Part 2: Making Existing Code Use It

Thirteen Composer packages let existing Redis and database code in WordPress, Laravel and Symfony use ePHPm's built-in versions. This post covers what's in them and the bugs they turned up.

8-Minute Read

The APIs PHP apps already call, mapped through ePHPm wrapper packages onto ephpm_kv_* and ephpm_db_*

Part 1 covered the plumbing. ePHPm registers ephpm_kv_* and ephpm_db_* functions that call straight into Rust. A cache read through one costs about a tenth of a microsecond instead of a loopback round trip. That’s nice and also useless on its own. Nobody is going to rewrite their WordPress object cache or their Laravel cache store around a function called ephpm_kv_set(). Applications talk to existing APIs instead:

Calling Rust From PHP Without a Socket, Part 1: The Native Functions

How ePHPm exposes its in-process KV store and SQLite bridge to PHP as plain functions, and what it took to make that safe under ZTS.

14-Minute Read

Two paths from PHP to the ePHPm KV store: over a RESP socket, or through a native function and a function pointer table

ePHPm is a single Rust binary that embeds PHP. It carries its own KV store and its own SQLite-backed database in the same process. For a long time PHP code could only reach that KV store the same way it reaches Redis. It opened a TCP socket to the RESP listener ePHPm runs on localhost, encoded a command and waited for the reply. That works, and every PHP Redis client in existence already speaks it. But it is a strange thing to do when the hash map you’re talking to lives a few pointers…

Rolling Your Own KV Store Instead of Embedding Redis

Why ePHPm has its own Redis-compatible cache built in instead of running Redis. It also covers a bug that hid in it for four months and how it compares to real Redis on the same machine.

11-Minute Read

Bar chart of redis-benchmark GET and SET throughput against Redis 7.4, ePHPm v0.5.2 and ePHPm v0.2.0

Every PHP deployment I’ve run eventually grew a Redis. Sessions, the WordPress object cache, Laravel’s cache and locks, rate limiting. ePHPm is supposed to be one binary that replaces nginx + php-fpm + Redis, so it needed a cache in the box. I didn’t want to write one. This post covers why I did anyway and how it’s built. It also covers the bug that sat in its eviction code from March until last month. Then I compare it against a stock Redis on the same machine with…

Recent Posts

Categories

About

Luther is a 20+ year software veteran specializing in backend APIs and architecting products. Employed at SUSE as the Team Lead for the Containers on Windows Team working on Rancher + Kubernetes