4 ms·
> Good work, but not a solution for cache invalidation. Assuming your definition of cache invalidation is about "when/who" to invalidate on writes. Let's actua
by uvdn7 4y ago
> Good work, but not a solution for cache invalidation.
Assuming your definition of cache invalidation is about "when/who" to invalidate on writes. Let's actually try solving it.
E.g. in its most generic form, a cache can store arbitrary materialization from any data source. Now when updating the data source, in order to keep caches consistent, you essentially need to transact (cross system transaction) on both the data source and cache(s). Usually cache has more number of replicas, I am not sure running this type of transactions is practical at scale.
What happens if we don't transact on both systems (the data source, and cache)? Well, now whenever the asynchronous update pipeline performs the computation, it's done against a moving data source (not a snapshot of when the write was committed). Now let's say the data source is Spanner, which provides point-in-time snapshots. On Spanner commit you can get a commit time (TrueTime) back. Now using that commit time, to read the data and compute cache update asynchronously can be done.
Because the materialization in cache don't take writes themselves, so updates to them are essentially performed blindly and can be ordered by the commit time (TrueTime).
Now this does assume whatever we cache (the query e.g.) needs to be schematized, and made known to the invalidation pipeline. I think it's a very fair assumption to make. As otherwise (anyone can cache anything without the invalidation pipeline knowing at all), it's pretty obvious that this problem can't be solved.
- uvdn7 4y agoMore details can be found at https://blog.the-pans.com/when-and-how-to-invalidate-cache/ https://blog.the-pans.com/when-and-how-to-invalidate-cache/
- yencabulator 4y agoFrom the article: - client starts a transaction - client runs any mutations as needed - client collects user_ids whose cache entries need to be invalidated - client invalidates cache - client commits the transaction You can now have caches fetching & storing the "old" state between the last two steps. This fails to invalidate cache in all scenarios.
- gigatexal 4y agoSo they didn't solve one of the fundamentally difficult things related to computing. I knew it was probably good to be dubious of such claims.
- uvdn7 4y agoI will not say cache invalidation is easy; and I am not trying to minimize anyone’s struggles. But cache invalidation is _not_ like FLP impossibility or CAP. Too many systems reason caching (inherently a distributed system) in an ad-hoc way that leads to failures and this belief that cache invalidation is uniquely hard (https://twitter.com/marcjbrooker/status/1534944338341310470?s=21&t=pXvsxVPPUZryP1VpWdgpmQ https://twitter.com/marcjbrooker/status/1534944338341310470?...). https://en.wikipedia.org/wiki/Consensus_(computer_science) https://en.wikipedia.org/wiki/Consensus_(computer_science) https://en.wikipedia.org/wiki/CAP_theorem https://en.wikipedia.org/wiki/CAP_theorem
- uvdn7 4y agoGood catch! I shouldn't have omitted the details here. Roughly there are two ways to solve the race you mentioned here. You can use a versioning scheme supported by the database to do compare-and-swap – i.e. sending invalidate along with a hybrid-logical-clock. HLC is nice in this case as it handles DB transaction rollback gracefully, if the database supports it. Or we can always do the invalidation asynchronously (by recording the invalidation keys transactionally and have a tailer that sends out the invalidation). I will make an edit to the blog to make it more clear. Let me know if that makes sense! I mean this – cache invalidate/fill race specifically – is very much a solved problem from a protocol perspective, as long as our definition of the problem is the same – do not leave stale data in cache indefinitely. That is not to say it is easy; I am not trying to minimize anyone's struggles. https://research.facebook.com/publications/scaling-memcache-at-facebook/ https://research.facebook.com/publications/scaling-memcache-... might be of interest. A lot of the challenges in cache are in making the tradeoffs between consistency and coordination overhead based on the workload and the requirement, _and actually_ making caches consistent in production. As explained in the post, there are practical challenges that are very unique to cache and cache invalidation.