X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Flibs%2Fobjectcache%2FWANObjectCache.php;h=d9398196f5d4d9d03c45f0f0ee4a55a3d62f1ae8;hp=08424c9c8adb5e08ed0721982725ca3e6942a6fb;hb=7206bd34682d1ed922a72b443759f81ddda44fcf;hpb=0613928b342092c9751f6270565fa8457ec7d6b4 diff --git a/includes/libs/objectcache/WANObjectCache.php b/includes/libs/objectcache/WANObjectCache.php index 08424c9c8a..d9398196f5 100644 --- a/includes/libs/objectcache/WANObjectCache.php +++ b/includes/libs/objectcache/WANObjectCache.php @@ -47,17 +47,23 @@ use Psr\Log\NullLogger; * There are three supported ways to handle broadcasted operations: * - a) Configure the 'purge' EventRelayer to point to a valid PubSub endpoint * that has subscribed listeners on the cache servers applying the cache updates. - * - b) Ignore the 'purge' EventRelayer configuration (default is NullEventRelayer) - * and set up mcrouter as the underlying cache backend, using one of the memcached - * BagOStuff classes as 'cache'. Use OperationSelectorRoute in the mcrouter settings - * to configure 'set' and 'delete' operations to go to all DCs via AllAsyncRoute and - * configure other operations to go to the local DC via PoolRoute (for reference, - * see https://github.com/facebook/mcrouter/wiki/List-of-Route-Handles). - * - c) Ignore the 'purge' EventRelayer configuration (default is NullEventRelayer) - * and set up dynomite as cache middleware between the web servers and either - * memcached or redis. This will also broadcast all key setting operations, not just purges, - * which can be useful for cache warming. Writes are eventually consistent via the - * Dynamo replication model (see https://github.com/Netflix/dynomite). + * - b) Ommit the 'purge' EventRelayer parameter and set up mcrouter as the underlying cache + * backend, using a memcached BagOStuff class for the 'cache' parameter. The 'region' + * and 'cluster' parameters must be provided and 'mcrouterAware' must be set to 'true'. + * Configure mcrouter as follows: + * - 1) Use Route Prefixing based on region (datacenter) and cache cluster. + * See https://github.com/facebook/mcrouter/wiki/Routing-Prefix and + * https://github.com/facebook/mcrouter/wiki/Multi-cluster-broadcast-setup + * - 2) To increase the consistency of delete() and touchCheckKey() during cache + * server membership changes, you can use the OperationSelectorRoute to + * configure 'set' and 'delete' operations to go to all servers in the cache + * cluster, instead of just one server determined by hashing. + * See https://github.com/facebook/mcrouter/wiki/List-of-Route-Handles + * - c) Ommit the 'purge' EventRelayer parameter and set up dynomite as cache middleware + * between the web servers and either memcached or redis. This will also broadcast all + * key setting operations, not just purges, which can be useful for cache warming. + * Writes are eventually consistent via the Dynamo replication model. + * See https://github.com/Netflix/dynomite * * Broadcasted operations like delete() and touchCheckKey() are done asynchronously * in all datacenters this way, though the local one should likely be near immediate. @@ -87,6 +93,12 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { protected $purgeChannel; /** @var EventRelayer Bus that handles purge broadcasts */ protected $purgeRelayer; + /** @bar bool Whether to use mcrouter key prefixing for routing */ + protected $mcrouterAware; + /** @var string Physical region for mcrouter use */ + protected $region; + /** @var string Cache cluster name for mcrouter use */ + protected $cluster; /** @var LoggerInterface */ protected $logger; /** @var StatsdDataFactoryInterface */ @@ -200,6 +212,16 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * callback supplied by the getWithSetCallback() caller. The result will be saved * as normal. The handler is expected to call the WAN cache callback at an opportune * time (e.g. HTTP post-send), though generally within a few 100ms. [optional] + * - region: the current physical region. This is required when using mcrouter as the + * backing store proxy. [optional] + * - cluster: name of the cache cluster used by this WAN cache. The name must be the + * same in all datacenters; the ("region","cluster") tuple is what distinguishes + * the counterpart cache clusters among all the datacenter. The contents of + * https://github.com/facebook/mcrouter/wiki/Config-Files give background on this. + * This is required when using mcrouter as the backing store proxy. [optional] + * - mcrouterAware: set as true if mcrouter is the backing store proxy and mcrouter + * is configured to interpret /// key prefixes as routes. This + * requires that "region" and "cluster" are both set above. [optional] */ public function __construct( array $params ) { $this->cache = $params['cache']; @@ -209,6 +231,10 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { $this->purgeRelayer = isset( $params['relayers']['purge'] ) ? $params['relayers']['purge'] : new EventRelayerNull( [] ); + $this->region = isset( $params['region'] ) ? $params['region'] : 'main'; + $this->cluster = isset( $params['cluster'] ) ? $params['cluster'] : 'wan-main'; + $this->mcrouterAware = !empty( $params['mcrouterAware'] ); + $this->setLogger( isset( $params['logger'] ) ? $params['logger'] : new NullLogger() ); $this->stats = isset( $params['stats'] ) ? $params['stats'] : new NullStatsdDataFactory(); $this->asyncHandler = isset( $params['asyncHandler'] ) ? $params['asyncHandler'] : null; @@ -1779,9 +1805,18 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * @return bool Success */ protected function relayPurge( $key, $ttl, $holdoff ) { - if ( $this->purgeRelayer instanceof EventRelayerNull ) { + if ( $this->mcrouterAware ) { + // See https://github.com/facebook/mcrouter/wiki/Multi-cluster-broadcast-setup + // Wildcards select all matching routes, e.g. the WAN cluster on all DCs + $ok = $this->cache->set( + "/*/{$this->cluster}/{$key}", + $this->makePurgeValue( $this->getCurrentTime(), self::HOLDOFF_NONE ), + $ttl + ); + } elseif ( $this->purgeRelayer instanceof EventRelayerNull ) { // This handles the mcrouter and the single-DC case - $ok = $this->cache->set( $key, + $ok = $this->cache->set( + $key, $this->makePurgeValue( $this->getCurrentTime(), self::HOLDOFF_NONE ), $ttl ); @@ -1810,8 +1845,12 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * @return bool Success */ protected function relayDelete( $key ) { - if ( $this->purgeRelayer instanceof EventRelayerNull ) { - // This handles the mcrouter and the single-DC case + if ( $this->mcrouterAware ) { + // See https://github.com/facebook/mcrouter/wiki/Multi-cluster-broadcast-setup + // Wildcards select all matching routes, e.g. the WAN cluster on all DCs + $ok = $this->cache->delete( "/*/{$this->cluster}/{$key}" ); + } elseif ( $this->purgeRelayer instanceof EventRelayerNull ) { + // Some other proxy handles broadcasting or there is only one datacenter $ok = $this->cache->delete( $key ); } else { $event = $this->cache->modifySimpleRelayEvent( [