Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restart redis than get Redis::CommandError: NOSCRIPT No matching script. Please use EVAL. #148

Open
weijenlarryli opened this issue Dec 15, 2023 · 5 comments

Comments

@weijenlarryli
Copy link

Hello redlock team,

I just started to use redlock yesterday.
After I restart my redis server, I get this error when using Redlock::Client lock

Redis::CommandError: NOSCRIPT No matching script. Please use EVAL.'
	/usr/local/bundle/gems/redlock-2.0.6/lib/redlock/client.rb:323:in `lock_instances'
	/usr/local/bundle/gems/redlock-2.0.6/lib/redlock/client.rb:275:in `block in try_lock_instances'
	/usr/local/bundle/gems/redlock-2.0.6/lib/redlock/client.rb:271:in `times'
	/usr/local/bundle/gems/redlock-2.0.6/lib/redlock/client.rb:271:in `try_lock_instances'
	/usr/local/bundle/gems/redlock-2.0.6/lib/redlock/client.rb:79:in `lock'

It seems redis cannot find the script.
Do you know how to fix this?

Thanks,
Larry

@jakephot
Copy link

jakephot commented Dec 20, 2023

I had the exact same issue. After debugging for a few hours, I found that this was due to a change in Redlock::Client::RedisInstance#recover_from_script_flush that was made when updating the gem from version 1.3.2 to 2.x.x. The change was to catch the RedisClient::CommandError error and not Redis::CommandError. However, the exception object was still Redis::CommandError with the following combination, causing the exception to be passed through to the next clause then just raised. This error reproduces only after restarting the Redis server or invoking SCRIPT FLUSH SYNC to clear the cache.

  • redis 4.8.1 / 5.0.8
  • redis-client 0.18.0 / 0.19.0

As for the solution, I downgraded the gem to 1.3.2 temporarily. Alternatively, I confirmed that the following monkey patch worked, but we did not use it on our production environment.

# config/initializers/redlock.rb

module Redlock
  class Client
    private
    class RedisInstance
      private
      def recover_from_script_flush
        retry_on_noscript = true
        begin
          yield
        rescue RedisClient::CommandError, Redis::CommandError => e # <= ADDED Redis::CommandError
          # When somebody has flushed the Redis instance's script cache, we might
          # want to reload our scripts. Only attempt this once, though, to avoid
          # going into an infinite loop.
          if retry_on_noscript && e.message.include?('NOSCRIPT')
            load_scripts
            retry_on_noscript = false
            retry
          else
            raise
          end
        end
      end
    end
  end
end

@leonnicolas
Copy link

Wouldn't the "recommended" fix be, to use redis-client to configure redlock. So instead of passing an instance of Redis to Redlock.new, use RedisClient?

Note that you would probably need redis 6+ with RESP3 support.

eltiffster added a commit to UVicLibrary/Vault that referenced this issue May 23, 2024
eltiffster added a commit to UVicLibrary/Vault that referenced this issue May 24, 2024
@kulbirsaini
Copy link

Thank you @jakephot for the monkey-patch! It saved my day. I wonder why this bug is still not solved though.

@yungtrizzle
Copy link

Hmm, in my case I didn't need the entire monkey-patch. I was already trying to rescue Redis::CommandError so adding RedisClient::CommandError there helped. Seems like the errors are not unified somewhere.

@johan-smits
Copy link

Updating the from LOCK_MANAGER = Redlock::Client.new([Redis.new(redis_opts)]) to LOCK_MANAGER = Redlock::Client.new([RedisClient.new(redis_opts)]) as suggested in #124 (comment) works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants