diff --git a/core/includes/cache.inc b/core/includes/cache.inc
index 341d77f..74afcbf 100644
--- a/core/includes/cache.inc
+++ b/core/includes/cache.inc
@@ -44,19 +44,38 @@ function cache($bin = 'cache') {
 }
 
 /**
- * Invalidates the items associated with given list of tags.
+ * 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 array $tags
+ *   The list of tags to delete cache items for.
+ */
+function cache_delete_tags(array $tags) {
+  foreach (CacheFactory::getBackends() as $bin => $class) {
+    cache($bin)->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 invalidate on each.
+ * and call invalidateTags() on each.
  *
  * @param array $tags
  *   The list of tags to invalidate cache items for.
  */
-function cache_invalidate(array $tags) {
+function cache_invalidate_tags(array $tags) {
   foreach (CacheFactory::getBackends() as $bin => $class) {
     cache($bin)->invalidateTags($tags);
   }
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 6800fa5..49528ae 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -6809,7 +6809,7 @@ function drupal_flush_all_caches() {
   // This is executed based on old/previously known information, which is
   // sufficient, since new extensions cannot have any primed caches yet.
   foreach (module_invoke_all('cache_flush') as $bin) {
-    cache($bin)->flush();
+    cache($bin)->deleteAll();
   }
 
   // Flush asset file caches.
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 48ee728..e9d6af8 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -103,7 +103,7 @@ function entity_get_info($entity_type = NULL) {
 function entity_info_cache_clear() {
   drupal_static_reset('entity_get_info');
   // Clear all languages.
-  cache()->invalidateTags(array('entity_info' => TRUE));
+  cache()->deleteTags(array('entity_info' => TRUE));
 }
 
 /**
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 5a5e544..fea041c 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -2616,7 +2616,7 @@ function menu_link_load($mlid) {
  * Clears the cached cached data for a single named menu.
  */
 function menu_cache_clear($menu_name = 'navigation') {
-  cache('menu')->invalidateTags(array('menu' => $menu_name));
+  cache('menu')->deleteTags(array('menu' => $menu_name));
   // Also clear the menu system static caches.
   menu_reset_static_cache();
 }
@@ -2628,7 +2628,7 @@ function menu_cache_clear($menu_name = 'navigation') {
  * might have been made to the router items or menu links.
  */
 function menu_cache_clear_all() {
-  cache('menu')->flush();
+  cache('menu')->deleteAll();
   menu_reset_static_cache();
 }
 
@@ -3257,13 +3257,13 @@ function _menu_clear_page_cache() {
   // Clear the page and block caches, but at most twice, including at
   //  the end of the page load when there are multiple links saved or deleted.
   if ($cache_cleared == 0) {
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
     // Keep track of which menus have expanded items.
     _menu_set_expanded_menus();
     $cache_cleared = 1;
   }
   elseif ($cache_cleared == 1) {
-    drupal_register_shutdown_function('cache_invalidate', array('content', TRUE));
+    drupal_register_shutdown_function('cache_invalidate_tags', array('content', TRUE));
     // Keep track of which menus have expanded items.
     drupal_register_shutdown_function('_menu_set_expanded_menus');
     $cache_cleared = 2;
diff --git a/core/includes/schema.inc b/core/includes/schema.inc
index f46739c..7ace4b5 100644
--- a/core/includes/schema.inc
+++ b/core/includes/schema.inc
@@ -108,7 +108,7 @@ function drupal_get_complete_schema($rebuild = FALSE) {
         cache()->set('schema', $schema);
       }
       if ($rebuild) {
-        cache()->invalidateTags(array('schema' => TRUE));
+        cache()->deleteTags(array('schema' => TRUE));
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Cache/BackendChain.php b/core/lib/Drupal/Core/Cache/BackendChain.php
index 4918767..f913d5f 100644
--- a/core/lib/Drupal/Core/Cache/BackendChain.php
+++ b/core/lib/Drupal/Core/Cache/BackendChain.php
@@ -31,6 +31,15 @@ class BackendChain implements CacheBackendInterface {
   protected $backends = array();
 
   /**
+   * Constructs a DatabaseBackend object.
+   *
+   * @param string $bin
+   *   The cache bin for which the object is created.
+   */
+  public function __construct($bin) {
+  }
+
+  /**
    * Appends a cache backend to the cache chain.
    *
    * @param CacheBackendInterface $backend
@@ -61,17 +70,11 @@ class BackendChain implements CacheBackendInterface {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::__construct().
-   */
-  public function __construct($bin) {
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
-  public function get($cid) {
+  public function get($cid, $allowInvalid = FALSE) {
     foreach ($this->backends as $index => $backend) {
-      if (($return = $backend->get($cid)) !== FALSE) {
+      if (($return = $backend->get($cid, $allowInvalid)) !== FALSE) {
         // We found a result, propagate it to all missed backends.
         if ($index > 0) {
           for ($i = ($index - 1); 0 <= $i; --$i) {
@@ -89,11 +92,11 @@ class BackendChain implements CacheBackendInterface {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
-  function getMultiple(&$cids) {
+  public function getMultiple(&$cids, $allowInvalid = FALSE) {
     $return = array();
 
     foreach ($this->backends as $index => $backend) {
-      $items = $backend->getMultiple($cids);
+      $items = $backend->getMultiple($cids, $allowInvalid);
 
       // Propagate the values that could be retrieved from the current cache
       // backend to all missed backends.
@@ -120,7 +123,7 @@ function getMultiple(&$cids) {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
-  function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
+  public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
     foreach ($this->backends as $backend) {
       $backend->set($cid, $data, $expire, $tags);
     }
@@ -129,7 +132,7 @@ function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, arra
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::delete().
    */
-  function delete($cid) {
+  public function delete($cid) {
     foreach ($this->backends as $backend) {
       $backend->delete($cid);
     }
@@ -138,27 +141,54 @@ function delete($cid) {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
    */
-  function deleteMultiple(array $cids) {
+  public function deleteMultiple(array $cids) {
     foreach ($this->backends as $backend) {
       $backend->deleteMultiple($cids);
     }
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::flush().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
    */
-  public function flush() {
+  public function deleteTags(array $tags) {
     foreach ($this->backends as $backend) {
-      $backend->flush();
+      $backend->deleteTags($tags);
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
+   */
+  public function deleteAll() {
+    foreach ($this->backends as $backend) {
+      $backend->deleteAll();
     }
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::expire().
    */
-  public function expire() {
+  public function deleteExpired() {
+    foreach ($this->backends as $backend) {
+      $backend->deleteExpired();
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
+   */
+  public function invalidate($cid) {
+    foreach ($this->backends as $backend) {
+      $backend->invalidate($cid);
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple().
+   */
+  public function invalidateMultiple(array $cids) {
     foreach ($this->backends as $backend) {
-      $backend->expire();
+      $backend->invalidateMultiple($cids);
     }
   }
 
diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
index ee1df76..4c30559 100644
--- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
+++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
@@ -48,54 +48,59 @@
 interface CacheBackendInterface {
 
   /**
-   * Indicates that the item should never be removed unless explicitly selected.
-   *
-   * The item may be removed using cache()->delete() with a cache ID.
+   * Indicates that the item should never be removed unless explicitly deleted.
    */
   const CACHE_PERMANENT = 0;
 
   /**
    * Returns data from the persistent cache.
    *
-   * Data may be stored as either plain text or as serialized data. cache_get()
-   * will automatically return unserialized objects and arrays.
-   *
-   * @param $cid
+   * @param string $cid
    *   The cache ID of the data to retrieve.
+   * @param bool $allowInvalid
+   *   (optional) If TRUE, a cache item may be returned even if it is expired or
+   *   has been invalidated. The "valid" property of the returned object
+   *   indicates whether the item is valid or not. Defaults to FALSE.
    *
-   * @return
-   *   The cache or FALSE on failure.
+   * @return object|false
+   *   The cache item or FALSE on failure.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::getMultiple()
    */
-  public function get($cid);
+  public function get($cid, $allowInvalid = FALSE);
 
   /**
    * Returns data from the persistent cache when given an array of cache IDs.
    *
-   * @param $cids
+   * @param array $cids
    *   An array of cache IDs for the data to retrieve. This is passed by
    *   reference, and will have the IDs successfully returned from cache
    *   removed.
+   * @param bool $allowInvalid
+   *   (optional) If TRUE, cache items may be returned even if they have expired
+   *   or been invalidated. The "valid" property of the returned objects
+   *   indicates whether each item is valid or not. Defaults to FALSE.
    *
-   * @return
-   *   An array of the items successfully returned from cache indexed by cid.
+   * @return array
+   *   An array of cache item objects indexed by cache ID.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::get()
    */
-  public function getMultiple(&$cids);
+  public function getMultiple(&$cids, $allowInvalid = FALSE);
 
   /**
    * Stores data in the persistent cache.
    *
-   * @param $cid
+   * @param string $cid
    *   The cache ID of the data to store.
-   * @param $data
-   *   The data to store in the cache. Complex data types will be automatically
-   *   serialized before insertion.
-   *   Strings will be stored as plain text and not serialized.
-   * @param $expire
+   * @param mixed $data
+   *   The data to store in the cache.
+   * @param int $expire
    *   One of the following values:
-   *   - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item
-   *     should never be removed unless cache->delete($cid) is used explicitly.
-   *   - A Unix timestamp: Indicates that the item should be kept at least until
-   *     the given time.
+   *   - CacheBackendInterface::CACHE_PERMANENT: Indicates that the item should
+   *     not be removed unless it is deleted explicitly.
+   *   - A Unix timestamp: Indicates that the item will be considered invalid
+   *     after this time.
    * @param array $tags
    *   An array of tags to be stored with the cache item. These should normally
    *   identify objects used to build the cache item, which should trigger
@@ -108,42 +113,132 @@
   /**
    * Deletes an item from the cache.
    *
-   * @param $cid
-   *    The cache ID to delete.
+   * If the cache item is being deleted because it is no longer "fresh", you may
+   * consider using invalidate() instead. This allows callers to retrieve the
+   * invalid item by calling get() with $allowInvalid set to TRUE. In some cases
+   * an invalid item may be acceptable rather than having to rebuild the cache.
+   *
+   * @param string $cid
+   *   The cache ID to delete.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteAll()
    */
   public function delete($cid);
 
   /**
    * Deletes multiple items from the cache.
    *
-   * @param $cids
-   *   An array of $cids to delete.
+   * If the cache items are being deleted because it is no longer "fresh", you
+   * may consider using invalidateMultiple() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allowInvalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $cids
+   *   An array of cache IDs to delete.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteExpired()
+   */
+  public function deleteMultiple(array $cids);
+
+  /**
+   * Deletes items with any of the specified tags.
+   *
+   * If the cache items are being deleted because it is no longer "fresh", you
+   * may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allowInvalid 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()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteExpired()
    */
-  public function deleteMultiple(Array $cids);
+  public function deleteTags(array $tags);
 
   /**
-   * Flushes all cache items in a bin.
+   * Deletes all cache items in a bin.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteExpired()
    */
-  public function flush();
+  public function deleteAll();
 
   /**
-   * Expires temporary items from the cache.
+   * Deletes expired items from the cache.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteAll()
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteExpired()
    */
-  public function expire();
+  public function deleteExpired();
 
   /**
-   * Invalidates each tag in the $tags array.
+   * Marks a cache item as invalid.
+   *
+   * Invalid items may be returned in later calls to get(), if the $allowInvalid
+   * argument is TRUE.
+   *
+   * @param string $cid
+   *   The cache ID to invalidate.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::delete()
+   * @see Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
+   * @see Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
+   */
+  public function invalidate($cid);
+
+  /**
+   * Marks cache items as invalid.
+   *
+   * Invalid items may be returned in later calls to get(), if the $allowInvalid
+   * argument is TRUE.
+   *
+   * @param string $cids
+   *   An array of cache IDs to invalidate.
+   *
+   * @see Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
+   * @see Drupal\Core\Cache\CacheBackendInterface::invalidate()
+   * @see Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
+   */
+  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 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()
    */
   public function invalidateTags(array $tags);
 
   /**
    * Performs garbage collection on a cache bin.
+   *
+   * The backend may choose to delete expired or invalidated items.
    */
   public function garbageCollection();
 
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index a12ed13..a82df6a 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Database\Database;
 use Exception;
+use PDO;
 
 /**
  * Defines a default cache implementation.
@@ -24,11 +25,6 @@ class DatabaseBackend implements CacheBackendInterface {
   protected $bin;
 
   /**
-   * A static cache of all tags checked during the request.
-   */
-  protected static $tagCache = array();
-
-  /**
    * Constructs a DatabaseBackend object.
    *
    * @param string $bin
@@ -46,16 +42,16 @@ class DatabaseBackend implements CacheBackendInterface {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
-  public function get($cid) {
+  public function get($cid, $allowInvalid = FALSE) {
     $cids = array($cid);
-    $cache = $this->getMultiple($cids);
+    $cache = $this->getMultiple($cids, $allowInvalid);
     return reset($cache);
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
-  public function getMultiple(&$cids) {
+  public function getMultiple(&$cids, $allowInvalid = FALSE) {
     try {
       // When serving cached pages, the overhead of using ::select() was found
       // to add around 30% overhead to the request. Since $this->bin is a
@@ -64,10 +60,10 @@ class DatabaseBackend implements CacheBackendInterface {
       // is used here only due to the performance overhead we would incur
       // otherwise. When serving an uncached page, the overhead of using
       // ::select() is a much smaller proportion of the request.
-      $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
+      $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum_invalidations, checksum_deletions FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
       $cache = array();
       foreach ($result as $item) {
-        $item = $this->prepareItem($item);
+        $item = $this->prepareItem($item, $allowInvalid);
         if ($item) {
           $cache[$item->cid] = $item;
         }
@@ -90,22 +86,37 @@ class DatabaseBackend implements CacheBackendInterface {
    *
    * @param stdClass $cache
    *   An item loaded from cache_get() or cache_get_multiple().
+   * @param bool $allowInvalid
+   *   If FALSE, the method returns FALSE if the cache item is not valid.
    *
-   * @return mixed
-   *   The item with data unserialized as appropriate or FALSE if there is no
-   *   valid item to load.
+   * @return mixed|false
+   *   The item with data unserialized as appropriate and a property indicating
+   *   whether the item is valid, or FALSE if there is no valid item to load.
    */
-  protected function prepareItem($cache) {
+  protected function prepareItem($cache, $allowInvalid) {
     if (!isset($cache->data)) {
       return FALSE;
     }
 
-    // The cache data is invalid if any of its tags have been cleared since.
-    if ($cache->tags) {
-      $cache->tags = explode(' ', $cache->tags);
-      if (!$this->validTags($cache->checksum, $cache->tags)) {
-        return FALSE;
-      }
+    $cache->tags = $cache->tags ? explode(' ', $cache->tags) : array();
+
+    $checksum = $this->checksumTags($cache->tags);
+
+    // Check if deleteTags() has been called with any of the entry's tags.
+    if ($cache->checksum_deletions != $checksum['deletions']) {
+      return FALSE;
+    }
+
+    // Check expire time.
+    $cache->valid = $cache->expire == CacheBackendInterface::CACHE_PERMANENT || $cache->expire >= REQUEST_TIME;
+
+    // Check if invalidateTags() has been called with any of the entry's tags.
+    if ($cache->checksum_invalidations != $checksum['invalidations']) {
+      $cache->valid = FALSE;
+    }
+
+    if (!$allowInvalid && !$cache->valid) {
+      return FALSE;
     }
 
     // Unserialize and return the cached data.
@@ -120,23 +131,26 @@ class DatabaseBackend implements CacheBackendInterface {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
-    $fields = array(
-      'serialized' => 0,
-      'created' => REQUEST_TIME,
-      'expire' => $expire,
-      'tags' => implode(' ', $this->flattenTags($tags)),
-      'checksum' => $this->checksumTags($tags),
-    );
-    if (!is_string($data)) {
-      $fields['data'] = serialize($data);
-      $fields['serialized'] = 1;
-    }
-    else {
-      $fields['data'] = $data;
-      $fields['serialized'] = 0;
-    }
-
     try {
+      $flat_tags = $this->flattenTags($tags);
+      $checksum = $this->checksumTags($flat_tags);
+      $fields = array(
+        'serialized' => 0,
+        'created' => REQUEST_TIME,
+        'expire' => $expire,
+        'tags' => implode(' ', $flat_tags),
+        'checksum_invalidations' => $checksum['invalidations'],
+        'checksum_deletions' => $checksum['deletions'],
+      );
+      if (!is_string($data)) {
+        $fields['data'] = serialize($data);
+        $fields['serialized'] = 1;
+      }
+      else {
+        $fields['data'] = $data;
+        $fields['serialized'] = 0;
+      }
+
       Database::getConnection()->merge($this->bin)
         ->key(array('cid' => $cid))
         ->fields($fields)
@@ -170,16 +184,31 @@ class DatabaseBackend implements CacheBackendInterface {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::flush().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
    */
-  public function flush() {
+  public function deleteTags(array $tags) {
+    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+    foreach ($this->flattenTags($tags) as $tag) {
+      unset($tag_cache[$tag]);
+      Database::getConnection()->merge('cache_tags')
+        ->insertFields(array('deletions' => 1))
+        ->expression('deletions', 'deletions + 1')
+        ->key(array('tag' => $tag))
+        ->execute();
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
+   */
+  public function deleteAll() {
     Database::getConnection()->truncate($this->bin)->execute();
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::expire().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteExpired().
    */
-  public function expire() {
+  public function deleteExpired() {
     Database::getConnection()->delete($this->bin)
       ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>')
       ->condition('expire', REQUEST_TIME, '<')
@@ -187,36 +216,56 @@ class DatabaseBackend implements CacheBackendInterface {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
    */
-  public function garbageCollection() {
-    $this->expire();
+  public function invalidate($cid) {
+    $this->invalidateMultiple(array($cid));
   }
 
   /**
-   * Compares two checksums of tags. Used to determine whether to serve a cached
-   * item or treat it as invalidated.
-   *
-   * @param integer $checksum
-   *   The initial checksum to compare against.
-   * @param array $tags
-   *   An array of tags to calculate a checksum for.
-   *
-   * @return boolean
-   *   TRUE if the checksums match, FALSE otherwise.
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalideMultiple().
+   */
+  public function invalidateMultiple(array $cids) {
+    // Update in chunks when a large array is passed.
+    do {
+      Database::getConnection()->update($this->bin)
+        ->fields(array('expire' => REQUEST_TIME - 1))
+        ->condition('cid', array_splice($cids, 0, 1000), 'IN')
+        ->execute();
+    }
+    while (count($cids));
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
    */
-  protected function validTags($checksum, array $tags) {
-    return $checksum == $this->checksumTags($tags);
+  public function invalidateTags(array $tags) {
+    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+    foreach ($this->flattenTags($tags) as $tag) {
+      unset($tag_cache[$tag]);
+      Database::getConnection()->merge('cache_tags')
+        ->insertFields(array('invalidations' => 1))
+        ->expression('invalidations', 'invalidations + 1')
+        ->key(array('tag' => $tag))
+        ->execute();
+    }
   }
 
   /**
-   * Flattens a tags array into a numeric array suitable for string storage.
+   * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection().
+   */
+  public function garbageCollection() {
+    $this->deleteExpired();
+  }
+
+  /**
+   * 'Flattens' a tags array into an array of strings.
    *
    * @param array $tags
    *   Associative array of tags to flatten.
    *
    * @return array
-   *   Numeric array of flattened tag identifiers.
+   *   An indexed array of flattened tag identifiers.
    */
   protected function flattenTags(array $tags) {
     if (isset($tags[0])) {
@@ -238,51 +287,38 @@ class DatabaseBackend implements CacheBackendInterface {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {
-    foreach ($this->flattenTags($tags) as $tag) {
-      unset(self::$tagCache[$tag]);
-      Database::getConnection()->merge('cache_tags')
-        ->key(array('tag' => $tag))
-        ->fields(array('invalidations' => 1))
-        ->expression('invalidations', 'invalidations + 1')
-        ->execute();
-    }
-  }
-
-  /**
    * Returns the sum total of validations for a given set of tags.
    *
    * @param array $tags
-   *   Associative array of tags.
+   *   Array of flat tags.
    *
-   * @return integer
+   * @return int
    *   Sum of all invalidations.
+   *
+   * @see Drupal\Core\Cache\DatabaseBackend::flattenTags()
    */
-  protected function checksumTags($tags) {
-    $checksum = 0;
-    $query_tags = array();
+  protected function checksumTags($flat_tags) {
+    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
 
-    foreach ($this->flattenTags($tags) as $tag) {
-      if (isset(self::$tagCache[$tag])) {
-        $checksum += self::$tagCache[$tag];
-      }
-      else {
-        $query_tags[] = $tag;
-      }
-   }
+    $checksum = array(
+      'invalidations' => 0,
+      'deletions' => 0,
+    );
+
+    $query_tags = array_diff($flat_tags, array_keys($tag_cache));
     if ($query_tags) {
-      try {
-        if ($db_tags = Database::getConnection()->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) {
-          self::$tagCache = array_merge(self::$tagCache, $db_tags);
-          $checksum += array_sum($db_tags);
-        }
-      }
-      catch (Exception $e) {
-        // The database may not be available, so we'll ignore cache_set requests.
-      }
+      $db_tags = Database::getConnection()->query('SELECT tag, invalidations, deletions FROM {cache_tags} 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 ($flat_tags as $tag) {
+      $checksum['invalidations'] += $tag_cache[$tag]['invalidations'];
+      $checksum['deletions'] += $tag_cache[$tag]['deletions'];
+    }
+
     return $checksum;
   }
 
diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php
index e23294a..b2ae035 100644
--- a/core/lib/Drupal/Core/Cache/InstallBackend.php
+++ b/core/lib/Drupal/Core/Cache/InstallBackend.php
@@ -36,14 +36,14 @@ class InstallBackend extends DatabaseBackend {
   /**
    * Overrides Drupal\Core\Cache\DatabaseBackend::get().
    */
-  public function get($cid) {
+  public function get($cid, $allowInvalid = FALSE) {
     return FALSE;
   }
 
   /**
    * Overrides Drupal\Core\Cache\DatabaseBackend::getMultiple().
    */
-  public function getMultiple(&$cids) {
+  public function getMultiple(&$cids, $allowInvalid = FALSE) {
     return array();
   }
 
@@ -77,36 +77,72 @@ class InstallBackend extends DatabaseBackend {
   }
 
   /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateTags().
+   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteAll().
    */
-  public function invalidateTags(array $tags) {
+  public function deleteAll() {
     try {
       if (class_exists('Drupal\Core\Database\Database')) {
-        parent::invalidateTags($tags);
+        parent::deleteAll();
       }
     }
     catch (Exception $e) {}
   }
 
   /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::flush().
+   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteExpired().
    */
-  public function flush() {
+  public function deleteExpired() {
     try {
       if (class_exists('Drupal\Core\Database\Database')) {
-        parent::flush();
+        parent::deleteExpired();
       }
     }
     catch (Exception $e) {}
   }
 
   /**
-   * Overrides Drupal\Core\Cache\DatabaseBackend::expire().
+   * Overrides Drupal\Core\Cache\DatabaseBackend::deleteTags().
    */
-  public function expire() {
+  public function deleteTags(array $tags) {
     try {
       if (class_exists('Drupal\Core\Database\Database')) {
-        parent::expire();
+        parent::deleteTags($tags);
+      }
+    }
+    catch (Exception $e) {}
+  }
+
+  /**
+   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidate().
+   */
+  public function invalidate($cid) {
+    try {
+      if (class_exists('Drupal\Core\Database\Database')) {
+        parent::invalidate($cid);
+      }
+    }
+    catch (Exception $e) {}
+  }
+
+  /**
+   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateMultiple().
+   */
+  public function invalidateMultiple(array $cids) {
+    try {
+      if (class_exists('Drupal\Core\Database\Database')) {
+        parent::invalidateMultiple($cids);
+      }
+    }
+    catch (Exception $e) {}
+  }
+
+  /**
+   * Overrides Drupal\Core\Cache\DatabaseBackend::invalidateTags().
+   */
+  public function invalidateTags(array $tags) {
+    try {
+      if (class_exists('Drupal\Core\Database\Database')) {
+        parent::invalidateTags($tags);
       }
     }
     catch (Exception $e) {}
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index 837df0e..87c970a 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -24,11 +24,6 @@ class MemoryBackend implements CacheBackendInterface {
   protected $cache = array();
 
   /**
-   * All tags invalidated during the request.
-   */
-  protected $invalidatedTags = array();
-
-  /**
    * Constructs a MemoryBackend object.
    *
    * @param string $bin
@@ -40,9 +35,9 @@ class MemoryBackend implements CacheBackendInterface {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
-  public function get($cid) {
+  public function get($cid, $allowInvalid = FALSE) {
     if (isset($this->cache[$cid])) {
-      return $this->prepareItem($this->cache[$cid]);
+      return $this->prepareItem($this->cache[$cid], $allowInvalid);
     }
     else {
       return FALSE;
@@ -52,13 +47,13 @@ class MemoryBackend implements CacheBackendInterface {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
-  public function getMultiple(&$cids) {
+  public function getMultiple(&$cids, $allowInvalid = FALSE) {
     $ret = array();
 
     $items = array_intersect_key($this->cache, array_flip($cids));
 
     foreach ($items as $item) {
-      $item = $this->prepareItem($item);
+      $item = $this->prepareItem($item, $allowInvalid);
       if ($item) {
         $ret[$item->cid] = $item;
       }
@@ -82,13 +77,15 @@ class MemoryBackend implements CacheBackendInterface {
    *   The item with data as appropriate or FALSE if there is no
    *   valid item to load.
    */
-  protected function prepareItem($cache) {
+  protected function prepareItem($cache, $allowInvalid) {
     if (!isset($cache->data)) {
       return FALSE;
     }
 
-    // The cache data is invalid if any of its tags have been cleared since.
-    if (count($cache->tags) && $this->hasInvalidatedTags($cache)) {
+    // Check expire time.
+    $cache->valid = $cache->expire == CacheBackendInterface::CACHE_PERMANENT || $cache->expire >= REQUEST_TIME;
+
+    if (!$allowInvalid && !$cache->valid) {
       return FALSE;
     }
 
@@ -102,29 +99,13 @@ class MemoryBackend implements CacheBackendInterface {
     $this->cache[$cid] = (object) array(
       'cid' => $cid,
       'data' => $data,
+      'created' => REQUEST_TIME,
       'expire' => $expire,
-      'tags' => $tags,
-      'checksum' => $this->checksum($this->flattenTags($tags)),
+      'tags' => $this->flattenTags($tags),
     );
   }
 
   /**
-   * Calculates a checksum so data can be invalidated using tags.
-   */
-  public function checksum($tags) {
-    $checksum = '';
-
-    foreach ($tags as $tag) {
-      // Has the tag already been invalidated.
-      if (isset($this->invalidatedTags[$tag])) {
-        $checksum = $checksum . $tag . ':' . $this->invalidatedTags[$tag];
-      }
-    }
-
-    return $checksum;
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::delete().
    */
   public function delete($cid) {
@@ -139,47 +120,70 @@ class MemoryBackend implements CacheBackendInterface {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::flush().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
+   */
+  public function deleteTags(array $tags) {
+    $flat_tags = $this->flattenTags($tags);
+    foreach ($this->cache as $cid => $item) {
+      if (array_intersect($flat_tags, $item->tags)) {
+        unset($this->cache[$cid]);
+      }
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
-  public function flush() {
+  public function deleteAll() {
     $this->cache = array();
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::expire().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteExpired().
    *
-   * Cache expiration is not implemented for PHP ArrayBackend as this backend
-   * only persists during a single request and expiration are done using
+   * Cache expiration is not implemented for MemoryBackend as this backend only
+   * persists during a single request and expiration are done using
    * REQUEST_TIME.
    */
-  public function expire() {
+  public function deleteExpired() {
   }
 
   /**
-   * Checks to see if any of the tags associated with a cache object have been
-   * invalidated.
-   *
-   * @param object @cache
-   *   An cache object to calculate and compare it's original checksum for.
-   *
-   * @return boolean
-   *   TRUE if the a tag has been invalidated, FALSE otherwise.
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
+   */
+  public function invalidate($cid) {
+    $this->cache[$cid]->expire = REQUEST_TIME - 1;
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple().
    */
-  protected function hasInvalidatedTags($cache) {
-    if ($cache->checksum != $this->checksum($this->flattenTags($cache->tags))) {
-      return TRUE;
+  public function invalidateMultiple(array $cids) {
+    foreach ($cids as $cid) {
+      $this->cache[$cid]->expire = REQUEST_TIME - 1;
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
+   */
+  public function invalidateTags(array $tags) {
+    $flat_tags = $this->flattenTags($tags);
+    foreach ($this->cache as $cid => $item) {
+      if (array_intersect($flat_tags, $item->tags)) {
+        $this->cache[$cid]->expire = REQUEST_TIME - 1;
+      }
     }
-    return FALSE;
   }
 
   /**
-   * Flattens a tags array into a numeric array suitable for string storage.
+   * 'Flattens' a tags array into an array of strings.
    *
    * @param array $tags
    *   Associative array of tags to flatten.
    *
-   * @return
-   *   An array of flattened tag identifiers.
+   * @return array
+   *   An indexed array of strings.
    */
   protected function flattenTags(array $tags) {
     if (isset($tags[0])) {
@@ -201,20 +205,6 @@ class MemoryBackend implements CacheBackendInterface {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {
-    foreach ($this->flattenTags($tags) as $tag) {
-      if (isset($this->invalidatedTags[$tag])) {
-        $this->invalidatedTags[$tag] = $this->invalidatedTags[$tag] + 1;
-      }
-      else {
-        $this->invalidatedTags[$tag] = 1;
-      }
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty().
    */
   public function isEmpty() {
diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php
index 66a9938..96e35a6 100644
--- a/core/lib/Drupal/Core/Cache/NullBackend.php
+++ b/core/lib/Drupal/Core/Cache/NullBackend.php
@@ -31,14 +31,14 @@ class NullBackend implements CacheBackendInterface {
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
-  public function get($cid) {
+  public function get($cid, $allowInvalid = FALSE) {
     return FALSE;
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple().
    */
-  public function getMultiple(&$cids) {
+  public function getMultiple(&$cids, $allowInvalid = FALSE) {
     return array();
   }
 
@@ -58,19 +58,29 @@ class NullBackend implements CacheBackendInterface {
   public function deleteMultiple(array $cids) {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::flush().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
-  public function flush() {}
+  public function deleteAll() {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::expire().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteExpired().
    */
-  public function expire() {}
+  public function deleteExpired() {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection().
+   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
    */
-  public function garbageCollection() {}
+  public function deleteTags(array $tags) {}
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
+   */
+  public function invalidate($cid) {}
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple().
+   */
+  public function invalidateMultiple(array $cids) {}
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
@@ -78,6 +88,11 @@ class NullBackend implements CacheBackendInterface {
   public function invalidateTags(array $tags) {}
 
   /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection().
+   */
+  public function garbageCollection() {}
+
+  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty().
    */
   public function isEmpty() {
diff --git a/core/modules/aggregator/aggregator.parser.inc b/core/modules/aggregator/aggregator.parser.inc
index bacaa84..ff2e522 100644
--- a/core/modules/aggregator/aggregator.parser.inc
+++ b/core/modules/aggregator/aggregator.parser.inc
@@ -45,7 +45,7 @@ function aggregator_aggregator_parse($feed) {
     $feed->modified = $modified;
 
     // Clear the page and block caches.
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
 
     return TRUE;
   }
diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc
index 2a17a55..2ef6602 100644
--- a/core/modules/block/block.admin.inc
+++ b/core/modules/block/block.admin.inc
@@ -207,7 +207,7 @@ function block_admin_display_form_submit($form, &$form_state) {
     throw $e;
   }
   drupal_set_message(t('The block settings have been updated.'));
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 }
 
 /**
@@ -606,7 +606,7 @@ function block_admin_configure_submit($form, &$form_state) {
       throw $e;
     }
     drupal_set_message(t('The block configuration has been saved.'));
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
     $form_state['redirect'] = 'admin/structure/block';
   }
 }
@@ -715,7 +715,7 @@ function block_add_block_form_submit($form, &$form_state) {
   }
 
   drupal_set_message(t('The block has been created.'));
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
   $form_state['redirect'] = 'admin/structure/block';
 }
 
@@ -763,7 +763,7 @@ function block_custom_block_delete_submit($form, &$form_state) {
     ->execute();
 
   drupal_set_message(t('The block %name has been removed.', array('%name' => $form_state['values']['info'])));
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
   $form_state['redirect'] = 'admin/structure/block';
   return;
 }
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php
index 3a5776c..d2d6c64 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockCacheTest.php
@@ -74,7 +74,7 @@ function testCachePerRole() {
     $this->assertText($old_content, 'Block is served from the cache.');
 
     // Clear the cache and verify that the stale data is no longer there.
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
     $this->drupalGet('');
     $this->assertNoText($old_content, 'Block cache clear removes stale cache data.');
     $this->assertText($current_content, 'Fresh block content is displayed after clearing the cache.');
diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc
index dcbd1bc..01594cd 100644
--- a/core/modules/comment/comment.admin.inc
+++ b/core/modules/comment/comment.admin.inc
@@ -197,7 +197,7 @@ function comment_admin_overview_submit($form, &$form_state) {
   }
   drupal_set_message(t('The update has been performed.'));
   $form_state['redirect'] = 'admin/content/comment';
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 }
 
 /**
@@ -245,7 +245,7 @@ function comment_multiple_delete_confirm($form, &$form_state) {
 function comment_multiple_delete_confirm_submit($form, &$form_state) {
   if ($form_state['values']['confirm']) {
     comment_delete_multiple(array_keys($form_state['values']['comments']));
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
     $count = count($form_state['values']['comments']);
     watchdog('content', 'Deleted @count comments.', array('@count' => $count));
     drupal_set_message(format_plural($count, 'Deleted 1 comment.', 'Deleted @count comments.'));
@@ -304,7 +304,7 @@ function comment_confirm_delete_submit($form, &$form_state) {
   drupal_set_message(t('The comment and all its replies have been deleted.'));
   watchdog('content', 'Deleted comment @cid and its replies.', array('@cid' => $comment->cid));
   // Clear the cache so an anonymous user sees that his comment was deleted.
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 
   $form_state['redirect'] = "node/$comment->nid";
 }
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index df0a33a..9facf2a 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1953,7 +1953,7 @@ function comment_unpublish_by_keyword_action_submit($form, $form_state) {
  */
 function comment_save_action(Comment $comment) {
   comment_save($comment);
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
   watchdog('action', 'Saved comment %title', array('%title' => $comment->subject));
 }
 
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
index cead0cd..2315613 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
@@ -374,6 +374,6 @@ class CommentFormController extends EntityFormController {
     $form_state['redirect'] = $redirect;
     // Clear the block and page caches so that anonymous users see the comment
     // they have posted.
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
   }
 }
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php
index 0ec3af2..895fbd4 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentBlockTest.php
@@ -73,7 +73,7 @@ function testRecentCommentBlock() {
     user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access comments'));
     // drupalCreateNode() does not automatically flush content caches unlike
     // posting a node from a node form.
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
     $this->drupalGet('');
     $this->assertNoText($block['title'], 'Block was not found.');
     user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access comments'));
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index 323a4fa..9c64bcd 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -147,7 +147,7 @@ function _field_info_collate_types() {
 function _field_info_collate_types_reset() {
   drupal_static_reset('_field_info_collate_types');
   // Clear all languages.
-  cache('field')->invalidateTags(array('field_info_types' => TRUE));
+  cache('field')->deleteTags(array('field_info_types' => TRUE));
 }
 
 /**
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 7fac3d2..3c4d7a6 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -824,7 +824,7 @@ function _field_extra_fields_pre_render($elements) {
  * Clears the field info and field data caches.
  */
 function field_cache_clear() {
-  cache('field')->flush();
+  cache('field')->deleteAll();
   field_info_cache_clear();
 }
 
diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php
index accbe17..817e3f3 100644
--- a/core/modules/field/lib/Drupal/field/FieldInfo.php
+++ b/core/modules/field/lib/Drupal/field/FieldInfo.php
@@ -112,7 +112,7 @@ class FieldInfo {
 
     $this->bundleExtraFields = array();
 
-    cache('field')->invalidateTags(array('field_info' => TRUE));
+    cache('field')->deleteTags(array('field_info' => TRUE));
   }
 
   /**
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index b55066f..f2bfa02 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -310,7 +310,7 @@ function filter_format_save($format) {
     $return = SAVED_UPDATED;
 
     // Clear the filter cache whenever a text format is updated.
-    cache('filter')->invalidateTags(array('filter_format' => $format->format));
+    cache('filter')->deleteTags(array('filter_format' => $format->format));
   }
 
   filter_formats_reset();
@@ -340,7 +340,7 @@ function filter_format_disable($format) {
 
   // Clear the filter cache whenever a text format is disabled.
   filter_formats_reset();
-  cache('filter')->invalidateTags(array('filter_format' => $format->format));
+  cache('filter')->deleteTags(array('filter_format' => $format->format));
 }
 
 /**
@@ -487,7 +487,7 @@ function filter_formats($account = NULL) {
  * @see filter_formats()
  */
 function filter_formats_reset() {
-  cache()->invalidateTags(array('filter_formats' => TRUE));
+  cache()->deleteTags(array('filter_formats' => TRUE));
   cache()->delete('filter_list_format');
   drupal_static_reset('filter_list_format');
   drupal_static_reset('filter_formats');
diff --git a/core/modules/forum/forum.admin.inc b/core/modules/forum/forum.admin.inc
index e3c564a..e128aa4 100644
--- a/core/modules/forum/forum.admin.inc
+++ b/core/modules/forum/forum.admin.inc
@@ -115,7 +115,7 @@ function forum_form_submit($form, &$form_state) {
     case SAVED_UPDATED:
       drupal_set_message(t('The @type %term has been updated.', array('%term' => $form_state['values']['name'], '@type' => $type)));
       // Clear the page and block caches to avoid stale data.
-      cache_invalidate(array('content' => TRUE));
+      cache_invalidate_tags(array('content' => TRUE));
       break;
   }
   $form_state['redirect'] = 'admin/structure/forum';
diff --git a/core/modules/image/image.api.php b/core/modules/image/image.api.php
index 1879a07..26fcc28 100644
--- a/core/modules/image/image.api.php
+++ b/core/modules/image/image.api.php
@@ -79,7 +79,7 @@ function hook_image_effect_info_alter(&$effects) {
  */
 function hook_image_style_flush($style) {
   // Empty cached data that contains information about the style.
-  cache('mymodule')->flush();
+  cache('mymodule')->deleteAll();
 }
 
  /**
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 315f99a..aa5ac8e 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -835,9 +835,9 @@ function image_style_flush($style) {
 
   // Clear page caches when flushing.
   if (module_exists('block')) {
-    cache('block')->flush();
+    cache('block')->deleteAll();
   }
-  cache('page')->flush();
+  cache('page')->deleteAll();
 }
 
 /**
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php
index 7ac92ad..7dd2a8a 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleTranslationTest.php
@@ -249,7 +249,7 @@ function testJavaScriptTranslation() {
     // Test JavaScript translation rebuilding.
     file_unmanaged_delete($js_file);
     $this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found'))));
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
     _locale_rebuild_js($langcode);
     $this->assertTrue($result = file_exists($js_file), t('JavaScript file rebuilt: %file', array('%file' => $result ? $js_file : t('not found'))));
   }
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 3ebe97d..68b6530 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -239,7 +239,7 @@ function locale_stream_wrappers() {
 function locale_language_insert($language) {
   // @todo move these two cache clears out. See http://drupal.org/node/1293252
   // Changing the language settings impacts the interface.
-  cache('page')->flush();
+  cache('page')->deleteAll();
   // Force JavaScript translation file re-creation for the new language.
   _locale_invalidate_js($language->langcode);
 }
@@ -250,7 +250,7 @@ function locale_language_insert($language) {
 function locale_language_update($language) {
   // @todo move these two cache clears out. See http://drupal.org/node/1293252
   // Changing the language settings impacts the interface.
-  cache('page')->flush();
+  cache('page')->deleteAll();
   // Force JavaScript translation file re-creation for the modified language.
   _locale_invalidate_js($language->langcode);
 }
@@ -269,7 +269,7 @@ function locale_language_delete($language) {
   _locale_invalidate_js($language->langcode);
 
   // Changing the language settings impacts the interface:
-  cache('page')->flush();
+  cache('page')->deleteAll();
 
   // Clearing all locale cache from database
   cache()->delete('locale:' . $language->langcode);
@@ -790,7 +790,7 @@ function _locale_refresh_translations($langcodes, $lids) {
     }
   }
   // Clear locale cache.
-  cache()->invalidateTags(array('locale' => TRUE));
+  cache()->deleteTags(array('locale' => TRUE));
 }
 
 /**
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 5add3df..9953958 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -413,7 +413,7 @@ class NodeFormController extends EntityFormController {
     }
 
     // Clear the page and block caches.
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
index edcb007..39bbc20 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
@@ -113,7 +113,7 @@ function testRecentNodeBlock() {
     $node4 = $this->drupalCreateNode($default_settings);
     // drupalCreateNode() does not automatically flush content caches unlike
     // posting a node from a node form.
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
 
     // Test that all four nodes are shown.
     $this->drupalGet('');
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index 2ca2d3e..2f91093 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -656,7 +656,7 @@ function node_admin_nodes_submit($form, &$form_state) {
     }
     call_user_func_array($function, $args);
 
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
   }
   else {
     // We need to rebuild the form to go to a second step. For example, to
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 55989de..79006a5 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -855,7 +855,7 @@ function _node_types_build($rebuild = FALSE) {
  * Clears the node type cache.
  */
 function node_type_cache_reset() {
-  cache()->invalidateTags(array('node_types' => TRUE));
+  cache()->deleteTags(array('node_types' => TRUE));
   drupal_static_reset('_node_types_build');
 }
 
@@ -3416,7 +3416,7 @@ function node_access_rebuild($batch_mode = FALSE) {
   if (!isset($batch)) {
     drupal_set_message(t('Content permissions have been rebuilt.'));
     node_access_needs_rebuild(FALSE);
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
   }
 }
 
@@ -3476,7 +3476,7 @@ function _node_access_rebuild_batch_finished($success, $results, $operations) {
   else {
     drupal_set_message(t('The content access permissions have not been properly rebuilt.'), 'error');
   }
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 }
 
 /**
diff --git a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
index 181bd72..4b41da5 100644
--- a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
+++ b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
@@ -50,12 +50,12 @@ function testPathCache() {
 
     // Visit the system path for the node and confirm a cache entry is
     // created.
-    cache('path')->flush();
+    cache('path')->deleteAll();
     $this->drupalGet($edit['source']);
     $this->assertTrue(cache('path')->get($edit['source']), 'Cache entry was created.');
 
     // Visit the alias for the node and confirm a cache entry is created.
-    cache('path')->flush();
+    cache('path')->deleteAll();
     $this->drupalGet($edit['alias']);
     // @todo The alias should actually have been cached with the system path as
     // the key, see the todo in drupal_cache_system_paths() in path.inc.
diff --git a/core/modules/poll/poll.module b/core/modules/poll/poll.module
index c85f121..eb89bdf 100644
--- a/core/modules/poll/poll.module
+++ b/core/modules/poll/poll.module
@@ -791,7 +791,7 @@ function poll_vote($form, &$form_state) {
     ->condition('chid', $choice)
     ->execute();
 
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 
   if (!$user->uid) {
     // The vote is recorded so the user gets the result view instead of the
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainImplementationUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainImplementationUnitTest.php
index 318373e..9c528ce 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainImplementationUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/BackendChainImplementationUnitTest.php
@@ -208,32 +208,32 @@ class BackendChainImplementationUnitTest extends UnitTestBase {
     $this->assertFalse($this->chain->isEmpty(), 'Chain is not empty');
 
     // This is the only test that needs to start with an empty chain.
-    $this->chain->flush();
-    $this->assert($this->chain->isEmpty(), 'Chain have been emptied by the flush() call');
+    $this->chain->deleteAll();
+    $this->assert($this->chain->isEmpty(), 'Chain have been emptied by the deleteAll() call');
 
     $this->secondBackend->set('test', 5);
     $this->assertFalse($this->chain->isEmpty(), 'Chain is not empty anymore now that the second backend has something');
   }
 
   /**
-   * Test that the flush operation is propagated to all backends in the chain.
+   * Test that the delete all operation is propagated to all backends in the chain.
    */
-  public function testFlushPropagation() {
+  public function testDeleteAllPropagation() {
     // Set both expiring and permanent keys.
     $this->chain->set('test1', 1, CacheBackendInterface::CACHE_PERMANENT);
     $this->chain->set('test2', 3, time() + 1000);
-    $this->chain->flush();
+    $this->chain->deleteAll();
 
-    $this->assertTrue($this->firstBackend->isEmpty(), 'First backend is empty after flush.');
-    $this->assertTrue($this->secondBackend->isEmpty(), 'Second backend is empty after flush.');
-    $this->assertTrue($this->thirdBackend->isEmpty(), 'Third backend is empty after flush.');
+    $this->assertTrue($this->firstBackend->isEmpty(), 'First backend is empty after delete all.');
+    $this->assertTrue($this->secondBackend->isEmpty(), 'Second backend is empty after delete all.');
+    $this->assertTrue($this->thirdBackend->isEmpty(), 'Third backend is empty after delete all.');
   }
 
   /**
-   * Test that the tags cache clear operation is propagated to all backends
+   * Test that the delete tags operation is propagated to all backends
    * in the chain.
    */
-  public function testClearTagsPropagation() {
+  public function testDeleteTagsPropagation() {
     // Create two cache entries with the same tag and tag value.
     $this->chain->set('test_cid_clear1', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
     $this->chain->set('test_cid_clear2', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
@@ -246,7 +246,7 @@ class BackendChainImplementationUnitTest extends UnitTestBase {
       'Two cache items were created in all backends.');
 
     // Invalidate test_tag of value 1. This should invalidate both entries.
-    $this->chain->invalidateTags(array('test_tag' => 2));
+    $this->chain->deleteTags(array('test_tag' => 2));
     $this->assertIdentical(FALSE, $this->firstBackend->get('test_cid_clear1')
       && $this->firstBackend->get('test_cid_clear2')
       && $this->secondBackend->get('test_cid_clear1')
@@ -267,7 +267,7 @@ class BackendChainImplementationUnitTest extends UnitTestBase {
       'Two cache items were created in all backends.');
 
     // Invalidate test_tag of value 1. This should invalidate both entries.
-    $this->chain->invalidateTags(array('test_tag' => array(1)));
+    $this->chain->deleteTags(array('test_tag' => array(1)));
     $this->assertIdentical(FALSE, $this->firstBackend->get('test_cid_clear1')
       && $this->firstBackend->get('test_cid_clear2')
       && $this->secondBackend->get('test_cid_clear1')
@@ -291,7 +291,7 @@ class BackendChainImplementationUnitTest extends UnitTestBase {
       && $this->thirdBackend->get('test_cid_clear3'),
       'Three cached items were created in all backends.');
 
-    $this->chain->invalidateTags(array('test_tag_foo' => array(3)));
+    $this->chain->deleteTags(array('test_tag_foo' => array(3)));
     $this->assertNotIdentical(FALSE, $this->firstBackend->get('test_cid_clear1')
       && $this->firstBackend->get('test_cid_clear2')
       && $this->secondBackend->get('test_cid_clear1')
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php
index 25ab106..dd1dea9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php
@@ -99,6 +99,6 @@ function assertCacheRemoved($message, $cid = NULL, $bin = NULL) {
       $bin = $this->default_bin;
     }
 
-    cache($bin)->expire();
+    cache($bin)->deleteExpired();
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php
index 95805d7..7d68ce7 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -102,7 +102,7 @@
     if (!isset($this->cachebackends[$bin])) {
       $this->cachebackends[$bin] = $this->createCacheBackend($bin);
       // Ensure the backend is empty.
-      $this->cachebackends[$bin]->flush();
+      $this->cachebackends[$bin]->deleteAll();
     }
     return $this->cachebackends[$bin];
   }
@@ -118,10 +118,10 @@
 
   public function tearDown() {
     // Destruct the registered backend, each test will get a fresh instance,
-    // properly flushing it here ensure that on persistant data backends they
+    // properly emptying it here ensure that on persistant data backends they
     // will come up empty the next test.
     foreach ($this->cachebackends as $bin => $cachebackend) {
-      $this->cachebackends[$bin]->flush();
+      $this->cachebackends[$bin]->deleteAll();
     }
     unset($this->cachebackends);
 
@@ -136,19 +136,31 @@
   public function testSetGet() {
     $backend = $this->getCacheBackend();
 
-    $data = 7;
     $this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1.");
-    $backend->set('test1', $data);
+    $backend->set('test1', 7);
     $cached = $backend->get('test1');
     $this->assert(is_object($cached), "Backend returned an object for cache id test1.");
-    $this->assertIdentical($data, $cached->data);
+    $this->assertIdentical(7, $cached->data);
+    $this->assertTrue($cached->valid, 'Item is marked as valid.');
+    $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.');
+    $this->assertEqual($cached->expire, CacheBackendInterface::CACHE_PERMANENT, 'Expire time is correct.');
 
-    $data = array('value' => 3);
     $this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2.");
-    $backend->set('test2', $data);
+    $backend->set('test2', array('value' => 3), REQUEST_TIME + 3);
     $cached = $backend->get('test2');
     $this->assert(is_object($cached), "Backend returned an object for cache id test2.");
-    $this->assertIdentical($data, $cached->data);
+    $this->assertIdentical(array('value' => 3), $cached->data);
+    $this->assertTrue($cached->valid, 'Item is marked as valid.');
+    $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.');
+    $this->assertEqual($cached->expire, REQUEST_TIME + 3, 'Expire time is correct.');
+
+    $backend->set('test3', 'foobar', REQUEST_TIME - 3);
+    $this->assertFalse($backend->get('test3'), 'Invalid item not returned.');
+    $cached = $backend->get('test3', TRUE);
+    $this->assert(is_object($cached), 'Backend returned an object for cache id test3.');
+    $this->assertFalse($cached->valid, 'Item is marked as valid.');
+    $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.');
+    $this->assertEqual($cached->expire, REQUEST_TIME - 3, 'Expire time is correct.');
   }
 
   /**
@@ -186,7 +198,7 @@
       'test2' => '0',
       'test3' => '',
       'test4' => 12.64,
-      'test5' => false,
+      'test5' => FALSE,
       'test6' => array(1,2,3),
     );
 
@@ -224,7 +236,7 @@
       'test7',
       'test21', // Cid does not exist.
       'test6',
-      'test19', // Cid does not exist until added before second getMulitple().
+      'test19', // Cid does not exist until added before second getMultiple().
       'test2',
     );
 
@@ -235,6 +247,10 @@
     $this->assert(isset($ret['test3']), "Existing cache id test3 is set.");
     $this->assert(isset($ret['test6']), "Existing cache id test6 is set.");
     $this->assert(isset($ret['test7']), "Existing cache id test7 is set.");
+    // Test return - ensure that objects has expected properties.
+    $this->assertTrue($ret['test2']->valid, 'Item is marked as valid.');
+    $this->assertEqual($ret['test2']->created, REQUEST_TIME, 'Created time is correct.');
+    $this->assertEqual($ret['test2']->expire, CacheBackendInterface::CACHE_PERMANENT, 'Expire time is correct.');
     // Test return - ensure it does not contain nonexistent cache ids.
     $this->assertFalse(isset($ret['test19']), "Nonexistent cache id test19 is not set.");
     $this->assertFalse(isset($ret['test21']), "Nonexistent cache id test21 is not set.");
@@ -298,7 +314,8 @@
   }
 
   /**
-   * Tests Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
+   * Test Drupal\Core\Cache\CacheBackendInterface::delete() and
+   * Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
    */
   public function testDeleteMultiple() {
     $backend = $this->getCacheBackend();
@@ -312,8 +329,9 @@
     $backend->set('test6', 13);
     $backend->set('test7', 17);
 
+    $backend->delete('test1');
+    $backend->delete('test23'); // Nonexistent key should not cause an error.
     $backend->deleteMultiple(array(
-      'test1',
       'test3',
       'test5',
       'test7',
@@ -338,92 +356,155 @@
   }
 
   /**
-   * Tests Drupal\Core\Cache\CacheBackendInterface::flush().
+   * Tests Drupal\Core\Cache\CacheBackendInterface::deleteTags().
    */
-  public function testFlush() {
+  function testDeleteTags() {
+    $backend = $this->getCacheBackend();
+
+    // Create two cache entries with the same tag and tag value.
+    $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
+    $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
+    $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));
+    $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.');
+
+    // Create two cache entries with the same tag and an array tag value.
+    $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
+    $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
+    $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' => array(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.');
+
+    // Create three cache entries with a mix of tags and tag values.
+    $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
+    $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2)));
+    $backend->set('test_cid_invalidate3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(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' => array(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.');
+
+    // Create cache entry in multiple bins. Two cache entries
+    // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous
+    // tests.
+    $tags = array('test_tag' => array(1, 2, 3));
+    $bins = array('path', 'bootstrap', 'page');
+    foreach ($bins as $bin) {
+      $this->getCacheBackend($bin)->set('test', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, $tags);
+      $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' => array(2)));
+    }
+
+    // Test that cache entry has been deleted in multple bins.
+    foreach ($bins as $bin) {
+      $this->assertFalse($this->getCacheBackend($bin)->get('test', TRUE), 'Tag deletion affected item in bin.');
+    }
+    // Test that the cache entry with a matching tag has been invalidated.
+    $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2', TRUE), 'Cache items matching tag were deleted.');
+    // Test that the cache entry with without a matching tag still exists.
+    $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.');
+  }
+
+  /**
+   * Test Drupal\Core\Cache\CacheBackendInterface::deleteAll().
+   */
+  public function testDeleteAll() {
     $backend = $this->getCacheBackend();
 
     // Set both expiring and permanent keys.
     $backend->set('test1', 1, CacheBackendInterface::CACHE_PERMANENT);
     $backend->set('test2', 3, time() + 1000);
 
-    $backend->flush();
+    $backend->deleteAll();
 
-    $this->assertTrue($backend->isEmpty(), "Backend is empty after flush.");
+    $this->assertTrue($backend->isEmpty(), "Backend is empty after deleteAll().");
 
-    $this->assertIdentical(FALSE, $backend->get('test1'), "First key has been flushed.");
-    $this->assertIdentical(FALSE, $backend->get('test2'), "Second key has been flushed.");
+    $this->assertIdentical(FALSE, $backend->get('test1'), "First key has been deleted.");
+    $this->assertIdentical(FALSE, $backend->get('test2'), "Second key has been deleted.");
   }
 
   /**
-   * Checks whether or not a cache entry exists.
-   *
-   * @param $cid
-   *   The cache id.
-   * @param $bin
-   *   The cache bin to use. If not provided the default test bin wil be used.
-   *
-   * @return
-   *   TRUE on pass, FALSE on fail.
+   * Test Drupal\Core\Cache\CacheBackendInterface::invalidate() and
+   * Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple().
    */
-  protected function checkCacheExists($cid, $bin = null) {
-    $cached = $this->getCacheBackend($bin)->get($cid);
-    return isset($cached->data);
+  function testInvalidate() {
+    $backend = $this->getCacheBackend();
+    $backend->set('test1', 1);
+    $backend->set('test2', 2);
+    $backend->set('test3', 2);
+    $backend->set('test4', 2);
+
+    $reference = array('test1', 'test2', 'test3', 'test4');
+
+    $cids = $reference;
+    $ret = $backend->getMultiple($cids);
+    $this->assertEqual(count($ret), 4, 'Four items returned.');
+
+    $backend->invalidate('test1');
+    $backend->invalidateMultiple(array('test2', 'test3'));
+
+    $cids = $reference;
+    $ret = $backend->getMultiple($cids);
+    $this->assertEqual(count($ret), 1, 'Only one item element returned.');
+
+    $cids = $reference;
+    $ret = $backend->getMultiple($cids, TRUE);
+    $this->assertEqual(count($ret), 4, 'Four items returned.');
   }
 
   /**
    * Tests Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
    */
-  function testClearTags() {
+  function testInvalidateTags() {
     $backend = $this->getCacheBackend();
 
     // Create two cache entries with the same tag and tag value.
-    $backend->set('test_cid_clear1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
-    $backend->set('test_cid_clear2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
-    $this->assertTrue($this->checkCacheExists('test_cid_clear1')
-                      && $this->checkCacheExists('test_cid_clear2'),
-                      'Two cache items were created.');
+    $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
+    $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2));
+    $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));
-    $this->assertFalse($this->checkCacheExists('test_cid_clear1')
-                      || $this->checkCacheExists('test_cid_clear2'),
-                      'Two caches removed after clearing a cache tag.');
+    $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.');
 
     // Create two cache entries with the same tag and an array tag value.
-    $backend->set('test_cid_clear1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
-    $backend->set('test_cid_clear2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
-    $this->assertTrue($this->checkCacheExists('test_cid_clear1')
-                      && $this->checkCacheExists('test_cid_clear2'),
-                      'Two cache items were created.');
+    $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
+    $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
+    $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' => array(1)));
-    $this->assertFalse($this->checkCacheExists('test_cid_clear1')
-                      || $this->checkCacheExists('test_cid_clear2'),
-                      'Two caches removed after clearing a cache tag.');
+    $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.');
 
     // Create three cache entries with a mix of tags and tag values.
-    $backend->set('test_cid_clear1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
-    $backend->set('test_cid_clear2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2)));
-    $backend->set('test_cid_clear3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(3)));
-    $this->assertTrue($this->checkCacheExists('test_cid_clear1')
-                      && $this->checkCacheExists('test_cid_clear2')
-                      && $this->checkCacheExists('test_cid_clear3'),
-                      'Two cached items were created.');
+    $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1)));
+    $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2)));
+    $backend->set('test_cid_invalidate3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(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' => array(3)));
-    $this->assertTrue($this->checkCacheExists('test_cid_clear1')
-                      && $this->checkCacheExists('test_cid_clear2'),
-                      'Cached items not matching the tag were not cleared.');
-
-    $this->assertFalse($this->checkCacheExists('test_cid_clear3'),
-                      'Cached item matching the tag was removed.');
+    $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.');
 
-    // Create cache entry in multiple bins. Two cache entries (test_cid_clear1
-    // and test_cid_clear2) still exist from previous tests.
+    // Create cache entry in multiple bins. Two cache entries
+    // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous
+    // tests.
     $tags = array('test_tag' => array(1, 2, 3));
     $bins = array('path', 'bootstrap', 'page');
     foreach ($bins as $bin) {
       $this->getCacheBackend($bin)->set('test', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, $tags);
-      $this->assertTrue($this->checkCacheExists('test', $bin), 'Cache item was set in bin.');
+      $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
     }
 
     // Invalidate tag in mulitple bins.
@@ -433,11 +514,11 @@ function testClearTags() {
 
     // Test that cache entry has been invalidated in multple bins.
     foreach ($bins as $bin) {
-      $this->assertFalse($this->checkCacheExists('test', $bin), 'Tag expire affected item in bin.');
+      $this->assertFalse($this->getCacheBackend($bin)->get('test'), 'Tag invalidation affected item in bin.');
     }
     // Test that the cache entry with a matching tag has been invalidated.
-    $this->assertFalse($this->checkCacheExists('test_cid_clear2', $bin), 'Cached items matching tag were cleared.');
+    $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2'), 'Cache items matching tag were invalidated.');
     // Test that the cache entry with without a matching tag still exists.
-    $this->assertTrue($this->checkCacheExists('test_cid_clear1', $bin), 'Cached items not matching tag were not cleared.');
+    $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
index 58078cd..65cb303 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
@@ -85,7 +85,7 @@ function testCacheInstall() {
     $database_cache->set('cache_two', 'Two');
     $this->assertEqual($database_cache->get('cache_one')->data, 'One');
     $this->assertEqual($database_cache->get('cache_two')->data, 'Two');
-    $install_cache->flush();
+    $install_cache->deleteAll();
     $this->assertFalse($database_cache->get('cache_one'));
     $this->assertFalse($database_cache->get('cache_two'));
 
@@ -106,8 +106,8 @@ function testCacheInstall() {
       $install_cache->isEmpty();
       $install_cache->delete('cache_one');
       $install_cache->deleteMultiple(array('cache_one', 'cache_two'));
-      $install_cache->flush();
-      $install_cache->expire();
+      $install_cache->deleteAll();
+      $install_cache->deleteExpired();
       $install_cache->garbageCollection();
       $install_cache->invalidateTags(array('tag'));
       $this->pass("The installer's cache backend can be used even when the cache database tables are unavailable.");
diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
index 41070c3..42515cf 100644
--- a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
@@ -91,7 +91,7 @@ function testCompileDIC() {
       'user' => 'user',
       'bundle_test' => 'bundle_test',
     );
-    $cache->flush();
+    $cache->deleteAll();
     $kernel = new DrupalKernel('testing', FALSE, $module_enabled, $cache);
     $kernel->boot();
     // Instantiate it a second time and we should still get a ContainerBuilder
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index c55289c..db7f3a9 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -735,7 +735,7 @@ function system_theme_settings_submit($form, &$form_state) {
   variable_set($key, $values);
   drupal_set_message(t('The configuration options have been saved.'));
 
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 }
 
 /**
@@ -1706,7 +1706,7 @@ function system_clear_cache_submit($form, &$form_state) {
  * @ingroup forms
  */
 function system_clear_page_cache_submit($form, &$form_state) {
-  cache('page')->flush();
+  cache('page')->deleteAll();
 }
 
 /**
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 8127e00..36edc72 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -598,6 +598,12 @@ function system_schema() {
         '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'),
   );
@@ -643,12 +649,18 @@ function system_schema() {
         'size' => 'big',
         'not null' => FALSE,
       ),
-      'checksum' => array(
+      'checksum_invalidations' => array(
         'description' => 'The tag invalidation sum when this entry was saved.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
+      'checksum_deletions' => array(
+        'description' => 'The tag deletion sum when this entry was saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
     ),
     'indexes' => array(
       'expire' => array('expire'),
@@ -1507,12 +1519,18 @@ function system_schema_cache_8007() {
         'size' => 'big',
         'not null' => FALSE,
       ),
-      'checksum' => array(
+      'checksum_invalidations' => array(
         'description' => 'The tag invalidation sum when this entry was saved.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
+      'checksum_deletions' => array(
+        'description' => 'The tag deletion sum when this entry was saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
     ),
     'indexes' => array(
       'expire' => array('expire'),
@@ -1633,12 +1651,18 @@ function system_update_8003() {
         'size' => 'big',
         'not null' => FALSE,
       ),
-      'checksum' => array(
+      'checksum_invalidations' => array(
         'description' => 'The tag invalidation sum when this entry was saved.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
+      'checksum_deletions' => array(
+        'description' => 'The tag deletion sum when this entry was saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
     ),
     'indexes' => array(
       'expire' => array('expire'),
@@ -1709,6 +1733,12 @@ function system_update_8006() {
         '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'),
   );
@@ -1732,12 +1762,18 @@ function system_update_8007() {
         'size' => 'big',
         'not null' => FALSE,
       ));
-      db_add_field($table, 'checksum', array(
+      db_add_field($table, 'checksum_invalidations', array(
         'description' => 'The tag invalidation sum when this entry was saved.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ));
+      db_add_field($table, 'checksum_deletions', array(
+        'description' => 'The tag deletion sum when this entry was saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ));
     }
   }
 }
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index ea3dadc..972354d 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3472,7 +3472,7 @@ function system_cron() {
 
   $cache_bins = array_merge(module_invoke_all('cache_flush'), array('form', 'menu'));
   foreach ($cache_bins as $bin) {
-    cache($bin)->expire();
+    cache($bin)->deleteExpired();
   }
 
   // Cleanup the batch table and the queue for failed batches.
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
index f81b9e5..2de222c 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
@@ -168,7 +168,7 @@ class TermFormController extends EntityFormController {
         drupal_set_message(t('Updated term %term.', array('%term' => $term->label())));
         watchdog('taxonomy', 'Updated term %term.', array('%term' => $term->label()), WATCHDOG_NOTICE, l(t('edit'), 'taxonomy/term/' . $term->tid . '/edit'));
         // Clear the page and block caches to avoid stale data.
-        cache_invalidate(array('content' => TRUE));
+        cache_invalidate_tags(array('content' => TRUE));
         break;
     }
 
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php
index dd5b478..9f246e8 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php
@@ -84,6 +84,6 @@ class VocabularyStorageController extends DatabaseStorageController {
   public function resetCache(array $ids = NULL) {
     drupal_static_reset('taxonomy_vocabulary_get_names');
     parent::resetCache($ids);
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
   }
 }
diff --git a/core/modules/taxonomy/taxonomy.admin.inc b/core/modules/taxonomy/taxonomy.admin.inc
index 24c2039..480a9ac 100644
--- a/core/modules/taxonomy/taxonomy.admin.inc
+++ b/core/modules/taxonomy/taxonomy.admin.inc
@@ -576,7 +576,7 @@ function taxonomy_term_confirm_delete_submit($form, &$form_state) {
   if (!isset($_GET['destination'])) {
     $form_state['redirect'] = 'admin/structure/taxonomy';
   }
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
   return;
 }
 
@@ -616,7 +616,7 @@ function taxonomy_vocabulary_confirm_delete_submit($form, &$form_state) {
   drupal_set_message(t('Deleted vocabulary %name.', array('%name' => $form_state['values']['name'])));
   watchdog('taxonomy', 'Deleted vocabulary %name.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE);
   $form_state['redirect'] = 'admin/structure/taxonomy';
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
   return;
 }
 
diff --git a/core/modules/user/lib/Drupal/user/ProfileFormController.php b/core/modules/user/lib/Drupal/user/ProfileFormController.php
index d2a7e81..c80be72 100644
--- a/core/modules/user/lib/Drupal/user/ProfileFormController.php
+++ b/core/modules/user/lib/Drupal/user/ProfileFormController.php
@@ -55,7 +55,7 @@ class ProfileFormController extends AccountFormController {
 
     // Clear the page cache because pages can contain usernames and/or profile
     // information:
-    cache_invalidate(array('content' => TRUE));
+    cache_invalidate_tags(array('content' => TRUE));
 
     drupal_set_message(t('The changes have been saved.'));
   }
diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc
index 396f4c0..ce39892 100644
--- a/core/modules/user/user.admin.inc
+++ b/core/modules/user/user.admin.inc
@@ -785,7 +785,7 @@ function user_admin_permissions_submit($form, &$form_state) {
   drupal_set_message(t('The changes have been saved.'));
 
   // Clear the cached pages and blocks.
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 }
 
 /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 570a199..6539346 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1991,7 +1991,7 @@ function _user_cancel($edit, $account, $method) {
   }
 
   // Clear the cache for anonymous users.
-  cache_invalidate(array('content' => TRUE));
+  cache_invalidate_tags(array('content' => TRUE));
 }
 
 /**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php
index 400fd0c..6938185 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/cache/CachePluginBase.php
@@ -196,7 +196,7 @@ function cache_get($type) {
    * to be sure that we catch everything. Maybe that's a bad idea.
    */
   function cache_flush() {
-    cache($this->table)->invalidateTags(array($this->view->storage->name => TRUE));
+    cache($this->table)->deleteTags(array($this->view->storage->name => TRUE));
   }
 
   /**
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 0eb1295..55af4a0 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -941,9 +941,9 @@ function views_language_list($field = 'name', $all = FALSE) {
 }
 
 /**
- * Implements hook_cache_flush().
+ * Implements hook_cache_deleteAll().
  */
-function views_cache_flush() {
+function views_cache_deleteAll() {
   return array('views_info', 'views_results');
 }
 
@@ -951,24 +951,24 @@ function views_cache_flush() {
  * Implements hook_field_create_instance.
  */
 function views_field_create_instance($instance) {
-  cache('views_info')->flush();
-  cache('views_results')->flush();
+  cache('views_info')->deleteAll();
+  cache('views_results')->deleteAll();
 }
 
 /**
  * Implements hook_field_update_instance.
  */
 function views_field_update_instance($instance, $prior_instance) {
-  cache('views_info')->flush();
-  cache('views_results')->flush();
+  cache('views_info')->deleteAll();
+  cache('views_results')->deleteAll();
 }
 
 /**
  * Implements hook_field_delete_instance.
  */
 function views_field_delete_instance($instance) {
-  cache('views_info')->flush();
-  cache('views_results')->flush();
+  cache('views_info')->deleteAll();
+  cache('views_results')->deleteAll();
 }
 
 /**
@@ -976,10 +976,10 @@ function views_field_delete_instance($instance) {
  */
 function views_invalidate_cache() {
   // Clear the views cache.
-  cache('views_info')->flush();
+  cache('views_info')->deleteAll();
 
   // Clear the page and block cache.
-  cache_invalidate(array('content' => TRUE));
+  cache_delete_tags(array('content' => TRUE));
 
   // Set the menu as needed to be rebuilt.
   state()->set('menu_rebuild_needed', TRUE);
diff --git a/core/update.php b/core/update.php
index 2273b40..0b6adbb 100644
--- a/core/update.php
+++ b/core/update.php
@@ -268,7 +268,7 @@ function update_info_page() {
   _drupal_flush_css_js();
   // Flush the cache of all data for the update status module.
   if (db_table_exists('cache_update')) {
-    cache('update')->flush();
+    cache('update')->deleteAll();
   }
 
   update_task_list('info');
