Skip to content

Refactor incrementWithTtlScript Lua EVAL to use Redis Functions #38

Description

@hongwei1

Description

We should consider replacing the EVAL Lua script incrementWithTtlScript with Redis Functions (introduced in Redis 7.0).

Current implementation relies on EVAL/EVALSHA for rate limiting / TTL logic:

local c = redis.call('INCR', KEYS[1])
if c == 1 then
  redis.call('EXPIRE', KEYS[1], ARGV[1])
elseif redis.call('TTL', KEYS[1]) < 0 then
  redis.call('SET', KEYS[1], 1, 'EX', ARGV[1])
  c = 1
end
return {c, redis.call('TTL', KEYS[1])}

Proposed Solution

Using Redis Functions provides several benefits over EVAL:

  1. Persistence & Replication: Functions are treated like data, persisting across restarts and replicating to replicas. We no longer need to handle NOSCRIPT errors on the application side.
  2. Simplified Application Logic: The application simply calls FCALL increment_with_ttl 1 <key> <ttl>.

Example function definition:

#!lua name=ratelimit_lib

local function increment_with_ttl(keys, args)
  local c = redis.call('INCR', keys[1])
  if c == 1 then
    redis.call('EXPIRE', keys[1], args[1])
  elseif redis.call('TTL', keys[1]) < 0 then
    redis.call('SET', keys[1], 1, 'EX', args[1])
    c = 1
  end
  return {c, redis.call('TTL', keys[1])}
end

redis.register_function('increment_with_ttl', increment_with_ttl)

Prerequisites

  • Ensure the minimum required Redis version is 7.0 in all environments.
  • Ensure the Redis client library supports FCALL and FUNCTION LOAD.
  • Update deployment/migration steps to load the function library into Redis upon startup.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions