diff --git a/core/lib/Drupal/Core/Cache/ApcuBackend.php b/core/lib/Drupal/Core/Cache/ApcuBackend.php
index 9bac79e..0ceafc8 100644
--- a/core/lib/Drupal/Core/Cache/ApcuBackend.php
+++ b/core/lib/Drupal/Core/Cache/ApcuBackend.php
@@ -178,14 +178,10 @@ public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANEN
     $cache->serialized = 0;
     $cache->data = $data;
 
-    // apc_store()'s $ttl argument can be omitted but also set to 0 (zero),
-    // in which case the value will persist until it's removed from the cache or
-    // until the next cache clear, restart, etc. This is what we want to do
-    // when $expire equals CacheBackendInterface::CACHE_PERMANENT.
-    if ($expire === CacheBackendInterface::CACHE_PERMANENT) {
-      $expire = 0;
-    }
-    apc_store($this->getApcuKey($cid), $cache, $expire);
+    // Don't set a time-to-live (ttl) on the APC cache since this can be
+    // configured by the user in their php.ini. The default ttl is 0 which means
+    // that items are only removed when the cache is cleared.
+    apc_store($this->getApcuKey($cid), $cache);
   }
 
   /**
@@ -215,21 +211,25 @@ public function deleteMultiple(array $cids) {
    * {@inheritdoc}
    */
   public function deleteAll() {
-    apc_delete(new \APCIterator('user', '/^' . preg_quote($this->binPrefix, '/') . '/'));
+    $this->removeBin();
   }
 
   /**
    * {@inheritdoc}
    */
   public function garbageCollection() {
-    // APC performs garbage collection automatically.
+    foreach ($this->getAll() as $data) {
+      if ($data['value']->expire !== Cache::PERMANENT && $data['value']->expire < REQUEST_TIME) {
+        apc_delete($data['key']);
+      }
+    }
   }
 
   /**
    * {@inheritdoc}
    */
   public function removeBin() {
-    apc_delete(new \APCIterator('user', '/^' . preg_quote($this->binPrefix, '/') . '/'));
+    apc_delete($this->getAll());
   }
 
   /**
@@ -243,8 +243,12 @@ public function invalidate($cid) {
    * {@inheritdoc}
    */
   public function invalidateMultiple(array $cids) {
-    foreach ($this->getMultiple($cids) as $cache) {
-      $this->set($cache->cid, $cache, REQUEST_TIME - 1);
+    $result = apc_fetch(array_map(array($this, 'getApcuKey'), $cids));
+    if ($result) {
+      foreach ($result as $key => $cache) {
+        $cache->expire = REQUEST_TIME - 1;
+        apc_store($key, $cache);
+      }
     }
   }
 
@@ -253,8 +257,8 @@ public function invalidateMultiple(array $cids) {
    */
   public function invalidateAll() {
     foreach ($this->getAll() as $data) {
-      $cid = str_replace($this->binPrefix, '', $data['key']);
-      $this->set($cid, $data['value'], REQUEST_TIME - 1);
+      $data['value']->expire = REQUEST_TIME - 1;
+      apc_store($data['key'], $data['value']);
     }
   }
 
diff --git a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
index cc0d9df..bc79621 100644
--- a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -519,6 +519,11 @@ function testInvalidate() {
     $ret = $backend->getMultiple($cids, TRUE);
     $this->assertEqual(count($ret), 4, 'Four items returned.');
 
+    // Test that calling invalidate() does not change data.
+    $this->assertIdentical($ret['test1']->data, 1);
+    // Test that calling invalidateMultiple() does not change data.
+    $this->assertIdentical($ret['test2']->data, 2);
+
     // Calling invalidateMultiple() with an empty array should not cause an
     // error.
     $this->assertFalse($backend->invalidateMultiple(array()));
@@ -600,6 +605,8 @@ public function testInvalidateAll() {
     $this->assertTrue($backend_b->get('test3'), 'Item in other bin is preserved.');
     $this->assertTrue($backend_a->get('test1', TRUE), 'First key has not been deleted.');
     $this->assertTrue($backend_a->get('test2', TRUE), 'Second key has not been deleted.');
+    // Test that calling invalidateAll() does not change data.
+    $this->assertIdentical($backend_a->get('test1', TRUE)->data, 1);
   }
 
   /**
