在ngx.shared中缓存Redis数据是一种好习惯

时间:2017-08-09 12:44:38

标签: caching nginx lua

我在nginx中嵌入了一些Lua代码。在这段代码中,我从Redis缓存中获取了一些小数据。现在我想知道,如果使用ngx.shared构造在nginx中缓存这些数据(在某种意义上已经缓存)是一个好习惯吗?这样做是否有任何利弊?在伪代码中,我希望有类似的东西:

local cache = ngx.shared.cache
local cached_key = cache:get("cached_key")
if cached_key == nil then
    ... get data from Redis
    cache:set("cached_key", cached_key)
end

1 个答案:

答案 0 :(得分:2)

如文档中所述ngx.shared是nginx服务器的所有工作者共享的空间。

所有列出的操作都是原子操作,因此如果您依次对ngx.shared使用两个操作,则只需要担心race conditions。在这种情况下,应使用ngx.semaphore保护它们。

专业人士:

  • 使用ngx.shared可以更快地访问数据,因为您可以避免对Redis服务器的请求/响应循环。
  • 即使您需要ngx.semaphore,您也可以更快地访问数据(但我没有提供基准)。

缺点:

  • ngx.shared缓存提供的数据不准确,因为本地缓存不会反映当前的Redis值。这并不总是一个关键点,因为工作人员使用的值与Redis中存储的值之间总是存在差异。
  • ngx.shared中存储的数据可能不一致,这一点更为重要。例如,它可以存储x=truey=false,而在Redis xy中始终具有相同的值。这取决于您更新本地缓存的方式。
  • 您必须通过在发送到Redis时更新缓存中的值来处理缓存。这可以通过包装redis函数轻松完成。如果您在每次拨打redis.get之后处理更新时都会遇到错误,因为您(或某人)忘记更新。
  • 您还必须处理读取:只要在ngx.cache中找不到值,您就必须自动从Redis中读取它。如果你在每次拨打cache.get之后把它们放进来处理读取,就会出现错误,因为你(或某人)忘记它。

对于最后两点,您可以轻松编写一个小包装模块。

作为结论:

  • 如果您的服务器只运行一个具有一个或多个工作人员的实例,则使用ngx.shared很有意思,因为您始终可以拥有始终保持最新的Redis数据缓存。
  • 如果您的服务器运行多个实例并且必须始终具有最新的缓存,或者您可能存在一致性问题,那么您应该避免使用ngx.shared进行缓存。
  • 在所有情况下,如果数据的大小可能很大,请确保在内存消耗过高之前提供清理方法。如果您无法提供清洁服务,则不应使用ngx.shared

另外,不要忘记将缓存的值存储在local变量中,以避免一次又一次get,从而提高效率。