From 4825b4c08ebc1d55f6c2065cc3afe52a9b15f294 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Thu, 21 May 2015 12:05:39 -0700 Subject: [PATCH] Made ReplicatedBagOStuff wrapping the SQL class the default stash * To make this work, a slaveOnly flag was added to SqlBagOStuff and it no longer prunes expired items on get(), it just treats them as missing. The use of garbageCollect() for the writeFactory cache and the use of replace() on updates already makes this a non-issue. * This also makes the default $wgMainStash non-bogus. Bug: T88493 Change-Id: I9d1f31305e08430de29a3cd521cdb10a82dffd10 --- includes/DefaultSettings.php | 16 +++++++++++++++- includes/objectcache/SqlBagOStuff.php | 25 +++++++++++++++---------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 2ea8b294b6..052555c126 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -2151,6 +2151,19 @@ $wgObjectCaches = array( CACHE_ACCEL => array( 'factory' => 'ObjectCache::newAccelerator' ), CACHE_MEMCACHED => array( 'factory' => 'ObjectCache::newMemcached', 'loggroup' => 'memcached' ), + 'db-replicated' => array( + 'class' => 'ReplicatedBagOStuff', + 'readFactory' => array( + 'class' => 'SqlBagOStuff', + 'args' => array( array( 'slaveOnly' => true ) ) + ), + 'writeFactory' => array( + 'class' => 'SqlBagOStuff', + 'args' => array( array( 'slaveOnly' => false ) ) + ), + 'loggroup' => 'SQLBagOStuff' + ), + 'apc' => array( 'class' => 'APCBagOStuff' ), 'xcache' => array( 'class' => 'XCacheBagOStuff' ), 'wincache' => array( 'class' => 'WinCacheBagOStuff' ), @@ -2213,6 +2226,7 @@ $wgWANObjectCaches = array( * lightweight data like hit counters and user activity. Sites with multiple * data-centers should have this use a store that replicates all writes. The * store should have enough consistency for CAS operations to be usable. + * Reads outside of those needed for merge() may be eventually consistent. * * The options are: * - db: Store cache objects in the DB @@ -2221,7 +2235,7 @@ $wgWANObjectCaches = array( * * @since 1.26 */ -$wgMainStash = 'db'; +$wgMainStash = 'db-replicated'; /** * The expiry time for the parser cache, in seconds. diff --git a/includes/objectcache/SqlBagOStuff.php b/includes/objectcache/SqlBagOStuff.php index 82eeb842e8..05115c9af2 100644 --- a/includes/objectcache/SqlBagOStuff.php +++ b/includes/objectcache/SqlBagOStuff.php @@ -30,6 +30,7 @@ class SqlBagOStuff extends BagOStuff { /** @var LoadBalancer */ protected $lb; + /** @var array */ protected $serverInfos; /** @var array */ @@ -53,6 +54,9 @@ class SqlBagOStuff extends BagOStuff { /** @var string */ protected $tableName = 'objectcache'; + /** @var bool */ + protected $slaveOnly = false; + /** @var array UNIX timestamps */ protected $connFailureTimes = array(); @@ -84,6 +88,10 @@ class SqlBagOStuff extends BagOStuff { * required to hold the largest shard index. Data will be * distributed across all tables by key hash. This is for * MySQL bugs 61735 and 61736. + * - slaveOnly: Whether to only use slave DBs and avoid triggering + * garbage collection logic of expired items. This only + * makes sense if the primary DB is used and only if get() + * calls will be used. This is used by ReplicatedBagOStuff. * * @param array $params */ @@ -112,6 +120,7 @@ class SqlBagOStuff extends BagOStuff { if ( isset( $params['shards'] ) ) { $this->shards = intval( $params['shards'] ); } + $this->slaveOnly = !empty( $params['slaveOnly'] ); } /** @@ -155,12 +164,13 @@ class SqlBagOStuff extends BagOStuff { * However, SQLite has an opposite behavior. And PostgreSQL needs to know * if we are in transaction or no */ - if ( wfGetDB( DB_MASTER )->getType() == 'mysql' ) { + $index = $this->slaveOnly ? DB_SLAVE : DB_MASTER; + if ( wfGetDB( $index )->getType() == 'mysql' ) { $this->lb = wfGetLBFactory()->newMainLB(); - $db = $this->lb->getConnection( DB_MASTER ); + $db = $this->lb->getConnection( $index ); $db->clearFlag( DBO_TRX ); // auto-commit mode } else { - $db = wfGetDB( DB_MASTER ); + $db = wfGetDB( $index ); } } if ( $wgDebugDBTransactions ) { @@ -274,12 +284,7 @@ class SqlBagOStuff extends BagOStuff { try { $db = $this->getDB( $row->serverIndex ); if ( $this->isExpired( $db, $row->exptime ) ) { // MISS - $this->debug( "get: key has expired, deleting" ); - # Put the expiry time in the WHERE condition to avoid deleting a - # newly-inserted value - $db->delete( $row->tableName, - array( 'keyname' => $key, 'exptime' => $row->exptime ), - __METHOD__ ); + $this->debug( "get: key has expired" ); } else { // HIT $values[$key] = $this->unserialize( $db->decodeBlob( $row->value ) ); } @@ -546,7 +551,7 @@ class SqlBagOStuff extends BagOStuff { } protected function garbageCollect() { - if ( !$this->purgePeriod ) { + if ( !$this->purgePeriod || $this->slaveOnly ) { // Disabled return; } -- 2.20.1