diff --git a/core/core.services.yml b/core/core.services.yml
index 3e2feb6..a666703 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -32,6 +32,15 @@ services:
     class: Drupal\Core\Cache\TimeZoneCacheContext
     tags:
       - { name: cache.context}
+  cache_tags:
+    class: Drupal\Core\Cache\CacheTagHandler
+    tags:
+      - { name: service_collector }
+  cache_tag_storage:
+    class: Drupal\Core\Cache\DatabaseCacheTagStorage
+    arguments: ['@database']
+    tags:
+      - { name: cache_tags }
   cache.backend.chainedfast:
     class: Drupal\Core\Cache\ChainedFastBackendFactory
     arguments: ['@settings']
@@ -39,12 +48,16 @@ services:
       - [setContainer, ['@service_container']]
   cache.backend.database:
     class: Drupal\Core\Cache\DatabaseBackendFactory
-    arguments: ['@database']
+    arguments: ['@database', '@cache_tag_storage']
   cache.backend.apcu:
     class: Drupal\Core\Cache\ApcuBackendFactory
     arguments: ['@app.root']
+    tags:
+      - { name: cache_tags }
   cache.backend.php:
     class: Drupal\Core\Cache\PhpBackendFactory
+    tags:
+      - { name: cache_tags }
   cache.bootstrap:
     class: Drupal\Core\Cache\CacheBackendInterface
     tags:
@@ -98,6 +111,7 @@ services:
     class: Drupal\Core\Cache\CacheBackendInterface
     tags:
       - { name: cache.bin, default_backend: cache.backend.chainedfast }
+      - { name: cache_tags }
     factory_method: get
     factory_service: cache_factory
     arguments: [discovery]
diff --git a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
index ffe5993..dd77ed1 100644
--- a/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/ApcuBackendFactory.php
@@ -9,7 +9,7 @@
 
 use \Drupal\Component\Utility\Crypt;
 
