2012-03-07 84 views
24

现在堆栈溢出使用redis,它们是否以相同的方式处理缓存失效?即一个身份列表哈希到查询字符串+名称(我猜这个名字是某种目的或对象类型名称)。Stack Overflow,Redis和Cache失效

也许他们然后直接检索从缓存中丢失的单个项目(绕过一堆数据库索引,而不是使用更有效的聚簇索引)。那会很聪明(Jeff提到的补液)。

现在,我正在努力寻找一种方法来以简洁的方式来实现所有这些。有没有这样的事情的例子,我可以用来帮助澄清我的想法,然后再做自己的第一次切割?

此外,我想知道在使用.net缓存(System.Runtime.Caching或System.Web.Caching)和外出使用redis之间的截止点。或者,Redis是否更快?

下面是从2009年最初的SO问题:

https://meta.stackexchange.com/questions/6435/how-does-stackoverflow-handle-cache-invalidation

一对夫妇的其他环节:

https://meta.stackexchange.com/questions/69164/does-stackoverflow-use-caching-and-if-so-how/69172#69172

https://meta.stackexchange.com/questions/110320/stack-overflow-db-performance-and-redis-cache

回答

40

老实说,我不能决定,如果这是SO问题或MSO问题,但是:

去查询另一个系统是从来没有快于查询本地内存(只要它是键控);简单的答案:我们同时使用!所以我们使用:

  • 本地内存
  • 其他检查Redis的,并更新本地内存
  • 从源头别的读取和更新Redis的和本地内存

这就如你所说,导致缓存失效的问题 - 尽管实际上在大多数地方不是关键。但是为此 - redis事件(pub/sub)允许一种简单的方法来广播正在改变到所有节点的密钥,以便他们可以放弃他们的本地副本 - 这意味着:下次需要时,我们将从redis中获取新副本。因此,我们广播对单个事件频道名称进行更改的键名称。

工具:在Ubuntu服务器上的Redis; BookSleeve作为redis包装器; protobuf-net和GZipStream(根据大小自动启用/禁用)打包数据。

所以:Redis的发布/订阅事件被使用(已经改变,知道国家的)对给定键缓存从一个节点立即失效(几乎)到所有节点。

关于不同的进程(来自注释,“你是否使用任何种类的共享内存模型来处理多个不同的进程以提供相同的数据?”):不,我们不这样做。每个Web层框只能托管一个进程(任何给定层),其中多租户之内,因此在同一进程内我们可能有70个站点。由于遗留原因(即“它工作并且不需要修复”),我们主要使用具有站点标识的http缓存作为密钥的一部分。

对于系统中少数大量数据密集型的部分,我们有机制坚持到磁盘,以便内存模型可以在连续的应用程序域之间传递,因为Web自然地回收(或重新部署) ,但这与redis无关。

这里有一个相关的例子,只有这是如何工作的显示广阔的味道 - 旋转了一个数以下的实例,然后键入一些键名:

static class Program 
{ 
    static void Main() 
    { 
     const string channelInvalidate = "cache/invalidate"; 
     using(var pub = new RedisConnection("127.0.0.1")) 
     using(var sub = new RedisSubscriberConnection("127.0.0.1")) 
     { 
      pub.Open(); 
      sub.Open(); 

      sub.Subscribe(channelInvalidate, (channel, data) => 
      { 
       string key = Encoding.UTF8.GetString(data); 
       Console.WriteLine("Invalidated {0}", key); 
      }); 
      Console.WriteLine(
        "Enter a key to invalidate, or an empty line to exit"); 
      string line; 
      do 
      { 
       line = Console.ReadLine(); 
       if(!string.IsNullOrEmpty(line)) 
       { 
        pub.Publish(channelInvalidate, line); 
       } 
      } while (!string.IsNullOrEmpty(line)); 
     } 
    } 
} 

你应该看到的是当你键入一个键名时,它会立即显示在所有正在运行的实例中,然后转储它们的该键的本地副本。显然在实际使用中,这两个连接需要放在某个地方并保持开放,因此不是将在using声明中。我们为此使用了一个近乎单身的单身人士。

+0

该事件是否也会回来并使内存中的版本无效?如果是这样,很酷。回复:内存中 - 您是否使用任何类型的共享内存模型来处理多个不同的进程,以提供相同的数据?我看到内存组件重复的潜力。 – sgtz 2012-03-07 07:22:46

+0

@sgtz将编辑 – 2012-03-07 07:40:16

+0

感谢Marc。现在消化信息(心理齿轮尚未完成转向)。从外部管理内存到期是一个非常好的接触。没有想到这一点。 (!) – sgtz 2012-03-07 10:03:43

相关问题