How to support lazy loading using TreeCache?
dasfrosty Jun 17, 2004 8:43 PMCurrently we are using a home grown caching solution to avoid multiple lookups of the same object from the database. However our own caching logic is not transaction aware, so we are looking to replace it with a third party caching solution that is, potentially TreeCache.
Our home grown solution takes a lazy loading type approach which does not seem to be completely compatible with how TreeCache is implemented:
- When an object is requested try to get it from the local cache.
- If the object's not in the local cache load it from the database and put it in the local cache.
- Return a clone of the object to the requestor.
- When an object is modified save it to the database and send a message to all cache instances in the cluster that the old version of the object is now invalid and should be removed. (I purposefully am avoiding the word "eviction" here since this is not triggered by the cache being too full or the object being left idle too long.)
- The next time the object is requested the modified version will be retrieved from the database and stored in the cache.
In trying to use TreeCache to support this same approach I have encountered differences in the design of TreeCache that appear to open the door to potential inconsistencies in the cache contents.
Because TreeCache treats puts as write operations in all cases, lazy loading of an object is replicated across all instances of the cache (assuming replication is enabled). In our current implementation an object is loaded into only the cache instance that is local to the client requesting the object. Propagating the lazy load to other cache instances seems to me undesirable for a couple reasons:
1. Adds unecessary overhead (although this could potentially reduce database calls in some situations)
2. Can lead to stale data being propagated to other cache instances.
To illustrate #2 consider the following scenario:
- thread1 in tx1 puts object in cache1
- thread1 modifies object -> object'
- thread2 in tx2 puts object in cache2
- thread1 removes object from cache1
- thread1 commits tx1 (object' stored in repository)
- thread2 commits tx2 (w/o modifying object)
- cache1 sends update to cache2
- cache2 sends update to cache1
- cache1 adds ref to object
- cache2 removes ref to object
- cache1 has ref to object while db contains object'
Am I misunderstanding something about the way TreeCache functions or is there another way to do lazy loading with TreeCache that doesn't allow this kind of inconsistency to occur?
Thanks,
Niels