Let’s first deal with the question of why we would decide to build a lock with Lua. There are two major reasons.
Technically speaking, when executing a Lua script with EVAL or EVALSHA, the first
group of arguments after the script or hash is the keys that will be read or written
within Lua (I mentioned this in two notes in sections 11.1.1 and 11.1.2). This is primarily
to allow for later Redis cluster servers to reject scripts that read or write keys
that aren’t available on a particular shard. If we don’t know what keys will be read/
written in advance, we shouldn’t be using Lua (we should instead use WATCH/MULTI/
EXEC or locks). As such, any time we’re reading or writing keys that weren’t provided as part of the KEYS argument to the script, we risk potential incompatibility or breakage
if we transition to a Redis cluster later.
The second reason is because there are situations where manipulating data in
Redis requires data that’s not available at the time of the initial call. One example
would be fetching some HASH values from Redis, and then using those values to access
information from a relational database, which then results in a write back to Redis. We
saw this first when we were scheduling the caching of rows in Redis back in section 2.4.
We didn’t bother locking in that situation because writing two copies of the same row
twice wouldn’t have been a serious issue. But in other caching scenarios, reading the
data to be cached multiple times can be more overhead than is acceptable, or could
even cause newer data to be overwritten by older data.
Given these two reasons, let’s rewrite our lock to use Lua.