【问题标题】:Do we need to cache loaded scripts when using StackExchange.Redis?使用 StackExchange.Redis 时是否需要缓存加载的脚本?
【发布时间】:2015-12-06 01:43:38
【问题描述】:

我正在创建一个库,主要用于通过 StackExchange.Redis 使用 Lua 脚本的非 Web 环境。

我们是否应该在使用 StackExchange.Redis 时为每个 Evaluate 调用加载 Lua 脚本,例如

var prepped = LuaScript.Prepare(_someScript);
var loaded = prepped.Load(someServer);
loaded.Evaluate(someDb);

或者我们应该加载一次,然后每次我们要在给定进程中评估它们时重用 LoadedLuaScript 实例?

【问题讨论】:

    标签: c# lua stackexchange.redis


    【解决方案1】:

    脚本应在启动时加载一次,并在需要时将 LoadedLuaScript 实例保留为 Evaluate。 StackExchange.Redis 不会在任何地方缓存 LoadedLuaScripts,因此,如果您在每次调用时都进行准备和加载过程,那么您要做的就是让 StackExchange.Redis 将脚本转移到 Redis,在那里它会被散列,Redis将意识到它已经拥有它,然后将哈希传回。

    如果您的进程没有频繁启动(对于某些值来说经常),那么在启动时加载所有脚本可能是合理的,即使它们已经加载到 Redis 中,因为它不会导致多个实例这些脚本缓存在 Redis 中。您可以将 LoadedLuaScripts 保存在一个简单的缓存中,例如:

        private static readonly string _helloScript =
              "print(\"Hello World!\")"
            ;
    
        public void LoadScripts(IDatabase db, IServer srv)
        {
            var scripts = new Dictionary<string, string>
            {
                { "sayHello",                      _helloScript },
            };
    
            foreach (var scriptName in scripts.Keys)
            {
                var prepped = LuaScript.Prepare(scripts[scriptName]);
    
                _scripts.Add(scriptName, prepped.Load(srv));
            }
        }
    
        public void SayHello(IDatabase db)
        {
            _scripts["sayHello"].Evaluate(db);
        }
    

    【讨论】:

      【解决方案2】:

      出于性能原因,Lua 脚本可以加载到 redis,然后通过它们的哈希调用。此加载是可选的,只需执行一次即可获得性能优势。

      使用 StackExchange.Redis,您不必显式使用 Load 方法。让 StackExchange.Redis 处理缓存更容易。 LuaScript 类在第一次调用“ScriptEvaluate”时自动将 Lua 脚本传输到 redis。对于同一脚本的进一步调用,仅使用哈希:

      var prepared = LuaScript.Prepare(script);
      prepared.Evaluate(someDb); // loads the script to redis and calls it
      
      var prepared2 = LuaScript.Prepare(script);
      prepared2.Evaluate(someDb); // calls the script by it's hash
      

      【讨论】:

        【解决方案3】:

        还不能发表评论,但我只想补充一下@ChriZ 的答案, 看起来 LuaScript.Evaluate 可能会通过查看 RedisDatabase.cs->GetMessages 来使用缓存(没有检查).. 但是..

        在 Evaluate 代码之后,它看起来像是进行了一些脏哈希正则表达式检查 (ScriptLoadProcessor.IsSHA1) 以及许多其他在我看来效率不高的检查...

        最重要的是,如果你去 LuaScript.cs 它是明确写的:

        与 LuaScript 不同,LoadedLuaScript 发送它的哈希值 ExecutableScript 到 Redis,而不是将整个脚本传递给每个 称呼。这要求脚本在被加载到 Redis 之前 用过的。要创建一个 LoadedLuaScript 首先通过创建一个 LuaScript LuaScript.Prepare(string),然后调用 Load(IServer, CommandFlags) on 返回的 LuaScript。

        如果我错了,请纠正我...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-10
          • 1970-01-01
          • 2010-12-24
          • 1970-01-01
          • 1970-01-01
          • 2020-12-19
          • 2012-12-09
          相关资源
          最近更新 更多