【问题标题】:How to handle updating objects in cache?如何处理更新缓存中的对象?
【发布时间】:2015-09-15 21:41:10
【问题描述】:

我希望这是问这个问题的正确地方,但是在最近经历了一些奇怪的行为之后,我在执行some research 之后意识到,当使用 .NET 内存缓存并从缓存中检索对象时,您会检索到该对象的引用缓存中的对象,而不是对象的副本,因此对对象的任何更新都将保留在缓存中。

在下面的示例中,学生在StudentController 中更新,并再次检索CourseController,学生包含更新后的值而无需刷新缓存。

我最初的方法是在更新数据库后清除缓存的学生集合(因为我认为缓存的版本不会包含更新),但鉴于存在这种持久性,是否需要再次重新填充缓存数据库已更新?

    // Student controller
    public class StudentController : Controller
    {
        // omitted for brevity.

        public ActionResult UpdateStudent(int id)
        {                               
            var student = CollegeCache.Students[id];

            student.FirstName = "SpongeBob"

            studentRepository.update(student)   

            // CollegeCache.clearStudents();        
        }
    }

    // Course controller
    public class CourseController : Controller
    {
        // omitted for brevity.

        public ActionResult GetCoursesDetails(int id)
        {                               
            var student = CollegeCache.Students[id];

            // here student.FirstName will be "SpongeBob", and not it's original value.
        }
    }   

    // Cache helper class
    public static class CollegeCache
    {
        private static readonly ObjectCache cache = new MemoryCache("College");
        private static object locker = new object();

        public static readonly string StudentsKey = "StudentsKey";

        // Clears the entire cache store.
        public static void Clear()
        {
            foreach (var item in cache)
                cache.Remove(item.Key);
        }

        // Clears a single cache entry.
        public static void Clear(string key)
        {
            cache.Remove(key);
        }

        // Add to cache helper
        private static void Add(string key, object value, DateTimeOffset expiration,
            CacheItemPriority priority = CacheItemPriority.Default)
        {
            var policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = expiration;
            policy.Priority = priority;

            var item = new CacheItem(key, value);
            cache.Add(item, policy);
        }

        // Students cache store.
        public static Dictionary<int, Student> Students
        {
            get
            {
                var dictionary = cache[StudentsKey] as Dictionary<int, Student>;
                if (dictionary == null)
                {
                    lock (locker)
                    {
                        dictionary = db.Students.All().ToList().ToDictionary(a => a.Id);
                        Add(StudentsKey, dictionary, DateTime.Now.AddHours(1));
                    }
                }

                return dictionary;
            }
        }

        // Clears the users cache store.
        public static void ClearStudents()
        {
            Clear(StudentsKey);
        }
    }   

【问题讨论】:

  • 好吧。如果您更新底层数据源中的数据,那么您还必须在缓存中更新它,否则缓存中的数据未来获取的状态将比数据库中的数据陈旧且不稳定。你会不同步。您可以清除缓存并重新填充,但每次有更新时这都是一件昂贵的事情。您应该只在更新数据库中的数据然后更新缓存时更新
  • 我注意到的一件事是您没有显示“缓存”的定义位置和方式。如果您可以发布它会很好,但无论如何,我上面的评论仍然适用:)
  • @Ahmedilyas 我知道缓存存储需要与数据存储同步,这就是我试图解释的。当我更新存储在缓存中的对象时,我不需要清除和刷新缓存 - 更新对象时会更新缓存(即,无需刷新缓存)。我现在更新了代码以包含完整的缓存实现。
  • 感谢代码更新马克。是的-因为您更新了有问题的对象,所以缓存应该以某种方式“自动”更新(前提是您从缓存中获取了对象)但是我仍然会在缓存端进行显式更新,因为如果数据源怎么办抛出错误(即 SQLException)?您需要确保有问题的对象被准确更新:) 好东西!
  • @Ahmedilyas 谢谢,这种方法很有意义。

标签: c# asp.net-mvc caching


【解决方案1】:

一般来说,如果您更新基础数据源中的数据,那么您还必须在缓存中更新它,否则缓存中的数据未来获取的状态将比数据库中的数据陈旧且不稳定。你会不同步。您可以清除缓存并重新填充,但每次更新时这样做会很昂贵 - 出于上述原因,不建议这样做。仅当您成功更新数据库中的数据并更新缓存时才应更新。

由于您更新了有问题的对象,缓存应该以某种方式“自动”更新(前提是您从缓存中获取了对象)但是我仍然会在缓存端进行显式更新,因为如果数据源抛出错误(即 SQLException)?您需要确保正确更新相关对象,否则您会遇到数据完整性问题:)

【讨论】:

  • "您可以清除缓存并重新填充,但每次更新时这样做会很昂贵。您应该只在更新数据库中的数据然后更新缓存时更新“这两个不是一回事吗?
  • 你基本上是说每次更新数据库时都清除缓存,但这是一项昂贵的操作?
  • 不,这不是我要说的 :) 我是说不要在每次数据库更新后清除整个缓存。仅当您成功进行数据库更新时才更新缓存中的特定/相关项目。
  • 哦,对了——这更有意义! :) 但是,是的,这是我的方法 - 我只清除受影响的缓存存储。例如如果我更新一个学生,我会清除存储在缓存中的学生集合,而其他人不受影响,除非缓存存储之间存在依赖关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多