Re: Rush conditions after APC TTLs expire
| From: | Rasmus Lerdorf | Date: | Thu, 17 Dec 2009 17:36:29 +0000 |
| Subject: | Re: Rush conditions after APC TTLs expire | ||
| References: | 1 | Groups: | php.pecl.dev |
| Request: | Send a blank email to pecl-dev+get-6922@lists.php.net to get a copy of this message | ||
That doesn't seem like a very robust mechanism. The normal way to
update user cache items on high-load sites is to simply ensure that only
a single process does it. People do this either by having a special
endpoint that a cron job hits occasionally making sure it is never
user-triggered, or alternatively, use apc_add() to add the pid of the
process that is currently updating. Since apc_add() is atomic you can
do something along the lines of:
$pid = getmypid();
apc_add("update_lock",$pid);
if(apc_fetch("update_lock"==$pid)) {
// Got update lock
...
}
-Rasmus
Richard wrote:
> When using APC with a user set TTL it seems that between the end of the
> TTL and the new item being re-cached all requests for this item will
> cause the object to be generated.
>
> This behaviour seems unavoidable based on the APC design and most of the
> time is is probably not an issue however if you have really high numbers
> of requests it can make the APC cache ineffective as a means to protect
> a backend resource.
>
> I know there are a lot of other cache systems like memcached that are
> better for this kind of problem but I wanted to see how people feel about
> the idea expressed in the attached patch.
>
> It adds two global config items
> - apc.ttl_preempt - percentage between 0 and 100 (defaults to 0/off)
> - apc.ttl_preempt_count - >0 (defaults to 1)
>
> ttl_preempt represents the percentage of the user set TTL after witch to
> allow ttl_preempt_count users to update the cache whilst all others use
> the old object.
>
> For example if you have apc.ttl_preempt set to 50 and
> apc.ttl_preempt_count set to 1, a variable in cache with a TTL of 30
> that is more then 15 seconds old will return that it's not in the cache
> for one request while others still get the cached version. Once this
> request has updated the cache all request will get the new version and
> the age of the cached item will be back to zero.
>
> This avoids the sudden rush effect at the end of a TTL on a cached item
> since it will be unlikely during high load to reach the TTL before a
> preempted replacement has happened.
>
> ttl_preempt_count would be set to numbers larger then one if you expect
> some request to fail to populate the cache, I would expect if to be
> unusual to need this in most cases.
>
> This works better for longer TTLs and will only protect the resource if
> the amount of time left in the TTL is greater then the length of time it
> takes to generate the cache item. It would also probably be better to
> allow setting the preempt values for each cache item rather then globally.
>
> I am not familiar with the APC code so apologies for how rough the patch
> is, happy to work more on it if the idea is liked.
>
> Richard.
>