From: Aaron Schulz Date: Wed, 15 Jul 2015 01:32:18 +0000 (-0700) Subject: Moved LoadMonitorMySQL to a separate file X-Git-Tag: 1.31.0-rc.0~10760^2 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/operations/?a=commitdiff_plain;h=528334e3a185991374a78a1aee131ee173cf2391;p=lhc%2Fweb%2Fwiklou.git Moved LoadMonitorMySQL to a separate file Change-Id: I529402416b8f12a511300b007b4f4aaf79054ad7 --- diff --git a/autoload.php b/autoload.php index 6444e3efa8..c4437343f2 100644 --- a/autoload.php +++ b/autoload.php @@ -678,7 +678,7 @@ $wgAutoloadLocalClasses = array( 'LoadBalancer' => __DIR__ . '/includes/db/LoadBalancer.php', 'LoadBalancerSingle' => __DIR__ . '/includes/db/LBFactorySingle.php', 'LoadMonitor' => __DIR__ . '/includes/db/LoadMonitor.php', - 'LoadMonitorMySQL' => __DIR__ . '/includes/db/LoadMonitor.php', + 'LoadMonitorMySQL' => __DIR__ . '/includes/db/LoadMonitorMySQL.php', 'LoadMonitorNull' => __DIR__ . '/includes/db/LoadMonitor.php', 'LocalFile' => __DIR__ . '/includes/filerepo/file/LocalFile.php', 'LocalFileDeleteBatch' => __DIR__ . '/includes/filerepo/file/LocalFile.php', diff --git a/includes/db/LoadMonitor.php b/includes/db/LoadMonitor.php index 01d2f95472..4975ea19dd 100644 --- a/includes/db/LoadMonitor.php +++ b/includes/db/LoadMonitor.php @@ -64,108 +64,3 @@ class LoadMonitorNull implements LoadMonitor { return array_fill_keys( $serverIndexes, 0 ); } } - -/** - * Basic MySQL load monitor with no external dependencies - * Uses memcached to cache the replication lag for a short time - * - * @ingroup Database - */ -class LoadMonitorMySQL implements LoadMonitor { - /** @var LoadBalancer */ - public $parent; - /** @var BagOStuff */ - protected $srvCache; - /** @var BagOStuff */ - protected $mainCache; - - public function __construct( $parent ) { - global $wgMemc; - - $this->parent = $parent; - - $this->srvCache = ObjectCache::newAccelerator( array(), 'hash' ); - $this->mainCache = $wgMemc ?: wfGetMainCache(); - } - - public function scaleLoads( &$loads, $group = false, $wiki = false ) { - } - - public function getLagTimes( $serverIndexes, $wiki ) { - if ( count( $serverIndexes ) == 1 && reset( $serverIndexes ) == 0 ) { - # Single server only, just return zero without caching - return array( 0 => 0 ); - } - - $key = $this->getLagTimeCacheKey(); - # Randomize TTLs to reduce stampedes (4.0 - 5.0 sec) - $ttl = mt_rand( 4e6, 5e6 ) / 1e6; - # Keep keys around longer as fallbacks - $staleTTL = 60; - - # (a) Check the local APC cache - $value = $this->srvCache->get( $key ); - if ( $value && $value['timestamp'] > ( microtime( true ) - $ttl ) ) { - wfDebugLog( 'replication', __FUNCTION__ . ": got lag times ($key) from local cache" ); - return $value['lagTimes']; // cache hit - } - $staleValue = $value ?: false; - - # (b) Check the shared cache and backfill APC - $value = $this->mainCache->get( $key ); - if ( $value && $value['timestamp'] > ( microtime( true ) - $ttl ) ) { - $this->srvCache->set( $key, $value, $staleTTL ); - wfDebugLog( 'replication', __FUNCTION__ . ": got lag times ($key) from main cache" ); - - return $value['lagTimes']; // cache hit - } - $staleValue = $value ?: $staleValue; - - # (c) Cache key missing or expired; regenerate and backfill - if ( $this->mainCache->lock( $key, 0, 10 ) ) { - # Let this process alone update the cache value - $cache = $this->mainCache; - $unlocker = new ScopedCallback( function () use ( $cache, $key ) { - $cache->unlock( $key ); - } ); - } elseif ( $staleValue ) { - # Could not acquire lock but an old cache exists, so use it - return $value['lagTimes']; - } - - $lagTimes = array(); - foreach ( $serverIndexes as $i ) { - if ( $i == 0 ) { # Master - $lagTimes[$i] = 0; - } elseif ( false !== ( $conn = $this->parent->getAnyOpenConnection( $i ) ) ) { - $lagTimes[$i] = $conn->getLag(); - } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) { - $lagTimes[$i] = $conn->getLag(); - # Close the connection to avoid sleeper connections piling up. - # Note that the caller will pick one of these DBs and reconnect, - # which is slightly inefficient, but this only matters for the lag - # time cache miss cache, which is far less common that cache hits. - $this->parent->closeConnection( $conn ); - } - } - - # Add a timestamp key so we know when it was cached - $value = array( 'lagTimes' => $lagTimes, 'timestamp' => microtime( true ) ); - $this->mainCache->set( $key, $value, $staleTTL ); - $this->srvCache->set( $key, $value, $staleTTL ); - wfDebugLog( 'replication', __FUNCTION__ . ": re-calculated lag times ($key)" ); - - return $value['lagTimes']; - } - - public function clearCaches() { - $key = $this->getLagTimeCacheKey(); - $this->srvCache->delete( $key ); - $this->mainCache->delete( $key ); - } - - private function getLagTimeCacheKey() { - # Lag is per-server, not per-DB, so key on the master DB name - return wfGlobalCacheKey( 'lag-times', $this->parent->getServerName( 0 ) ); - } -} diff --git a/includes/db/LoadMonitorMySQL.php b/includes/db/LoadMonitorMySQL.php new file mode 100644 index 0000000000..7c4a35c542 --- /dev/null +++ b/includes/db/LoadMonitorMySQL.php @@ -0,0 +1,125 @@ +parent = $parent; + + $this->srvCache = ObjectCache::newAccelerator( array(), 'hash' ); + $this->mainCache = $wgMemc ?: wfGetMainCache(); + } + + public function scaleLoads( &$loads, $group = false, $wiki = false ) { + } + + public function getLagTimes( $serverIndexes, $wiki ) { + if ( count( $serverIndexes ) == 1 && reset( $serverIndexes ) == 0 ) { + # Single server only, just return zero without caching + return array( 0 => 0 ); + } + + $key = $this->getLagTimeCacheKey(); + # Randomize TTLs to reduce stampedes (4.0 - 5.0 sec) + $ttl = mt_rand( 4e6, 5e6 ) / 1e6; + # Keep keys around longer as fallbacks + $staleTTL = 60; + + # (a) Check the local APC cache + $value = $this->srvCache->get( $key ); + if ( $value && $value['timestamp'] > ( microtime( true ) - $ttl ) ) { + wfDebugLog( 'replication', __FUNCTION__ . ": got lag times ($key) from local cache" ); + return $value['lagTimes']; // cache hit + } + $staleValue = $value ?: false; + + # (b) Check the shared cache and backfill APC + $value = $this->mainCache->get( $key ); + if ( $value && $value['timestamp'] > ( microtime( true ) - $ttl ) ) { + $this->srvCache->set( $key, $value, $staleTTL ); + wfDebugLog( 'replication', __FUNCTION__ . ": got lag times ($key) from main cache" ); + + return $value['lagTimes']; // cache hit + } + $staleValue = $value ?: $staleValue; + + # (c) Cache key missing or expired; regenerate and backfill + if ( $this->mainCache->lock( $key, 0, 10 ) ) { + # Let this process alone update the cache value + $cache = $this->mainCache; + $unlocker = new ScopedCallback( function () use ( $cache, $key ) { + $cache->unlock( $key ); + } ); + } elseif ( $staleValue ) { + # Could not acquire lock but an old cache exists, so use it + return $value['lagTimes']; + } + + $lagTimes = array(); + foreach ( $serverIndexes as $i ) { + if ( $i == 0 ) { # Master + $lagTimes[$i] = 0; + } elseif ( false !== ( $conn = $this->parent->getAnyOpenConnection( $i ) ) ) { + $lagTimes[$i] = $conn->getLag(); + } elseif ( false !== ( $conn = $this->parent->openConnection( $i, $wiki ) ) ) { + $lagTimes[$i] = $conn->getLag(); + # Close the connection to avoid sleeper connections piling up. + # Note that the caller will pick one of these DBs and reconnect, + # which is slightly inefficient, but this only matters for the lag + # time cache miss cache, which is far less common that cache hits. + $this->parent->closeConnection( $conn ); + } + } + + # Add a timestamp key so we know when it was cached + $value = array( 'lagTimes' => $lagTimes, 'timestamp' => microtime( true ) ); + $this->mainCache->set( $key, $value, $staleTTL ); + $this->srvCache->set( $key, $value, $staleTTL ); + wfDebugLog( 'replication', __FUNCTION__ . ": re-calculated lag times ($key)" ); + + return $value['lagTimes']; + } + + public function clearCaches() { + $key = $this->getLagTimeCacheKey(); + $this->srvCache->delete( $key ); + $this->mainCache->delete( $key ); + } + + private function getLagTimeCacheKey() { + # Lag is per-server, not per-DB, so key on the master DB name + return wfGlobalCacheKey( 'lag-times', $this->parent->getServerName( 0 ) ); + } +}