-class ApcuBackendFactory implements CacheFactoryInterface {
+class ApcuBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface {
 
   /**
    * The site prefix string.
@@ -41,4 +41,43 @@ public function get($bin) {
     return new ApcuBackend($bin, $this->sitePrefix);
   }
 
+  /**
+   * Deletes items with any of the specified tags.
+   *
+   * If the cache items are being deleted because they are no longer "fresh",
+   * you may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   */
+  public function deleteTags(array $tags) {
+    // TODO: Implement deleteTags() method.
+  }
+
+  /**
+   * Marks cache items with any of the specified tags as invalid.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
+   */
+  public function invalidateTags(array $tags) {
+    // TODO: Implement invalidateTags() method.
+  }
 }
diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php
index ddf444e..b8e6cdc 100644
--- a/core/lib/Drupal/Core/Cache/Cache.php
+++ b/core/lib/Drupal/Core/Cache/Cache.php
@@ -96,41 +96,25 @@ public static function buildTags($prefix, array $suffixes) {
   /**
    * Deletes items from all bins with any of the specified tags.
    *
-   * Many sites have more than one active cache backend, and each backend may
-   * use a different strategy for storing tags against cache items, and
-   * deleting cache items associated with a given tag.
-   *
-   * When deleting a given list of tags, we iterate over each cache backend, and
-   * and call deleteTags() on each.
-   *
    * @param string[] $tags
    *   The list of tags to delete cache items for.
    */
   public static function deleteTags(array $tags) {
+    // @todo Move to service.
     static::validateTags($tags);
-    foreach (static::getBins() as $cache_backend) {
-      $cache_backend->deleteTags($tags);
-    }
+    \Drupal::service('cache_tags')->deleteTags($tags);
   }
 
   /**
    * Marks cache items from all bins with any of the specified tags as invalid.
    *
-   * Many sites have more than one active cache backend, and each backend my use
-   * a different strategy for storing tags against cache items, and invalidating
-   * cache items associated with a given tag.
-   *
-   * When invalidating a given list of tags, we iterate over each cache backend,
-   * and call invalidateTags() on each.
-   *
    * @param string[] $tags
    *   The list of tags to invalidate cache items for.
    */
   public static function invalidateTags(array $tags) {
+    // @todo Move to service.
     static::validateTags($tags);
-    foreach (static::getBins() as $cache_backend) {
-      $cache_backend->invalidateTags($tags);
-    }
+    \Drupal::service('cache_tags')->invalidateTags($tags);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
index 39c8c26..fd1ae87 100644
--- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
+++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
@@ -18,7 +18,7 @@
  *
  * @ingroup cache
  */
-interface CacheBackendInterface {
+interface CacheBackendInterface extends CacheTagInvalidationInterface {
 
   /**
    * Indicates that the item should never be removed unless explicitly deleted.
@@ -161,27 +161,6 @@ public function delete($cid);
   public function deleteMultiple(array $cids);
 
   /**
-   * Deletes items with any of the specified tags.
-   *
-   * If the cache items are being deleted because they are no longer "fresh",
-   * you may consider using invalidateTags() instead. This allows callers to
-   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
-   * In some cases an invalid item may be acceptable rather than having to
-   * rebuild the cache.
-   *
-   * @param array $tags
-   *   Associative array of tags, in the same format that is passed to
-   *   CacheBackendInterface::set().
-   *
-   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
-   */
-  public function deleteTags(array $tags);
-
-  /**
    * Deletes all cache items in a bin.
    *
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
@@ -224,21 +203,6 @@ public function invalidate($cid);
   public function invalidateMultiple(array $cids);
 
   /**
-   * Marks cache items with any of the specified tags as invalid.
-   *
-   * @param array $tags
-   *   Associative array of tags, in the same format that is passed to
-   *   CacheBackendInterface::set().
-   *
-   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
-   */
-  public function invalidateTags(array $tags);
-
-  /**
    * Marks all cache items as invalid.
    *
    * Invalid items may be returned in later calls to get(), if the $allow_invalid
diff --git a/core/lib/Drupal/Core/Cache/CacheTagHandler.php b/core/lib/Drupal/Core/Cache/CacheTagHandler.php
new file mode 100644
index 0000000..d439954
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagHandler.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagHandler.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Passes cache tag events to classes that wish to respond to them.
+ */
+class CacheTagHandler implements CacheTagHandlerInterface {
+
+  /**
+   * Holds an array of cache tag invalidators.
+   *
+   * @var CacheTagInvalidationInterface[]
+   */
+  protected $invalidators;
+
+  public function invalidateTags(array $tags) {
+    foreach ($this->invalidators as $invalidator) {
+      $invalidator->invalidateTags($tags);
+    }
+  }
+
+  public function deleteTags(array $tags) {
+    foreach ($this->invalidators as $invalidator) {
+      $invalidator->deleteTags($tags);
+    }
+  }
+
+  public function addHandler(CacheTagInvalidationInterface $service) {
+    $this->invalidators[] = $service;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagHandlerInterface.php b/core/lib/Drupal/Core/Cache/CacheTagHandlerInterface.php
new file mode 100644
index 0000000..288e04b
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagHandlerInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagHandlerInterface
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Defines required methods for classes wanting to handle cache tag changes.
+ */
+interface CacheTagHandlerInterface {
+
+  /**
+   * Marks cache items with any of the specified tags as invalid.
+   *
+   * @param string[] $tags
+   *   The list of tags for which to invalidate cache items.
+   */
+  public function invalidateTags(array $tags);
+
+  /**
+   * Deletes cache items with any of the specified tags.
+   *
+   * @param string[] $tags
+   *   The list of tags for which to delete cache items.
+   */
+  public function deleteTags(array $tags);
+
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagInvalidationInterface.php b/core/lib/Drupal/Core/Cache/CacheTagInvalidationInterface.php
new file mode 100644
index 0000000..6efb15a
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagInvalidationInterface.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagInvalidationInterface.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Defines methods required for classes that respond to cache tag invalidations.
+ */
+interface CacheTagInvalidationInterface {
+
+  /**
+   * Deletes items with any of the specified tags.
+   *
+   * If the cache items are being deleted because they are no longer "fresh",
+   * you may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   */
+  public function deleteTags(array $tags);
+
+  /**
+   * Marks cache items with any of the specified tags as invalid.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
+   */
+  public function invalidateTags(array $tags);
+
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagInvalidationStorageInterface.php b/core/lib/Drupal/Core/Cache/CacheTagInvalidationStorageInterface.php
new file mode 100644
index 0000000..a200d44
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagInvalidationStorageInterface.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagInvalidationStorageInterface.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * An interface defining cache tag invalidation classes with storage.
+ */
+interface CacheTagInvalidationStorageInterface {
+
+  /**
+   * Returns the sum total of validations for a given set of tags.
+   *
+   * @param array $tags
+   *   Array of cache tags.
+   *
+   * @return int[]
+   *   Array with cache tag invalidations and deletions for the set of passed in
+   *   cache tags.
+   */
+  public function checksumTags(array $tags);
+
+  /**
+   * Notifies the cache tag invalidation storage about cache tags being written.
+   */
+  public function onCacheTagsWrite(array $tags);
+
+  /**
+   * Reset statically cached tags informatoin.
+   *
+   * This is only used by tests.
+   */
+  public function reset();
+}
diff --git a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php
index c261b84..90eef28 100644
--- a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php
@@ -12,7 +12,7 @@
 /**
  * Defines the chained fast cache backend factory.
  */
-class ChainedFastBackendFactory implements CacheFactoryInterface {
+class ChainedFastBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface {
 
   use ContainerAwareTrait;
 
@@ -53,7 +53,7 @@ public function __construct(Settings $settings = NULL, $consistent_service_name
     }
 
     // Default the fast backend to APCu if it's available.
-    if (!isset($fast_service_name) && function_exists('apc_fetch')) {
+    if (FALSE && !isset($fast_service_name) && function_exists('apc_fetch')) {
       $fast_service_name = 'cache.backend.apcu';
     }
 
@@ -85,4 +85,43 @@ public function get($bin) {
     }
   }
 
+  /**
+   * Deletes items with any of the specified tags.
+   *
+   * If the cache items are being deleted because they are no longer "fresh",
+   * you may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   */
+  public function deleteTags(array $tags) {
+    // TODO: Implement deleteTags() method.
+  }
+
+  /**
+   * Marks cache items with any of the specified tags as invalid.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
+   */
+  public function invalidateTags(array $tags) {
+    // TODO: Implement invalidateTags() method.
+  }
 }
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 813c00a..56ebbb6 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -35,19 +35,29 @@ class DatabaseBackend implements CacheBackendInterface {
   protected $connection;
 
   /**
+   * Storage for cache tag invalidations and deletions.
+   *
+   * @var \Drupal\Core\Cache\CacheTagInvalidationStorageInterface
+   */
+  protected $cacheTagStorage;
+
+  /**
    * Constructs a DatabaseBackend object.
    *
    * @param \Drupal\Core\Database\Connection $connection
    *   The database connection.
+   * @param \Drupal\Core\Cache\CacheTagInvalidationStorageInterface $cacheTagStorage
+   *   The object that stores cache tag invalidations and deletions.
    * @param string $bin
    *   The cache bin for which the object is created.
    */
-  public function __construct(Connection $connection, $bin) {
+  public function __construct(Connection $connection, CacheTagInvalidationStorageInterface $cacheTagStorage, $bin) {
     // All cache tables should be prefixed with 'cache_'.
     $bin = 'cache_' . $bin;
 
     $this->bin = $bin;
     $this->connection = $connection;
+    $this->cacheTagStorage = $cacheTagStorage;
   }
 
   /**
@@ -116,7 +126,7 @@ protected function prepareItem($cache, $allow_invalid) {
 
     $cache->tags = $cache->tags ? explode(' ', $cache->tags) : array();
 
-    $checksum = $this->checksumTags($cache->tags);
+    $checksum = $this->cacheTagStorage->checksumTags($cache->tags);
 
     // Check if deleteTags() has been called with any of the entry's tags.
     if ($cache->checksum_deletions != $checksum['deletions']) {
@@ -147,10 +157,13 @@ protected function prepareItem($cache, $allow_invalid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
-    Cache::validateTags($tags);
-    $tags = array_unique($tags);
-    // Sort the cache tags so that they are stored consistently in the database.
-    sort($tags);
+    if ($tags) {
+      Cache::validateTags($tags);
+      $tags = array_unique($tags);
+      // Sort the cache tags so that they are stored consistently in the database.
+      sort($tags);
+      $this->cacheTagStorage->onCacheTagsWrite($tags);
+    }
     $try_again = FALSE;
     try {
       // The bin might not yet exist.
@@ -174,20 +187,7 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array
    * Actually set the cache.
    */
   protected function doSet($cid, $data, $expire, $tags) {
-    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
-    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
-    // Remove tags that were already deleted or invalidated during this request
-    // from the static caches so that another deletion or invalidation can
-    // occur.
-    foreach ($tags as $tag) {
-      if (isset($deleted_tags[$tag])) {
-        unset($deleted_tags[$tag]);
-      }
-      if (isset($invalidated_tags[$tag])) {
-        unset($invalidated_tags[$tag]);
-      }
-    }
-    $checksum = $this->checksumTags($tags);
+    $checksum = $this->cacheTagStorage->checksumTags($tags);
     $fields = array(
       'serialized' => 0,
       'created' => round(microtime(TRUE), 3),
@@ -215,9 +215,6 @@ protected function doSet($cid, $data, $expire, $tags) {
    * {@inheritdoc}
    */
   public function setMultiple(array $items) {
-    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
-    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
-
     // Use a transaction so that the database can write the changes in a single
     // commit.
     $transaction = $this->connection->startTransaction();
@@ -237,24 +234,14 @@ public function setMultiple(array $items) {
           'tags' => array(),
         );
 
-        Cache::validateTags($item['tags']);
-        $item['tags'] = array_unique($item['tags']);
-        // Sort the cache tags so that they are stored consistently in the DB.
-        sort($item['tags']);
-
-        // Remove tags that were already deleted or invalidated during this
-        // request from the static caches so that another deletion or
-        // invalidation can occur.
-        foreach ($item['tags'] as $tag) {
-          if (isset($deleted_tags[$tag])) {
-            unset($deleted_tags[$tag]);
-          }
-          if (isset($invalidated_tags[$tag])) {
-            unset($invalidated_tags[$tag]);
-          }
+        if ($item['tags']) {
+          Cache::validateTags($item['tags']);
+          $item['tags'] = array_unique($item['tags']);
+          // Sort the cache tags so that they are stored consistently in the DB.
+          sort($item['tags']);
+          $this->cacheTagStorage->onCacheTagsWrite($item['tags']);
         }
-
-        $checksum = $this->checksumTags($item['tags']);
+        $checksum = $this->cacheTagStorage->checksumTags($item['tags']);
 
         $fields = array(
           'cid' => $cid,
@@ -319,28 +306,7 @@ public function deleteMultiple(array $cids) {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
    */
-  public function deleteTags(array $tags) {
-    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
-    foreach ($tags as $tag) {
-      // Only delete tags once per request unless they are written again.
-      if (isset($deleted_tags[$tag])) {
-        continue;
-      }
-      $deleted_tags[$tag] = TRUE;
-      unset($tag_cache[$tag]);
-      try {
-        $this->connection->merge('cachetags')
-          ->insertFields(array('deletions' => 1))
-          ->expression('deletions', 'deletions + 1')
-          ->key('tag', $tag)
-          ->execute();
-      }
-      catch (\Exception $e) {
-        $this->catchException($e, 'cachetags');
-      }
-    }
-  }
+  public function deleteTags(array $tags) {}
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
@@ -386,30 +352,9 @@ public function invalidateMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
+   * Implements Drupal\Core\Cache\CacheTagHandlerInterface::invalidateTags().
    */
-  public function invalidateTags(array $tags) {
-    try {
-      $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-      $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
-      foreach ($tags as $tag) {
-        // Only invalidate tags once per request unless they are written again.
-        if (isset($invalidated_tags[$tag])) {
-          continue;
-        }
-        $invalidated_tags[$tag] = TRUE;
-        unset($tag_cache[$tag]);
-        $this->connection->merge('cachetags')
-          ->insertFields(array('invalidations' => 1))
-          ->expression('invalidations', 'invalidations + 1')
-          ->key('tag', $tag)
-          ->execute();
-      }
-    }
-    catch (\Exception $e) {
-      $this->catchException($e, 'cachetags');
-    }
-  }
+  public function invalidateTags(array $tags) {}
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
@@ -443,40 +388,6 @@ public function garbageCollection() {
   }
 
   /**
-   * Returns the sum total of validations for a given set of tags.
-   *
-   * @param array $tags
-   *   Array of cache tags.
-   *
-   * @return int
-   *   Sum of all invalidations.
-   */
-  protected function checksumTags(array $tags) {
-    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-
-    $checksum = array(
-      'invalidations' => 0,
-      'deletions' => 0,
-    );
-
-    $query_tags = array_diff($tags, array_keys($tag_cache));
-    if ($query_tags) {
-      $db_tags = $this->connection->query('SELECT tag, invalidations, deletions FROM {cachetags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllAssoc('tag', \PDO::FETCH_ASSOC);
-      $tag_cache += $db_tags;
-
-      // Fill static cache with empty objects for tags not found in the database.
-      $tag_cache += array_fill_keys(array_diff($query_tags, array_keys($db_tags)), $checksum);
-    }
-
-    foreach ($tags as $tag) {
-      $checksum['invalidations'] += $tag_cache[$tag]['invalidations'];
-      $checksum['deletions'] += $tag_cache[$tag]['deletions'];
-    }
-
-    return $checksum;
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function removeBin() {
@@ -496,11 +407,7 @@ protected function ensureBinExists() {
       $database_schema = $this->connection->schema();
       if (!$database_schema->tableExists($this->bin)) {
         $schema_definition = $this->schemaDefinition();
-        $database_schema->createTable($this->bin, $schema_definition['bin']);
-        // If the bin doesn't exist, the cache tags table may also not exist.
-        if (!$database_schema->tableExists('cachetags')) {
-          $database_schema->createTable('cachetags', $schema_definition['cachetags']);
-        }
+        $database_schema->createTable($this->bin, $schema_definition);
         return TRUE;
       }
     }
@@ -516,14 +423,16 @@ protected function ensureBinExists() {
   /**
    * Act on an exception when cache might be stale.
    *
-   * If the {cachetags} table does not yet exist, that's fine but if the table
+   * If the table does not yet exist, that's fine, but if the table
    * exists and yet the query failed, then the cache is stale and the
    * exception needs to propagate.
    *
    * @param $e
    *   The exception.
    * @param string|null $table_name
-   *   The table name, defaults to $this->bin. Can be cachetags.
+   *   The table name. Defaults to $this->bin.
+   *
+   * @throws \Exception
    */
   protected function catchException(\Exception $e, $table_name = NULL) {
     if ($this->connection->schema()->tableExists($table_name ?: $this->bin)) {
@@ -552,10 +461,10 @@ protected function normalizeCid($cid) {
   }
 
   /**
-   * Defines the schema for the {cache_*} bin and {cachetags} tables.
+   * Defines the schema for the {cache_*} bin table.
    */
   public function schemaDefinition() {
-    $schema['bin'] = array(
+    $schema = array(
       'description' => 'Storage for the cache API.',
       'fields' => array(
         'cid' => array(
@@ -617,31 +526,6 @@ public function schemaDefinition() {
       ),
       'primary key' => array('cid'),
     );
-    $schema['cachetags'] = array(
-      'description' => 'Cache table for tracking cache tags related to the cache bin.',
-      'fields' => array(
-        'tag' => array(
-          'description' => 'Namespace-prefixed tag string.',
-          'type' => 'varchar',
-          'length' => 255,
-          'not null' => TRUE,
-          'default' => '',
-        ),
-        'invalidations' => array(
-          'description' => 'Number incremented when the tag is invalidated.',
-          'type' => 'int',
-          'not null' => TRUE,
-          'default' => 0,
-        ),
-        'deletions' => array(
-          'description' => 'Number incremented when the tag is deleted.',
-          'type' => 'int',
-          'not null' => TRUE,
-          'default' => 0,
-        ),
-      ),
-      'primary key' => array('tag'),
-    );
     return $schema;
   }
 }
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
index 1d70164..2772bab 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -23,8 +23,9 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
    *
    * @param \Drupal\Core\Database\Connection $connection
    */
-  function __construct(Connection $connection) {
+  function __construct(Connection $connection, CacheTagInvalidationStorageInterface $cacheTagStorage) {
     $this->connection = $connection;
+    $this->cacheTagStorage = $cacheTagStorage;
   }
 
   /**
@@ -37,7 +38,7 @@ function __construct(Connection $connection) {
    *   The cache backend object for the specified cache bin.
    */
   function get($bin) {
-    return new DatabaseBackend($this->connection, $bin);
+    return new DatabaseBackend($this->connection, $this->cacheTagStorage, $bin);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Cache/DatabaseCacheTagStorage.php b/core/lib/Drupal/Core/Cache/DatabaseCacheTagStorage.php
new file mode 100644
index 0000000..150d073
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/DatabaseCacheTagStorage.php
@@ -0,0 +1,247 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\DatabaseCacheTagStorage.
+ */
+
+namespace Drupal\Core\Cache;
+
+use \Drupal\Core\Database\Connection;
+use Drupal\Core\Database\SchemaObjectExistsException;
+
+/**
+ * Storage for cache tag invalidations and deletions.
+ */
+class DatabaseCacheTagStorage implements CacheTagInvalidationStorageInterface, CacheTagInvalidationInterface {
+
+  /**
+   * The database connection.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * Contains already loaded tags from the database.
+   *
+   * @var array
+   */
+  protected $tagCache = array();
+
+  /**
+   * A list of tags that have already been deleted in this requested.
+   *
+   * Used to prevent the deletion of the same cache tag multiple times.
+   *
+   * @var array
+   */
+  protected $deletedTags = array();
+
+  /**
+   * A list of tags that have already been invalidated in this requested.
+   *
+   * Used to prevent the invalidation of the same cache tag multiple times.
+   *
+   * @var array
+   */
+  protected $invalidatedTags = array();
+
+  /**
+   * Constructs a DatabaseBackend object.
+   *
+   * @param \Drupal\Core\Database\Connection $connection
+   *   The database connection.
+   */
+  public function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function invalidateTags(array $tags) {
+    try {
+      foreach ($tags as $tag) {
+        // Only invalidate tags once per request unless they are written again.
+        if (isset($this->invalidatedTags[$tag])) {
+          continue;
+        }
+        $this->invalidatedTags[$tag] = TRUE;
+        unset($this->tagCache[$tag]);
+        $this->connection->merge('cachetags')
+          ->insertFields(array('invalidations' => 1))
+          ->expression('invalidations', 'invalidations + 1')
+          ->key('tag', $tag)
+          ->execute();
+      }
+    }
+    catch (\Exception $e) {
+      // Create the cache table, which will be empty. This fixes cases during
+      // core install where a cache table is cleared before it is set
+      // with {cache_render} and {cache_data}.
+      if (!$this->ensureTableExists()) {
+        $this->catchException($e);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteTags(array $tags) {
+    foreach ($tags as $tag) {
+      // Only delete tags once per request unless they are written again.
+      if (isset($this->deletedTags[$tag])) {
+        continue;
+      }
+      $this->deletedTags[$tag] = TRUE;
+      unset($this->tagCache[$tag]);
+      try {
+        $this->connection->merge('cachetags')
+          ->insertFields(array('deletions' => 1))
+          ->expression('deletions', 'deletions + 1')
+          ->key('tag', $tag)
+          ->execute();
+      }
+      catch (\Exception $e) {
+        // Create the cache table, which will be empty. This fixes cases during
+        // core install where a cache table is cleared before it is set
+        // with {cache_render} and {cache_data}.
+        if (!$this->ensureTableExists()) {
+          $this->catchException($e);
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checksumTags(array $tags) {
+    $checksum = array(
+      'invalidations' => 0,
+      'deletions' => 0,
+    );
+
+    $query_tags = array_diff($tags, array_keys($this->tagCache));
+    if ($query_tags) {
+      $db_tags = array();
+      try {
+        $db_tags = $this->connection->query('SELECT tag, invalidations, deletions FROM {cachetags} WHERE tag IN (:tags)', array(':tags' => $query_tags))
+          ->fetchAllAssoc('tag', \PDO::FETCH_ASSOC);
+        $this->tagCache += $db_tags;
+      }
+      catch (\Exception $e) {
+        // If the table does not exist yet, create.
+        if (!$this->ensureTableExists()) {
+          $this->catchException($e);
+        }
+      }
+      // Fill static cache with empty objects for tags not found in the database.
+      $this->tagCache += array_fill_keys(array_diff($query_tags, array_keys($db_tags)), $checksum);
+    }
+
+    foreach ($tags as $tag) {
+      $checksum['invalidations'] += $this->tagCache[$tag]['invalidations'];
+      $checksum['deletions'] += $this->tagCache[$tag]['deletions'];
+    }
+
+    return $checksum;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onCacheTagsWrite(array $tags) {
+    // Remove tags that were already deleted or invalidated during this request
+    // from the static caches so that another deletion or invalidation can
+    // occur.
+    foreach ($tags as $tag) {
+      unset($this->deletedTags[$tag]);
+      unset($this->invalidatedTags[$tag]);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function reset() {
+    $this->tagCache = array();
+    $this->deletedTags = array();
+    $this->invalidatedTags = array();
+  }
+
+  /**
+   * Check if the cache tags table exists and create it if not.
+   */
+  protected function ensureTableExists() {
+    try {
+      $database_schema = $this->connection->schema();
+      // Create the cache tags table if it does not exist.
+      if (!$database_schema->tableExists('cachetags')) {
+        $schema_definition = $this->schemaDefinition();
+        $database_schema->createTable('cachetags', $schema_definition);
+
+        return TRUE;
+      }
+      // If another process has already created the cache tags table, attempting to
+      // recreate it will throw an exception. In this case just catch the
+      // exception and do nothing.
+    }
+    catch (SchemaObjectExistsException $e) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Defines the schema for the {cachetags} table.
+   */
+  public function schemaDefinition() {
+    $schema = array(
+      'description' => 'Cache table for tracking cache tags related to the cache bin.',
+      'fields' => array(
+        'tag' => array(
+          'description' => 'Namespace-prefixed tag string.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'invalidations' => array(
+          'description' => 'Number incremented when the tag is invalidated.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'deletions' => array(
+          'description' => 'Number incremented when the tag is deleted.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'primary key' => array('tag'),
+    );
+    return $schema;
+  }
+
+  /**
+   * Act on an exception when cache might be stale.
+   *
+   * If the {cachetags} table does not yet exist, that's fine but if the table
+   * exists and yet the query failed, then the cache is stale and the
+   * exception needs to propagate.
+   *
+   * @param \Exception $e
+   *   The exception.
+   *
+   * @throws \Exception
+   */
+  protected function catchException(\Exception $e) {
+    if ($this->connection->schema()->tableExists('cachetags')) {
+      throw $e;
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
index c9e288d..6783720 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
@@ -7,13 +7,40 @@
 
 namespace Drupal\Core\Cache;
 
-class MemoryBackendFactory implements CacheFactoryInterface {
+class MemoryBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface {
+
+  /**
+   * Instantiated memory cache bins.
+   *
+   * @var \Drupal\Core\Cache\MemoryBackend[]
+   */
+  protected $bins = array();
 
   /**
    * {@inheritdoc}
    */
   function get($bin) {
-    return new MemoryBackend($bin);
+    if (!isset($this->bins[$bin])) {
+      $this->bins[$bin] = new MemoryBackend($bin);
+    }
+    return $this->bins[$bin];
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteTags(array $tags) {
+    foreach ($this->bins as $bin) {
+      $bin->deleteTags($tags);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function invalidateTags(array $tags) {
+    foreach ($this->bins as $bin) {
+      $bin->deleteTags($tags);
+    }
+  }
 }
diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php
index d27bc13..fb898de 100644
--- a/core/lib/Drupal/Core/Cache/NullBackend.php
+++ b/core/lib/Drupal/Core/Cache/NullBackend.php
@@ -70,7 +70,7 @@ public function deleteMultiple(array $cids) {}
   public function deleteAll() {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
+   * Implements Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags().
    */
   public function deleteTags(array $tags) {}
 
@@ -85,7 +85,7 @@ public function invalidate($cid) {}
   public function invalidateMultiple(array $cids) {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
+   * Implements Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags().
    */
   public function invalidateTags(array $tags) {}
 
diff --git a/core/lib/Drupal/Core/Cache/NullBackendFactory.php b/core/lib/Drupal/Core/Cache/NullBackendFactory.php
index 0101a8e..b1d9365 100644
--- a/core/lib/Drupal/Core/Cache/NullBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/NullBackendFactory.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Cache;
 
-class NullBackendFactory implements CacheFactoryInterface {
+class NullBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface {
 
   /**
    * {@inheritdoc}
@@ -16,4 +16,43 @@ function get($bin) {
     return new NullBackend($bin);
   }
 
+  /**
+   * Deletes items with any of the specified tags.
+   *
+   * If the cache items are being deleted because they are no longer "fresh",
+   * you may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   */
+  public function deleteTags(array $tags) {
+    // TODO: Implement deleteTags() method.
+  }
+
+  /**
+   * Marks cache items with any of the specified tags as invalid.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
+   */
+  public function invalidateTags(array $tags) {
+    // TODO: Implement invalidateTags() method.
+  }
 }
diff --git a/core/lib/Drupal/Core/Cache/NullCacheTagHandler.php b/core/lib/Drupal/Core/Cache/NullCacheTagHandler.php
new file mode 100644
index 0000000..76b4c41
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/NullCacheTagHandler.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\NullCacheTagHandler.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * A no-op implementation of CacheTagHandlerInterface, for the installer.
+ */
+class NullCacheTagHandler implements CacheTagHandlerInterface {
+
+  /**
+   * Holds an array of cache tag invalidators.
+   *
+   * @var CacheTagInvalidationInterface[]
+   */
+  protected $invalidators;
+
+  public function invalidateTags(array $tags) {}
+
+  public function deleteTags(array $tags) {}
+
+  public function addHandler(CacheTagInvalidationInterface $service) {
+    $this->invalidators[] = $service;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/PhpBackendFactory.php b/core/lib/Drupal/Core/Cache/PhpBackendFactory.php
index 0801b72..872bf16 100644
--- a/core/lib/Drupal/Core/Cache/PhpBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/PhpBackendFactory.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Cache;
 
-class PhpBackendFactory implements CacheFactoryInterface {
+class PhpBackendFactory implements CacheFactoryInterface, CacheTagInvalidationInterface {
 
   /**
    * Gets PhpBackend for the specified cache bin.
@@ -22,4 +22,43 @@ function get($bin) {
     return new PhpBackend($bin);
   }
 
+  /**
+   * Deletes items with any of the specified tags.
+   *
+   * If the cache items are being deleted because they are no longer "fresh",
+   * you may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   */
+  public function deleteTags(array $tags) {
+    // TODO: Implement deleteTags() method.
+  }
+
+  /**
+   * Marks cache items with any of the specified tags as invalid.
+   *
+   * @param array $tags
+   *   Associative array of tags, in the same format that is passed to
+   *   CacheBackendInterface::set().
+   *
+   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
+   * @see \Drupal\Core\Cache\CacheTagInvalidationInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
+   */
+  public function invalidateTags(array $tags) {
+    // TODO: Implement invalidateTags() method.
+  }
 }
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 6e93561..af823f7 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -48,6 +48,8 @@ public function register(ContainerBuilder $container) {
       ->addArgument(new Reference('request_stack'));
     $container
       ->register('router.dumper', 'Drupal\Core\Routing\NullMatcherDumper');
+    $container
+      ->register('cache_tags', 'Drupal\Core\Cache\NullCacheTagHandler');
 
     // Replace the route builder with an empty implementation.
     // @todo Convert installer steps into routes; add an installer.routing.yml.
diff --git a/core/modules/book/src/BookManager.php b/core/modules/book/src/BookManager.php
index 3f5cfdc..e1f4282 100644
--- a/core/modules/book/src/BookManager.php
+++ b/core/modules/book/src/BookManager.php
@@ -433,7 +433,7 @@ public function deleteFromBook($nid) {
     }
     $this->updateOriginalParent($original);
     $this->books = NULL;
-    \Drupal::cache('data')->deleteTags(array('bid:' . $original['bid']));
+    Cache::deleteTags(array('bid:' . $original['bid']));
   }
 
   /**
@@ -763,7 +763,7 @@ public function saveBookLink(array $link, $new) {
     foreach ($affected_bids as $bid) {
       $cache_tags[] = 'bid:' . $bid;
     }
-    \Drupal::cache('data')->deleteTags($cache_tags);
+    Cache::deleteTags($cache_tags);
     return $link;
   }
 
diff --git a/core/modules/config/src/Tests/Storage/CachedStorageTest.php b/core/modules/config/src/Tests/Storage/CachedStorageTest.php
index 11c3599..2d4e464 100644
--- a/core/modules/config/src/Tests/Storage/CachedStorageTest.php
+++ b/core/modules/config/src/Tests/Storage/CachedStorageTest.php
@@ -90,7 +90,8 @@ public function containerBuild(ContainerBuilder $container) {
     parent::containerBuild($container);
     // Use the regular database cache backend to aid testing.
     $container->register('cache_factory', 'Drupal\Core\Cache\DatabaseBackendFactory')
-      ->addArgument(new Reference('database'));
+      ->addArgument(new Reference('database'))
+      ->addArgument(new Reference('cache_tag_storage'));
   }
 
 }
diff --git a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
index e9919cd..740bb0d 100644
--- a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
+++ b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
@@ -137,7 +137,7 @@ public function testStringTranslation() {
 
     // Reset the tag cache on the tester side in order to pick up the call to
     // Cache::deleteTags() on the tested side.
-    drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+    \Drupal::service('cache_tag_storage')->reset();
 
     $this->assertTrue($name != $translation && t($name, array(), array('langcode' => $langcode)) == $translation, 't() works for non-English.');
     // Refresh the locale() cache to get fresh data from t() below. We are in
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index f26c5d4..7abd200 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -256,7 +256,8 @@ public function containerBuild(ContainerBuilder $container) {
     $this->container->setParameter('language.default_values', Language::$defaultValues);
 
     $container->register('lock', 'Drupal\Core\Lock\NullLockBackend');
-    $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory');
+    $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory')
+      ->addTag('cache_tags');
 
     $container
       ->register('config.storage', 'Drupal\Core\Config\DatabaseStorage')
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index d2b31ae..deda382 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -1148,12 +1148,7 @@ protected function resetAll() {
    */
   protected function refreshVariables() {
     // Clear the tag cache.
-    // @todo Replace drupal_static() usage within classes and provide a
-    //   proper interface for invoking reset() on a cache backend:
-    //   https://www.drupal.org/node/2311945.
-    drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
-    drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::deletedTags');
-    drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::invalidatedTags');
+    \Drupal::service('cache_tag_storage')->reset();
     foreach (Cache::getBins() as $backend) {
       if (is_callable(array($backend, 'reset'))) {
         $backend->reset();
diff --git a/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php b/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php
index da8f565..c10f25a 100644
--- a/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/ApcuBackendUnitTest.php
@@ -34,7 +34,9 @@ protected function checkRequirements() {
   }
 
   protected function createCacheBackend($bin) {
-    return new ApcuBackend($bin, $this->databasePrefix);
+    $backend = new ApcuBackend($bin, $this->databasePrefix);
+    \Drupal::service('cache_tags')->addHandler($backend);
+    return $backend;
   }
 
   protected function tearDown() {
diff --git a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
index cbfaf16..cc5760b 100644
--- a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
@@ -26,6 +26,8 @@ protected function createCacheBackend($bin) {
       ->prependBackend(new MemoryBackend('bar'))
       ->appendBackend(new MemoryBackend('baz'));
 
+    \Drupal::service('cache_tags')->addHandler($chain);
+
     return $chain;
   }
 }
diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
index bd2952e..518383b 100644
--- a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
@@ -30,7 +30,7 @@ class DatabaseBackendUnitTest extends GenericCacheBackendUnitTestBase {
    *   A new DatabaseBackend object.
    */
   protected function createCacheBackend($bin) {
-    return new DatabaseBackend($this->container->get('database'), $bin);
+    return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tag_storage'), $bin);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
index 97d7ccd..5ce1ab5 100644
--- a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -485,7 +485,7 @@ function testDeleteTags() {
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
 
     // Delete test_tag of value 1. This should delete both entries.
-    $backend->deleteTags(array('test_tag:2'));
+    Cache::deleteTags(array('test_tag:2'));
     $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleting a cache tag.');
     $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.');
 
@@ -495,7 +495,7 @@ function testDeleteTags() {
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
 
     // Delete test_tag of value 1. This should delete both entries.
-    $backend->deleteTags(array('test_tag:1'));
+    Cache::deleteTags(array('test_tag:1'));
     $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleted a cache tag.');
     $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.');
 
@@ -504,7 +504,7 @@ function testDeleteTags() {
     $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag:2'));
     $backend->set('test_cid_invalidate3', $this->defaultValue, Cache::PERMANENT, array('test_tag_foo:3'));
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.');
-    $backend->deleteTags(array('test_tag_foo:3'));
+    Cache::deleteTags(array('test_tag_foo:3'));
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cached items not matching the tag were not deleted.');
     $this->assertFalse($backend->get('test_cid_invalidated3', TRUE), 'Cache item matching the tag was deleted.');
 
@@ -518,10 +518,7 @@ function testDeleteTags() {
       $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
     }
 
-    // Delete tag in mulitple bins.
-    foreach ($bins as $bin) {
-      $this->getCacheBackend($bin)->deleteTags(array('test_tag:2'));
-    }
+    Cache::deleteTags(array('test_tag:2'));
 
     // Test that cache entry has been deleted in multple bins.
     foreach ($bins as $bin) {
@@ -597,7 +594,7 @@ function testInvalidateTags() {
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
 
     // Invalidate test_tag of value 1. This should invalidate both entries.
-    $backend->invalidateTags(array('test_tag:2'));
+    Cache::invalidateTags(array('test_tag:2'));
     $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after invalidating a cache tag.');
     $this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.');
 
@@ -607,7 +604,7 @@ function testInvalidateTags() {
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
 
     // Invalidate test_tag of value 1. This should invalidate both entries.
-    $backend->invalidateTags(array('test_tag:1'));
+    Cache::invalidateTags(array('test_tag:1'));
     $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two caches removed after invalidating a cache tag.');
     $this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.');
 
@@ -616,7 +613,7 @@ function testInvalidateTags() {
     $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag:2'));
     $backend->set('test_cid_invalidate3', $this->defaultValue, Cache::PERMANENT, array('test_tag_foo:3'));
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.');
-    $backend->invalidateTags(array('test_tag_foo:3'));
+    Cache::invalidateTags(array('test_tag_foo:3'));
     $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cache items not matching the tag were not invalidated.');
     $this->assertFalse($backend->get('test_cid_invalidated3'), 'Cached item matching the tag was removed.');
 
@@ -630,10 +627,7 @@ function testInvalidateTags() {
       $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
     }
 
-    // Invalidate tag in mulitple bins.
-    foreach ($bins as $bin) {
-      $this->getCacheBackend($bin)->invalidateTags(array('test_tag:2'));
-    }
+    Cache::invalidateTags(array('test_tag:2'));
 
     // Test that cache entry has been invalidated in multple bins.
     foreach ($bins as $bin) {
diff --git a/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php b/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
index 85edfde..3a99482 100644
--- a/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
@@ -23,6 +23,8 @@ class MemoryBackendUnitTest extends GenericCacheBackendUnitTestBase {
    *   A new MemoryBackend object.
    */
   protected function createCacheBackend($bin) {
-    return new MemoryBackend($bin);
+    $backend = new MemoryBackend($bin);
+    \Drupal::service('cache_tags')->addHandler($backend);
+    return $backend;
   }
 }
diff --git a/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php b/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php
index 57df19b..01b58ca 100644
--- a/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/PhpBackendUnitTest.php
@@ -23,7 +23,9 @@ class PhpBackendUnitTest extends GenericCacheBackendUnitTestBase {
    *   A new MemoryBackend object.
    */
   protected function createCacheBackend($bin) {
-    return new PhpBackend($bin);
+    $backend = new PhpBackend($bin);
+    \Drupal::service('cache_tags')->addHandler($backend);
+    return $backend;
   }
 
 }
diff --git a/core/modules/views/tests/src/Unit/ViewsDataTest.php b/core/modules/views/tests/src/Unit/ViewsDataTest.php
index 0476ffd..4bd856d 100644
--- a/core/modules/views/tests/src/Unit/ViewsDataTest.php
+++ b/core/modules/views/tests/src/Unit/ViewsDataTest.php
@@ -26,6 +26,13 @@ class ViewsDataTest extends UnitTestCase {
   protected $cacheBackend;
 
   /**
+   * The mocked cache tag handler.
+   *
+   * @var \Drupal\Core\Cache\CacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTagHandler;
+
+  /**
    * The mocked module handler.
    *
    * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -57,8 +64,9 @@ class ViewsDataTest extends UnitTestCase {
    * {@inheritdoc}
    */
   protected function setUp() {
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-    $this->getContainerWithCacheBins($this->cacheBackend);
+    $this->getContainerWithCacheBins($this->cacheTagHandler);
 
     $configs = array();
     $configs['views.settings']['skip_cache'] = FALSE;
@@ -250,20 +258,21 @@ public function testFullAndTableGetCache() {
     $this->cacheBackend->expects($this->at(3))
       ->method('set')
       ->with("views_data:$random_table_name:en", array());
+    $this->cacheTagHandler->expects($this->once())
+      ->method('deleteTags')
+      ->with(['views_data']);
     $this->cacheBackend->expects($this->at(4))
-      ->method('deleteAll');
+      ->method('get')
+      ->with("views_data:en")
+      ->will($this->returnValue(FALSE));
     $this->cacheBackend->expects($this->at(5))
-      ->method('get')
-      ->with("views_data:en")
-      ->will($this->returnValue(FALSE));
+      ->method('set')
+      ->with("views_data:en", $expected_views_data);
     $this->cacheBackend->expects($this->at(6))
-      ->method('set')
-      ->with("views_data:en", $expected_views_data);
+      ->method('get')
+      ->with("views_data:$random_table_name:en")
+      ->will($this->returnValue(FALSE));
     $this->cacheBackend->expects($this->at(7))
-      ->method('get')
-      ->with("views_data:$random_table_name:en")
-      ->will($this->returnValue(FALSE));
-    $this->cacheBackend->expects($this->at(8))
       ->method('set')
       ->with("views_data:$random_table_name:en", array());
 
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
index cf5b3f1..2b53e0a 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
@@ -21,7 +21,14 @@ class CacheCollectorTest extends UnitTestCase {
    *
    * @var \PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cache;
+  protected $cacheBackend;
+
+  /**
+   * The cache tag handler.
+   *
+   * @var \PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTagHandler;
 
   /**
    * The lock backend that should be used.
@@ -48,12 +55,13 @@ class CacheCollectorTest extends UnitTestCase {
    * {@inheritdoc}
    */
   protected function setUp() {
-    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
     $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
     $this->cid = $this->randomMachineName();
-    $this->collector = new CacheCollectorHelper($this->cid, $this->cache, $this->lock);
+    $this->collector = new CacheCollectorHelper($this->cid, $this->cacheBackend, $this->lock);
 
-    $this->getContainerWithCacheBins($this->cache);
+    $this->getContainerWithCacheBins($this->cacheTagHandler);
   }
 
 
@@ -90,7 +98,7 @@ public function testSetAndGetNull() {
     $key = $this->randomMachineName();
     $value = NULL;
 
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('invalidate')
       ->with($this->cid);
     $this->collector->set($key, $value);
@@ -115,7 +123,7 @@ public function testGetFromCache() {
       'data' => array($key => $value),
       'created' => REQUEST_TIME,
     );
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('get')
       ->with($this->cid)
       ->will($this->returnValue($cache));
@@ -137,7 +145,7 @@ public function testDelete() {
     $this->assertTrue($this->collector->has($key));
     $this->assertEquals($value, $this->collector->get($key));
 
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('invalidate')
       ->with($this->cid);
     $this->collector->delete($key);
@@ -151,7 +159,7 @@ public function testDelete() {
   public function testUpdateCacheNoChanges() {
     $this->lock->expects($this->never())
       ->method('acquire');
-    $this->cache->expects($this->never())
+    $this->cacheBackend->expects($this->never())
       ->method('set');
 
     // Destruct the object to trigger the update data process.
@@ -175,10 +183,10 @@ public function testUpdateCache() {
       ->method('acquire')
       ->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
       ->will($this->returnValue(TRUE));
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('get')
       ->with($this->cid, FALSE);
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('set')
       ->with($this->cid, array($key => $value), Cache::PERMANENT, array());
     $this->lock->expects($this->once())
@@ -205,7 +213,7 @@ public function testUpdateCacheLockFail() {
       ->method('acquire')
       ->with($this->cid . ':Drupal\Core\Cache\CacheCollector')
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->never())
+    $this->cacheBackend->expects($this->never())
       ->method('set');
 
     // Destruct the object to trigger the update data process.
@@ -223,12 +231,12 @@ public function testUpdateCacheInvalidatedConflict() {
       'data' => array($key => $value),
       'created' => REQUEST_TIME,
     );
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with($this->cid)
       ->will($this->returnValue($cache));
 
-    $this->cache->expects($this->at(1))
+    $this->cacheBackend->expects($this->at(1))
       ->method('invalidate')
       ->with($this->cid);
     $this->collector->set($key, 'new value');
@@ -244,11 +252,11 @@ public function testUpdateCacheInvalidatedConflict() {
       'data' => array($key => $value),
       'created' => REQUEST_TIME + 1,
     );
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with($this->cid)
       ->will($this->returnValue($cache));
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('delete')
       ->with($this->cid);
     $this->lock->expects($this->once())
@@ -280,11 +288,11 @@ public function testUpdateCacheMerge() {
       'data' => array('other key' => 'other value'),
       'created' => REQUEST_TIME + 1,
     );
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with($this->cid)
       ->will($this->returnValue($cache));
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('set')
       ->with($this->cid, array('other key' => 'other value', $key => $value), Cache::PERMANENT, array());
     $this->lock->expects($this->once())
@@ -306,7 +314,7 @@ public function testUpdateCacheDelete() {
       'data' => array($key => $value),
       'created' => REQUEST_TIME,
     );
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with($this->cid)
       ->will($this->returnValue($cache));
@@ -322,10 +330,10 @@ public function testUpdateCacheDelete() {
       ->will($this->returnValue(TRUE));
     // The second argument is set to TRUE because we triggered a cache
     // invalidation.
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with($this->cid, TRUE);
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('set')
       ->with($this->cid, array(), Cache::PERMANENT, array());
     $this->lock->expects($this->once())
@@ -373,10 +381,10 @@ public function testUpdateCacheClear() {
     $this->assertEquals(1, $this->collector->getCacheMisses());
 
     // Clear the collected cache, should call it again.
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('delete')
       ->with($this->cid);
-    $this->cache->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('deleteTags');
     $this->collector->clear();
     $this->assertEquals($value, $this->collector->get($key));
@@ -390,7 +398,7 @@ public function testUpdateCacheClearTags() {
     $key = $this->randomMachineName();
     $value = $this->randomMachineName();
     $tags = array($this->randomMachineName());
-    $this->collector = new CacheCollectorHelper($this->cid, $this->cache, $this->lock, $tags);
+    $this->collector = new CacheCollectorHelper($this->cid, $this->cacheBackend, $this->lock, $tags);
 
     // Set the data and request it.
     $this->collector->setCacheMissData($key, $value);
@@ -401,9 +409,9 @@ public function testUpdateCacheClearTags() {
     $this->assertEquals(1, $this->collector->getCacheMisses());
 
     // Clear the collected cache using the tags, should call it again.
-    $this->cache->expects($this->never())
+    $this->cacheBackend->expects($this->never())
       ->method('delete');
-    $this->cache->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('deleteTags')
       ->with($tags);
     $this->collector->clear();
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
index 2da84fe..02ce8b5 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -79,9 +79,9 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
   /**
    * The mocked cache backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagHandler;
 
   /**
    * The mocked typed config manager.
@@ -121,7 +121,7 @@ protected function setUp() {
       ->with('en')
       ->will($this->returnValue(new Language(array('id' => 'en'))));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
 
     $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
 
@@ -129,9 +129,8 @@ protected function setUp() {
     $container->set('entity.manager', $this->entityManager);
     $container->set('uuid', $this->uuid);
     $container->set('language_manager', $this->languageManager);
-    $container->set('cache.test', $this->cacheBackend);
+    $container->set('cache_tags', $this->cacheTagHandler);
     $container->set('config.typed', $this->typedConfigManager);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
     \Drupal::setContainer($container);
 
     $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array($values, $this->entityTypeId));
@@ -361,7 +360,7 @@ public function testEnable() {
    * @depends testSetStatus
    */
   public function testDisable() {
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array($this->entityTypeId . ':' . $this->id));
 
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index ddfbd81..bf7ca84 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -85,9 +85,9 @@ class ConfigEntityStorageTest extends UnitTestCase {
   /**
    * The mocked cache backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagHandler;
 
   /**
    * The mocked typed config manager.
@@ -153,7 +153,7 @@ protected function setUp() {
       ->with('test_entity_type')
       ->will($this->returnValue($this->entityType));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
 
     $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
     $this->typedConfigManager->expects($this->any())
@@ -162,8 +162,7 @@ protected function setUp() {
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('config.typed', $this->typedConfigManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
+    $container->set('cache_tags', $this->cacheTagHandler);
     \Drupal::setContainer($container);
 
   }
@@ -173,7 +172,7 @@ protected function setUp() {
    * @covers ::doCreate
    */
   public function testCreateWithPredefinedUuid() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->moduleHandler->expects($this->at(0))
@@ -198,7 +197,7 @@ public function testCreateWithPredefinedUuid() {
    * @return \Drupal\Core\Entity\EntityInterface
    */
   public function testCreate() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->moduleHandler->expects($this->at(0))
@@ -240,7 +239,7 @@ public function testSaveInsert(EntityInterface $entity) {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . '_list', // List cache tag.
@@ -299,7 +298,7 @@ public function testSaveUpdate(EntityInterface $entity) {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . ':foo', // Own cache tag.
@@ -359,7 +358,7 @@ public function testSaveRename(ConfigEntityInterface $entity) {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId .':bar', // Own cache tag.
@@ -403,7 +402,7 @@ public function testSaveRename(ConfigEntityInterface $entity) {
    * @expectedExceptionMessage The entity does not have an ID.
    */
   public function testSaveInvalid() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $entity = $this->getMockEntity();
@@ -428,7 +427,7 @@ public function testSaveDuplicate() {
     $config_object->expects($this->never())
       ->method('save');
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->configFactory->expects($this->once())
@@ -459,7 +458,7 @@ public function testSaveMismatch() {
     $config_object->expects($this->never())
       ->method('save');
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->configFactory->expects($this->once())
@@ -492,7 +491,7 @@ public function testSaveNoMismatch() {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . '_list', // List cache tag.
@@ -542,7 +541,7 @@ public function testSaveChangedUuid() {
         array('id', 'foo'),
       )));
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->configFactory->expects($this->at(1))
@@ -699,7 +698,7 @@ public function testLoadRevision() {
    * @covers ::deleteRevision
    */
   public function testDeleteRevision() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->assertSame(NULL, $this->entityStorage->deleteRevision(1));
@@ -725,7 +724,7 @@ public function testDelete() {
       $config_map[] = array("the_config_prefix.$id", $config_object);
     }
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . ':bar', // Own cache tag.
@@ -775,7 +774,7 @@ public function testDeleteNothing() {
     $this->configFactory->expects($this->never())
       ->method('get');
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagHandler->expects($this->never())
       ->method('invalidateTags');
 
     $this->entityStorage->delete(array());
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index 933b7ed..cf7a2f4 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -63,7 +63,14 @@ class EntityManagerTest extends UnitTestCase {
    *
    * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cache;
+  protected $cacheBackend;
+
+  /**
+   * The cache tag handler.
+   *
+   * @var \Drupal\Core\Cache\CacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTagHandler;
 
   /**
    * The language manager.
@@ -119,7 +126,8 @@ protected function setUp() {
       ->with('entity_type_build')
       ->will($this->returnValue(array()));
 
-    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
 
     $language = $this->getMock('Drupal\Core\Language\LanguageInterface');
     $language->expects($this->any())
@@ -139,7 +147,7 @@ protected function setUp() {
     $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
     $this->controllerResolver = $this->getClassResolverStub();
 
-    $this->container = $this->getContainerWithCacheBins($this->cache);
+    $this->container = $this->getContainerWithCacheBins($this->cacheTagHandler);
 
     $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
 
@@ -180,7 +188,7 @@ protected function setUpEntityManager($definitions = array()) {
       ->method('getDefinitions')
       ->will($this->returnValue($definitions));
 
-    $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cache, $this->languageManager, $this->translationManager, $this->getClassResolverStub(), $this->typedDataManager, $this->installedDefinitions, $this->eventDispatcher);
+    $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler, $this->cacheBackend, $this->languageManager, $this->translationManager, $this->getClassResolverStub(), $this->typedDataManager, $this->installedDefinitions, $this->eventDispatcher);
     $this->entityManager->setContainer($this->container);
     $this->entityManager->setDiscovery($this->discovery);
   }
@@ -193,13 +201,13 @@ protected function setUpEntityManager($definitions = array()) {
    */
   public function testClearCachedDefinitions() {
     $this->setUpEntityManager();
-    $this->cache->expects($this->at(0))
+    $this->cacheTagHandler->expects($this->at(0))
       ->method('deleteTags')
       ->with(array('entity_types'));
-    $this->cache->expects($this->at(1))
+    $this->cacheTagHandler->expects($this->at(1))
       ->method('deleteTags')
       ->with(array('entity_bundles'));
-    $this->cache->expects($this->at(2))
+    $this->cacheTagHandler->expects($this->at(2))
       ->method('deleteTags')
       ->with(array('entity_field_info'));
 
@@ -524,21 +532,21 @@ public function testGetBaseFieldDefinitionsWithCaching() {
 
     $expected = array('id' => $field_definition);
 
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(1))
+    $this->cacheBackend->expects($this->at(1))
       ->method('get')
       ->with('entity_type', FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(2))
+    $this->cacheBackend->expects($this->at(2))
       ->method('set')
       ->with('entity_type');
-    $this->cache->expects($this->at(3))
+    $this->cacheBackend->expects($this->at(3))
       ->method('set')
       ->with('entity_base_field_definitions:test_entity_type:en');
-    $this->cache->expects($this->at(4))
+    $this->cacheBackend->expects($this->at(4))
       ->method('get')
       ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue((object) array('data' => $expected)));
@@ -558,27 +566,27 @@ public function testGetFieldDefinitionsWithCaching() {
 
     $expected = array('id' => $field_definition);
 
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue((object) array('data' => $expected)));
-    $this->cache->expects($this->at(1))
+    $this->cacheBackend->expects($this->at(1))
       ->method('get')
       ->with('entity_bundle_field_definitions:test_entity_type:test_bundle:en', FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(2))
+    $this->cacheBackend->expects($this->at(2))
       ->method('get')
       ->with('entity_type', FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(3))
+    $this->cacheBackend->expects($this->at(3))
       ->method('set');
-    $this->cache->expects($this->at(4))
+    $this->cacheBackend->expects($this->at(4))
       ->method('set');
-    $this->cache->expects($this->at(5))
+    $this->cacheBackend->expects($this->at(5))
       ->method('get')
       ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue((object) array('data' => $expected)));
-    $this->cache->expects($this->at(6))
+    $this->cacheBackend->expects($this->at(6))
       ->method('get')
       ->with('entity_bundle_field_definitions:test_entity_type:test_bundle:en', FALSE)
       ->will($this->returnValue((object) array('data' => $expected)));
@@ -617,29 +625,29 @@ public function testGetFieldStorageDefinitionsWithCaching() {
       'field_storage' => $field_storage_definition,
     );
 
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
-    $this->cache->expects($this->at(1))
+    $this->cacheBackend->expects($this->at(1))
       ->method('get')
       ->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(2))
+    $this->cacheBackend->expects($this->at(2))
       ->method('get')
       ->with('entity_type', FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(3))
+    $this->cacheBackend->expects($this->at(3))
       ->method('set')
       ->with('entity_type');
-    $this->cache->expects($this->at(4))
+    $this->cacheBackend->expects($this->at(4))
       ->method('set')
       ->with('entity_field_storage_definitions:test_entity_type:en');
-    $this->cache->expects($this->at(5))
+    $this->cacheBackend->expects($this->at(5))
       ->method('get')
       ->with('entity_base_field_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue((object) array('data' => array('id' => $expected['id']))));
-    $this->cache->expects($this->at(6))
+    $this->cacheBackend->expects($this->at(6))
       ->method('get')
       ->with('entity_field_storage_definitions:test_entity_type:en', FALSE)
       ->will($this->returnValue((object) array('data' => $expected)));
@@ -771,7 +779,7 @@ protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $f
    */
   public function testClearCachedFieldDefinitions() {
     $this->setUpEntityManager();
-    $this->cache->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('deleteTags')
       ->with(array('entity_field_info'));
     $this->typedDataManager->expects($this->once())
@@ -787,7 +795,7 @@ public function testClearCachedFieldDefinitions() {
    */
   public function testClearCachedBundles() {
     $this->setUpEntityManager();
-    $this->cache->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('deleteTags')
       ->with(array('entity_bundles'));
 
@@ -859,30 +867,30 @@ public function testGetAllBundleInfo() {
       'apple' => $apple,
       'banana' => $banana,
     ));
-    $this->cache->expects($this->at(0))
+    $this->cacheBackend->expects($this->at(0))
       ->method('get')
       ->with("entity_bundle_info:en", FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(1))
+    $this->cacheBackend->expects($this->at(1))
       ->method('get')
       ->with("entity_type", FALSE)
       ->will($this->returnValue(FALSE));
-    $this->cache->expects($this->at(2))
+    $this->cacheBackend->expects($this->at(2))
       ->method('set')
       ->with("entity_type");
-    $this->cache->expects($this->at(3))
+    $this->cacheBackend->expects($this->at(3))
       ->method('set')
       ->with("entity_bundle_info:en");
-    $this->cache->expects($this->at(4))
+    $this->cacheTagHandler->expects($this->at(0))
       ->method('deleteTags')
       ->with(array('entity_types'));
-    $this->cache->expects($this->at(5))
+    $this->cacheTagHandler->expects($this->at(1))
       ->method('deleteTags')
       ->with(array('entity_bundles'));
-    $this->cache->expects($this->at(6))
+    $this->cacheTagHandler->expects($this->at(2))
       ->method('deleteTags')
       ->with(array('entity_field_info'));
-    $this->cache->expects($this->at(7))
+    $this->cacheBackend->expects($this->at(4))
       ->method('get')
       ->with("entity_bundle_info:en", FALSE)
       ->will($this->returnValue((object) array('data' => 'cached data')));
@@ -1015,7 +1023,7 @@ function testgetExtraFields() {
       ->method('getCurrentLanguage')
       ->will($this->returnValue($language));
 
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('get')
       ->with($cache_id);
 
@@ -1027,7 +1035,7 @@ function testgetExtraFields() {
       ->method('alter')
       ->with('entity_extra_field_info', $hook_bundle_extra_fields);
 
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('set')
       ->with($cache_id, $processed_hook_bundle_extra_fields[$entity_type_id][$bundle]);
 
@@ -1167,7 +1175,7 @@ public function testGetFieldMapFromCache() {
       )
     );
     $this->setUpEntityManager();
-    $this->cache->expects($this->once())
+    $this->cacheBackend->expects($this->once())
       ->method('get')
       ->with('entity_field_map')
       ->will($this->returnValue((object) array('data' => $expected)));
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index 6535732..c512fb1 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -75,9 +75,9 @@ class EntityUnitTest extends UnitTestCase {
   /**
    * The mocked cache backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagHandler;
 
   /**
    * The entity values.
@@ -116,14 +116,13 @@ protected function setUp() {
       ->with('en')
       ->will($this->returnValue(new Language(array('id' => 'en'))));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandler');
 
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('uuid', $this->uuid);
     $container->set('language_manager', $this->languageManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
+    $container->set('cache_tags', $this->cacheTagHandler);
     \Drupal::setContainer($container);
 
     $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\Entity', array($this->values, $this->entityTypeId));
@@ -393,12 +392,12 @@ public function testPreSave() {
    * @covers ::postSave
    */
   public function testPostSave() {
-    $this->cacheBackend->expects($this->at(0))
+    $this->cacheTagHandler->expects($this->at(0))
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . '_list', // List cache tag.
       ));
-    $this->cacheBackend->expects($this->at(1))
+    $this->cacheTagHandler->expects($this->at(1))
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . ':' . $this->values['id'], // Own cache tag.
@@ -450,7 +449,7 @@ public function testPreDelete() {
    * @covers ::postDelete
    */
   public function testPostDelete() {
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagHandler->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . ':' . $this->values['id'],
diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
index ee10e54..a79b9c3 100644
--- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
@@ -70,9 +70,9 @@ class KeyValueEntityStorageTest extends UnitTestCase {
   /**
    * The mocked cache backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\cacheTagHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagHandler;
 
   /**
    * {@inheritdoc}
@@ -110,7 +110,7 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') {
       ->with('test_entity_type')
       ->will($this->returnValue($this->entityType));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTagHandler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
 
     $this->keyValueStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface');
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
@@ -130,8 +130,7 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') {
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('language_manager', $this->languageManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
+    $container->set('cache_tags', $this->cacheTagHandler);
     \Drupal::setContainer($container);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index 0a58e81..89ed10c 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -121,7 +121,7 @@ protected function setUp() {
     $logger = $this->getMock('Psr\Log\LoggerInterface');
     $this->themeHandler = new TestThemeHandler($this->root, $this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $logger, $this->cssCollectionOptimizer, $this->configInstaller, $this->configManager, $this->routeBuilderIndicator, $this->extensionDiscovery);
 
-    $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $cache_backend = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
     $this->getContainerWithCacheBins($cache_backend);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
index c2ef841..db6bda3 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
@@ -190,10 +190,9 @@ public function testDefaultPluginManagerWithFilledCache() {
    */
   public function testCacheClearWithTags() {
     $cid = $this->randomMachineName();
-    $cache_backend = $this->getMockBuilder('Drupal\Core\Cache\MemoryBackend')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $cache_backend
+    $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $cache_tag_handler = $this->getMock('Drupal\Core\Cache\CacheTagHandlerInterface');
+    $cache_tag_handler
       ->expects($this->once())
       ->method('deleteTags')
       ->with(array('tag'));
@@ -201,7 +200,7 @@ public function testCacheClearWithTags() {
       ->expects($this->never())
       ->method('deleteMultiple');
 
-    $this->getContainerWithCacheBins($cache_backend);
+    $this->getContainerWithCacheBins($cache_tag_handler);
 
     $plugin_manager = new TestPluginManager($this->namespaces, $this->expectedDefinitions, NULL, NULL, '\Drupal\plugin_test\Plugin\plugin_test\fruit\FruitInterface');
     $plugin_manager->setCacheBackend($cache_backend, $cid, array('tag'));
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 43748e8..268dadd 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -8,8 +8,7 @@
 namespace Drupal\Tests;
 
 use Drupal\Component\Utility\Random;
-use Drupal\Component\Utility\String;
-use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Cache\CacheTagHandlerInterface;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 
 /**
@@ -199,22 +198,18 @@ public function getStringTranslationStub() {
   /**
    * Sets up a container with cache bins.
    *
-   * @param \Drupal\Core\Cache\CacheBackendInterface $backend
+   * @param \Drupal\Core\Cache\CacheTagHandlerInterface $cache_tags_handler
    *   The cache backend to set up.
    *
    * @return \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
    *   The container with the cache bins set up.
    */
-  protected function getContainerWithCacheBins(CacheBackendInterface $backend) {
+  protected function getContainerWithCacheBins(CacheTagHandlerInterface $cache_tags_handler) {
     $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
     $container->expects($this->any())
-      ->method('getParameter')
-      ->with('cache_bins')
-      ->will($this->returnValue(array('cache.test' => 'test')));
-    $container->expects($this->any())
       ->method('get')
-      ->with('cache.test')
-      ->will($this->returnValue($backend));
+      ->with('cache_tags')
+      ->will($this->returnValue($cache_tags_handler));
 
     \Drupal::setContainer($container);
     return $container;
diff --git a/sites/development.services.yml b/sites/development.services.yml
index cc21211..75c5f44 100644
--- a/sites/development.services.yml
+++ b/sites/development.services.yml
@@ -5,5 +5,9 @@
 services:
   cache.backend.memory:
     class: Drupal\Core\Cache\MemoryBackendFactory
+    tags:
+      - { name: cache_tags }
   cache.backend.null:
     class: Drupal\Core\Cache\NullBackendFactory
+    tags:
+      - { name: cache_tags }
