Generally we would recommend using Read-Through Caching.
- The client(s) go to Coherence looking for a value.
- If it is not there, Coherence locks the key
- The Coherence Worker thread goes to the database and loads the value
- Everyone is returned the value
Coherence Cache Aside has very bad press (my friend Lewis Foti once offered to shoot anyone who used it again ).
- The client goes to Coherence looking for a value
- If a NULL value is returned to the client it loads from the database
- The client then puts the value returned into Coherence
Cache-Aside is usually chosen for two reasons:
- Database code is written in C#, Read-Through code needs to be written in Java, so Cache-Aside is used.
- Legacy. Cache-Aside has been used an the technical debt of moving to Read-Through is too high
Consider now the case where you have 6000 Grid clients (we have this scenario). The cluster starts up and all the clients try and download the currency rates. Suddenly you see 6000 hits on the database table and the database falls over.
This problem does not occur with ReadThrough since Coherence has a lock and only one client goes to the database at a time per key.
- Use a WrapperNamedCache to intercept all calls to GET
- Use an EntryProcessor or Trigger
- If Coherence sees a NULL value it sets the value to LOADING with a TTL (say 10s) and returns a LOAD command to the client
- The client loads from the database and sets the value in Coherence
- Other clients (say 6000) receive the command LOADING and retry (say in 500ms) - they do NOT hit the database
- If the client dies the load will postpone for TTL (say 10s) then the next client that hits will go back to point 3 until someone successfully loads the value
- Everyone now gets the correct value
I tried a solution using a blocking EntryProcessor. Unfortunately, this causes thread starvation on the Server see Non-proliferation of Coherence Services
To Nick Funnell and Toyin Akin for their input on this.