on my website, in order to display data in convient way to customer, I have to run complex SQL queries. There is not much to improve, as the data set is being changed very often. Therefore I want to create "timed" cache, let's say data should be valid for 2 minutes. This is trival, however, if entry gets old and need recalculation (which last let's say 1,5-3 seconds) I have to solve the problem, what if 20 customers will trigger cached value recalculation.
Is there any design pattern for this purpose? I was thinking about some synchronized boolean, let's say "updating" and displaying old value to other customers, but I am simply scared of locks... Also there is a problem what if the value is not yet in cache at all, e.g. after server restart. In basic words, I am looking for solution to multiple updates of the same value, when it needs to be calculated. In the past I lost a lot of nerves when trying to use JBoss Cache for this purpose.
I would be very grateful for any tips from you.
Without knowing the specifics of your current implementation it's hard to know what to suggest as the best solution for your situation.
If it were me I would start by encapsulating my database table access into a single point using the Repository Pattern (see Fowler's Patterns of Enterprise Application Architecture) and then implement my cache in there. If you route all read and write access through this repository then your cache becomes much easier as you don't have to constantly watch the db table for changes made elsewhere. This is ok as long as the db table is exclusively used by your single application. If you have a shared schema between systems then that's a whole other smell of its own, one which caching alone will not help you with.
You could have 2 caches. One that is read only and is displayed to the user. Other one is updated in the background . When its time to show the updated data to the user, swap the caches. This way you are locking the caches only when you swap them.
If multiple business components changing the database than situation is not easy
You can use dirty bit option in the database against each record. Any component which is making any DML should set the value to '1'
And after 2 minutes you can check only those records which are having dirty bit = '1'
You will refresh your cache and set the dirty bit to '0'
Maintaining two copies of Cache is also a good option
Michal Glowacki wrote: I would be very grateful for any tips from you.
Well, like Tim, without knowing more specifics, it's difficult to advise on what the best solution is, but I would definitely guard against statements like "there is not much to improve" - particularly when you clearly have a problem - because it sounds like you're saying: "I want a solution, but I'm not prepared to do a, b, c...".
You might want to look at my quote at the bottom, because that's exactly the sort of thinking it's referring to.
It sounds to me like you need to analyse your transactions thoroughly. Only then will you be in a position to:
(a) Ask for advice.
(b) Come up with a solution from the answers you're given.
Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here