browserCDNappdatabase1def get_price(item):2 p = cache.get(item)3 if p is not None:4 return p5 p = db.load(item)6 cache.set(item, p, ex=60)7 return ptea cake $6pie $7jam $2$31def set_price(item, p):2 db.save(item, p)3 cache.delete(item)$3None$6
Back row: browser, CDN, app server and database (the database is the source of truth)Middle and front: the Redis cache's three slots, the prices table and the two Python cardsEnvelopes carry each ask; pucks carry prices; a cross is a miss, a tick a hit; the clock is the TTLAt the back: a browser, a CDN, the app server and the database. In the middle: a three-slot Redis cache and the database's prices table. In front: get_price, the cache-aside read path, and set_price, the write path. The first read of tea misses and loads $3 from the database; the app keeps a copy for 60 seconds, so the next read hits. A change made straight in the database leaves the copy stale until its time to live runs out; set_price saves and deletes the copy instead. When the cache is full, the least recently used copy is evicted. The figure's cache has exactly three slots so eviction is easy to see. A real Redis is limited by memory (maxmemory), and by default it refuses new writes when full (noeviction) unless you choose a policy such as allkeys-lru.

The idea

  1. Some answers are slow to get: the database may have to read its disk and do real work. A cache is a small, fast store in memory that keeps copies of answers, so asking again is quick.

Cache-aside, step by step

Keeping copies fresh

Full caches and layers

What happens

;; step 1/10 · idea
cache     a small, fast store that keeps copies
          here: Redis, keys and values in memory
database  the source of truth, slower to ask
main memory read      about 100 ns
new disk spot (seek)  about 8,000,000 ns (8 ms)
cache now [ empty | empty | empty ]

The figure's cache has exactly three slots so eviction is easy to see. A real Redis is limited by memory (maxmemory), and by default it refuses new writes when full (noeviction) unless you choose a policy such as allkeys-lru. Redis does not track exact LRU order: it samples a few keys and evicts the oldest of the sample, which comes close to true LRU. The figure shows exact LRU.