c# - 我应该如何将动态变化的数据存储到服务器缓存中?

标签 c# asp.net caching

编辑: 本网站的目的:名为 Utopiapimp.com。它是一款名为 utopia-game.com 的游戏的第三方实用程序。该网站目前拥有超过 12,000 名用户,我负责运营该网站。该游戏完全基于文本,并将永远保持这种状态。用户从游戏中复制并粘贴整页文本,并将复制的信息粘贴到我的站点中。我针对粘贴的数据运行一系列正则表达式并将其分解。然后我根据那个粘贴将 5 个值到超过 30 个值的任意位置插入到数据库中。然后我获取这些值并对它们运行查询,以非常简单易懂的方式显示信息。该游戏以团队为基础,每个团队有 25 个用户。所以每个团队都是一个组,每一行都是一个用户信息。用户可以一次更新所有 25 行或仅更新一行。我需要将内容存储到缓存中,因为该站点几乎每分钟执行 1,000 多个查询的速度非常慢。

所以这是交易。假设我有一个包含 100 列和 5000 行的 excel EDIT(Excel 只是一个想象的例子,我实际上并没有使用 excel)。每行都有两个唯一标识符。一个用于它自己的行,一个用于将 25 行组合在一起。该行中大约有 10 列几乎永远不会更改,而其他 90 列将始终更改。我们可以说有些甚至会在几秒钟内发生变化,具体取决于行的更新速度。也可以从组中添加和删除行,但不能从数据库中添加和删除行。这些行取自数据库中的大约 4 个查询,以显示数据库中最新和更新的数据。所以每次更新数据库中的内容时,我也希望更新该行。如果一行或一组在 12 小时左右没有更新,就会从 Cache 中取出。一旦用户通过数据库查询再次调用该组。它们将被放入缓存中。

以上就是我想要的。这就是愿望。

实际上,我仍然拥有所有行,但我将它们存储在缓存中的方式目前已损坏。我将每一行存储在一个类中,该类通过一个巨大的列表存储在服务器缓存中。当我去更新/删除/插入列表或行中的项目时,大部分时间它都有效,但有时它会抛出错误,因为缓存已更改。我希望能够锁定缓存,就像数据库或多或少地锁定一行一样。我有 DateTime 戳记可以在 12 小时后删除内容,但这几乎总是会中断,因为其他用户正在更新组中相同的 25 行,或者只是缓存发生了变化。

这是我如何将项目添加到缓存的示例,这个示例表明我只提取了 10 个左右很少更改的列。此示例全部删除 12 小时后未更新的行:

DateTime dt = DateTime.UtcNow;
    if (HttpContext.Current.Cache["GetRows"] != null)
    {
        List<RowIdentifiers> pis = (List<RowIdentifiers>)HttpContext.Current.Cache["GetRows"];
        var ch = (from xx in pis
                  where xx.groupID == groupID 
                  where xx.rowID== rowID
                  select xx).ToList();
        if (ch.Count() == 0)
        {
            var ck = GetInGroupNotCached(rowID, groupID, dt); //Pulling the group from the DB
            for (int i = 0; i < ck.Count(); i++)
                pis.Add(ck[i]);
            pis.RemoveAll((x) => x.updateDateTime < dt.AddHours(-12));
            HttpContext.Current.Cache["GetRows"] = pis;
            return ck;
        }
        else
            return ch;
    }
    else
    {
        var pis = GetInGroupNotCached(rowID, groupID, dt);//Pulling the group from the DB
        HttpContext.Current.Cache["GetRows"] = pis;
        return pis;
    }

最后一点,我从缓存中删除了项目,因此缓存实际上并没有变大。

要重新发布问题,这样做的更好方法是什么?也许以及如何锁定缓存?我能比这更好吗?我只是希望它在删除或添加行时停止中断。

编辑:代码 SQLCacheDependency 不适用于 Remus 评论中发布的 LINQ。它适用于全表选择,但我只想从行中选择某些列。我不想选择整行,所以我不能使用 Remus 的想法。

以下代码示例均无效。

var ck = (from xx in db.GetInGroupNotCached
              where xx.rowID== rowID
              select new {                 
                  xx.Item,
                  xx.AnotherItem,
                  xx.AnotherItem,
                  }).CacheSql(db, "Item:" + rowID.ToString()).ToList();


var ck = (from xx in db.GetInGroupNotCached
              where xx.rowID== rowID
              select new ClassExample {              
                Item=  xx.Item,
                 AnotherItem= xx.AnotherItem,
                 AnotherItemm = xx.AnotherItemm,
                  }).CacheSql(db, "Item:" + rowID.ToString()).ToList();

最佳答案

我真的怀疑您的缓存解决方案是否真的有用。 List<T>无法编入索引,因此列表中的查找始终是 O(n) 操作。

假设您已经分析了您的应用程序并且知道数据库是您的瓶颈,这就是您可以做的:

在数据库中,您可以为数据创建索引,对它们的查找通常会显示 O(log(n))。您应该为包含静态数据的查询创建覆盖率索引。将频繁更改的数据保留为非索引,因为这会因必要的索引更新而减慢插入和更新的速度。您可以阅读 SQL Server 索引 here .获取 SQL Server Profiler 并检查哪些是最慢的查询以及原因。适当的索引可以让您获得巨大的性能提升(例如,您的 GroupId 上的索引将减少查找时间,从全表扫描 O(n) 到索引查找 O(n/25),假设每组有 25 个人) .

人们经常编写次优 SQL(返回不必要的列、选择 N+1、笛卡尔连接)。你也应该检查一下。

在实现缓存之前,我会确保您的数据库确实是性能问题的罪魁祸首。过早的优化是万恶之源,缓存很难做好。缓存频繁更改的数据并不是缓存的目的。

关于c# - 我应该如何将动态变化的数据存储到服务器缓存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2594440/

相关文章:

c# - Umbraco 7 中的表面 Controller 还是自定义 Controller ?

ASP.NET 将整数绑定(bind)到 CheckBox 的 Checked 字段

linux - 检查 Varnish 4 中超过 2 个 Web 服务器的后端健康状况

c# - ParentForm 为空(在 Form 内的 UserControl 内的 Button 中)!

c# - 如何将标签内容与查询中的值绑定(bind)?

c# - 使用 C# 创建名称中第一个字符为 '#' 的 Active Directory 组

c# - 如何在出现错误时优雅地退出我的应用程序?

jQuery 下拉列表

caching - Apollo writeFragment 不更新数据

javascript - 使用 JavaScript 使浏览器的缓存失效