4 * An interface for database load monitoring
7 interface LoadMonitor
{
9 * Construct a new LoadMonitor with a given LoadBalancer parent
11 function __construct( $parent );
14 * Perform pre-connection load ratio adjustment.
16 * @param string $group The selected query group
19 function scaleLoads( &$loads, $group = false, $wiki = false );
22 * Perform post-connection backoff.
24 * If the connection is in overload, this should return a backoff factor
25 * which will be used to control polling time. The number of threads
26 * connected is a good measure.
28 * If there is no overload, zero can be returned.
30 * A threshold thread count is given, the concrete class may compare this
31 * to the running thread count. The threshold may be false, which indicates
32 * that the sysadmin has not configured this feature.
34 * @param Database $conn
35 * @param float $threshold
37 function postConnectionBackoff( $conn, $threshold );
40 * Return an estimate of replication lag for each server
42 function getLagTimes( $serverIndexes, $wiki );
47 * Basic MySQL load monitor with no external dependencies
48 * Uses memcached to cache the replication lag for a short time
51 class LoadMonitor_MySQL
implements LoadMonitor
{
52 var $parent; // LoadBalancer
54 function __construct( $parent ) {
55 $this->parent
= $parent;
58 function scaleLoads( &$loads, $group = false, $wiki = false ) {
61 function getLagTimes( $serverIndexes, $wiki ) {
62 wfProfileIn( __METHOD__
);
67 $masterName = $this->parent
->getServerName( 0 );
68 $memcKey = wfMemcKey( 'lag_times', $masterName );
69 $times = $wgMemc->get( $memcKey );
71 # Randomly recache with probability rising over $expiry
72 $elapsed = time() - $times['timestamp'];
73 $chance = max( 0, ( $expiry - $elapsed ) * $requestRate );
74 if ( mt_rand( 0, $chance ) != 0 ) {
75 unset( $times['timestamp'] );
76 wfProfileOut( __METHOD__
);
79 wfIncrStats( 'lag_cache_miss_expired' );
81 wfIncrStats( 'lag_cache_miss_absent' );
84 # Cache key missing or expired
87 foreach ( $serverIndexes as $i ) {
88 if ($i == 0) { # Master
90 } elseif ( false !== ( $conn = $this->parent
->getAnyOpenConnection( $i ) ) ) {
91 $times[$i] = $conn->getLag();
92 } elseif ( false !== ( $conn = $this->parent
->openConnection( $i, $wiki ) ) ) {
93 $times[$i] = $conn->getLag();
97 # Add a timestamp key so we know when it was cached
98 $times['timestamp'] = time();
99 $wgMemc->set( $memcKey, $times, $expiry );
101 # But don't give the timestamp to the caller
102 unset($times['timestamp']);
105 wfProfileOut( __METHOD__
);
109 function postConnectionBackoff( $conn, $threshold ) {
113 $status = $conn->getStatus("Thread%");
114 if ( $status['Threads_running'] > $threshold ) {
115 return $status['Threads_connected'];