From: Aaron Schulz Date: Thu, 25 Sep 2014 18:58:16 +0000 (-0700) Subject: Simplified getMaxLag() to use getLagTimes() X-Git-Tag: 1.31.0-rc.0~13810^2 X-Git-Url: http://git.cyclocoop.org/%24image?a=commitdiff_plain;h=855a19ec86c1a9ef0d732ab4df133e5737b3fca0;p=lhc%2Fweb%2Fwiklou.git Simplified getMaxLag() to use getLagTimes() * This method now benefits from more cache sharing and de-duplicated lag time querying to reduce connection stampedes. Change-Id: I2f3b9a22e4adabea703fbae1f96e65fb65125e2b --- diff --git a/includes/db/LoadBalancer.php b/includes/db/LoadBalancer.php index 0ccbd933ae..9797f298fa 100644 --- a/includes/db/LoadBalancer.php +++ b/includes/db/LoadBalancer.php @@ -58,8 +58,8 @@ class LoadBalancer { private $mLaggedSlaveMode; /** @var string The last DB selection or connection error */ private $mLastError = 'Unknown error'; - /** @var array Process cache of LoadMonitor::getLagTimes() */ - private $mLagTimes; + /** @var ProcessCacheLRU */ + private $mProcCache; /** * @param array $params Array with keys: @@ -108,6 +108,8 @@ class LoadBalancer { } } } + + $this->mProcCache = new ProcessCacheLRU( 30 ); } /** @@ -1080,7 +1082,8 @@ class LoadBalancer { } /** - * Get the hostname and lag time of the most-lagged slave. + * Get the hostname and lag time of the most-lagged slave + * * This is useful for maintenance scripts that need to throttle their updates. * May attempt to open connections to slaves on the default DB. If there is * no lag, the maximum lag will be reported as -1. @@ -1093,67 +1096,45 @@ class LoadBalancer { $host = ''; $maxIndex = 0; - if ( $this->getServerCount() <= 1 ) { // no replication = no lag - return array( $host, $maxLag, $maxIndex ); + if ( $this->getServerCount() <= 1 ) { + return array( $host, $maxLag, $maxIndex ); // no replication = no lag } - // Try to get the max lag info from the server cache - $key = 'loadbalancer:maxlag:cluster:' . $this->mServers[0]['host']; - $cache = ObjectCache::newAccelerator( array(), 'hash' ); - $maxLagInfo = $cache->get( $key ); // (host, lag, index) - - // Fallback to connecting to each slave and getting the lag - if ( !$maxLagInfo ) { - foreach ( $this->mServers as $i => $conn ) { - if ( $i == $this->getWriterIndex() ) { - continue; // nothing to check - } - $conn = false; - if ( $wiki === false ) { - $conn = $this->getAnyOpenConnection( $i ); - } - if ( !$conn ) { - $conn = $this->openConnection( $i, $wiki ); - } - if ( !$conn ) { - continue; - } - $lag = $conn->getLag(); - if ( $lag > $maxLag ) { - $maxLag = $lag; - $host = $this->mServers[$i]['host']; - $maxIndex = $i; - } + $lagTimes = $this->getLagTimes( $wiki ); + foreach ( $lagTimes as $i => $lag ) { + if ( $lag > $maxLag ) { + $maxLag = $lag; + $host = $this->mServers[$i]['host']; + $maxIndex = $i; } - $maxLagInfo = array( $host, $maxLag, $maxIndex ); - $cache->set( $key, $maxLagInfo, 5 ); } - return $maxLagInfo; + return array( $host, $maxLag, $maxIndex ); } /** * Get lag time for each server - * Results are cached for a short time in memcached, and indefinitely in the process cache + * + * Results are cached for a short time in memcached/process cache * * @param string|bool $wiki * @return array Map of (server index => seconds) */ function getLagTimes( $wiki = false ) { - # Try process cache - if ( isset( $this->mLagTimes ) ) { - return $this->mLagTimes; + if ( $this->getServerCount() <= 1 ) { + return array( 0 => 0 ); // no replication = no lag } - if ( $this->getServerCount() == 1 ) { - # No replication - $this->mLagTimes = array( 0 => 0 ); - } else { - # Send the request to the load monitor - $this->mLagTimes = $this->getLoadMonitor()->getLagTimes( - array_keys( $this->mServers ), $wiki ); + + if ( $this->mProcCache->has( 'slave_lag', 'times', 1 ) ) { + return $this->mProcCache->get( 'slave_lag', 'times' ); } - return $this->mLagTimes; + # Send the request to the load monitor + $times = $this->getLoadMonitor()->getLagTimes( array_keys( $this->mServers ), $wiki ); + + $this->mProcCache->set( 'slave_lag', 'times', $times ); + + return $times; } /** @@ -1179,10 +1160,10 @@ class LoadBalancer { } /** - * Clear the cache for getLagTimes + * Clear the cache for slag lag delay times */ function clearLagTimeCache() { - $this->mLagTimes = null; + $this->mProcCache->clear( 'slave_lag' ); } } diff --git a/includes/jobqueue/JobRunner.php b/includes/jobqueue/JobRunner.php index e38aa5ff03..4d2c618dec 100644 --- a/includes/jobqueue/JobRunner.php +++ b/includes/jobqueue/JobRunner.php @@ -77,8 +77,7 @@ class JobRunner { } // Bail out if there is too much DB lag - // @note: getLagTimes() has better caching than getMaxLag() - $maxLag = max( wfGetLBFactory()->getMainLB( wfWikiID() )->getLagTimes() ); + list( , $maxLag ) = wfGetLBFactory()->getMainLB( wfWikiID() )->getMaxLag(); if ( $maxLag >= 5 ) { $response['reached'] = 'slave-lag-limit'; return $response;