Redis/Locks lab

Locks Lab: Wrong-Owner DEL

This lab shows a subtle Redis lock bug: a worker whose lock expired can wake up and delete a lock now owned by another worker.

Break modeAcquire with SET NX PX, release with plain DEL.
Fix modeRelease with Lua compare-and-delete.
InvariantNo worker should delete a successor's lock.
TTL expires
plain DEL
EVAL
mismatch

Redis Commands

SET key value NX PX ttl

Acquires the lock only when missing. NX means do not overwrite an existing owner. PX sets TTL in milliseconds.

GET key

Reads the current lock owner token. The token is the proof of ownership.

DEL key

Deletes the lock. Plain DEL is unsafe because it does not verify ownership.

EVAL script keys args

Runs compare-and-delete atomically so no other command interleaves between GET and DEL.

Lua Release Script

if redis.call('GET', KEYS[1]) == ARGV[1] then
  return redis.call('DEL', KEYS[1])
else
  return 0
end
KEYS[1]

The lock key, lock:inventory.

ARGV[1]

The caller's ownership token, such as w3-i7.

redis.call('GET', KEYS[1])

Reads the current owner inside Redis.

== ARGV[1]

Checks whether the caller still owns the lock.

DEL

Deletes only on token match. Token mismatch returns 0 and preserves the successor's lock.

Run Targets

The runnable lab is labs/redis/locks, backed by labs/redis/cmd/locks.

make break

Naive release. Look for WRONG-OWNER DEL lines.

make test

Lua release. Look for expired holders skipping DEL.

make load

More workers and iterations to stress the release invariant.

Important Limit

What this fix does not solve The lab makes work duration longer than the lock TTL. That means concurrent critical-section occupancy can still happen. Lua compare-and-delete only prevents deleting another worker's lock. Correct writes often also need lock extension, idempotency, or fencing tokens.

Code Pointers

CodeWhy it matters
cmd/locks/main.goThe expired-owner scenario, unsafe DEL, and Lua compare-and-delete release.
locks/MakefileTargets for unsafe release, safe release, and stress runs.
locks/compose.yamlRedis container used by the lab.
locks/README.mdExpected output and the limit of compare-and-delete.
Cache Rate limit Streams Pub/Sub