diff --git a/dmemcache.inc b/dmemcache.inc
index 31759bf..700df80 100644
--- a/dmemcache.inc
+++ b/dmemcache.inc
@@ -34,10 +34,10 @@ function dmemcache_set($key, $value, $exp = 0, $bin = 'cache') {
   $full_key = dmemcache_key($key, $bin);
   $success = FALSE;
   if ($mc = dmemcache_object($bin)) {
-    if (class_exists('Memcached')) {
+    if ($mc instanceof Memcached) {
       $success = $mc->set($full_key, $value, $exp);
     }
-    else {
+    elseif ($mc instanceof Memcache) {
       $success = $mc->set($full_key, $value, MEMCACHE_COMPRESSED, $exp);
     }
   }
@@ -75,10 +75,10 @@ function dmemcache_add($key, $value, $exp = 0, $bin = 'cache', $mc = NULL, $flag
   $full_key = dmemcache_key($key, $bin);
   $success = FALSE;
   if ($mc || ($mc = dmemcache_object($bin))) {
-    if (class_exists('Memcached')) {
+    if ($mc instanceof Memcached) {
       $success = $mc->add($full_key, $value, $exp);
     }
-    else {
+    elseif ($mc instanceof Memcache) {
       $success = $mc->add($full_key, $value, $flag, $exp);
     }
   }
@@ -144,10 +144,10 @@ function dmemcache_get_multi($keys, $bin = 'cache', $mc = NULL) {
   }
   $results = array();
   if ($mc || ($mc = dmemcache_object($bin))) {
-    if (class_exists('Memcached')) {
+    if ($mc instanceof Memcached) {
       $results = $mc->getMulti($full_keys);
     }
-    else {
+    elseif ($mc instanceof Memcache) {
       $results = $mc->get($full_keys);
     }
   }
@@ -210,18 +210,18 @@ function dmemcache_stats($bin = 'cache', $type = '') {
     // If $type is 'default', then no parameter should be passed to the 
     // Memcache memcache_get_extended_stats() function.
     if ($type == 'default' || $type == '') {
-      if (class_exists('Memcached')) {
+      if ($mc instanceof Memcached) {
         return $mc->getStats();
       }
-      else if (class_exists('Memcache')) {
+      elseif ($mc instanceof Memcache) {
         return $mc->getExtendedStats();
       }
     }
     else {
-      if (class_exists('Memcached')) {
+      if ($mc instanceof Memcached) {
         return $mc->getStats();        
       }
-      else if (class_exists('Memcache')) {
+      elseif ($mc instanceof Memcache) {
         return $mc->getExtendedStats($type);
       }
     }
@@ -242,7 +242,25 @@ function dmemcache_stats($bin = 'cache', $type = '') {
  * @return an Memcache object or FALSE.
  */
 function dmemcache_object($bin = NULL, $flush = FALSE) {
-  static $memcacheCache = array(), $memcache_servers, $memcache_bins;
+  static $extension, $memcacheCache = array(), $memcache_servers, $memcache_bins;
+
+  if (!isset($extension)) {
+    // If an extension is specified in settings.php, use that when available.
+    $preferred = variable_get('memcache_extension', NULL);
+    if (isset($preferred) && class_exists($preferred)) {
+      $extension = $preferred;
+    }
+    // If no extension is set, default to Memcache.
+    // The Memcached extension has some features that the older extension lacks
+    // but also an unfixed bug that affects cache clears.
+    // @see http://pecl.php.net/bugs/bug.php?id=16829
+    elseif (class_exists('Memcache')) {
+      $extension = 'Memcache';
+    }
+    elseif (class_exists('Memcached')) {
+      $extension = 'Memcached';
+    }
+  }
 
   if ($flush) {
     foreach ($memcacheCache as $cluster) {
@@ -273,7 +291,7 @@ function dmemcache_object($bin = NULL, $flush = FALSE) {
     }
     else {
       // Create a new Memcache object. Each cluster gets its own Memcache object.
-      if (class_exists('Memcached')) {
+      if ($extension == 'Memcached') {
         $memcache = new Memcached;
         $default_opts = array(
           Memcached::OPT_COMPRESSION => FALSE,
@@ -287,7 +305,7 @@ function dmemcache_object($bin = NULL, $flush = FALSE) {
           $memcache->setOption($key, $value);
         }
       }
-      else if (class_exists('Memcache')) {
+      elseif ($extension == 'Memcache') {
         $memcache = new Memcache;
       }
       else {
@@ -303,14 +321,14 @@ function dmemcache_object($bin = NULL, $flush = FALSE) {
           list($host, $port) = explode(':', $s);
 
           // This is a server that belongs to this cluster.
-          if (!class_exists('Memcached') && !$init) {
+          if ($memcache instanceof Memcache && !$init) {
             // If using PECL memcache extension, use ->connect for first server
             if ($memcache->connect($host, $port)) {
               $init = TRUE;
             }
           }
           else {
-            if ($memcache->addServer($host, $port) && !$init) {
+            if ($memcache instanceof Memcached && $memcache->addServer($host, $port) && !$init) {
               $init = TRUE;
             }
           }
diff --git a/memcache.inc b/memcache.inc
index 0ab5226..a9313d9 100644
--- a/memcache.inc
+++ b/memcache.inc
@@ -23,7 +23,7 @@ define('MEMCACHE_WILDCARD_INVALIDATE', 86400 * 28);
  *   'cache_menu', 'cache_page', or 'cache' for the default cache.
  */
 function cache_get($cid, $table = 'cache') {
-  // Handle excluded bins first.
+  // Handle excluded bins first_char.
   $bins = variable_get('memcache_bins', array());
   if (!is_null($table) && isset($bins[$table]) && $bins[$table] == 'database') {
     return _cache_get($cid, $table);
@@ -111,7 +111,7 @@ function cache_get($cid, $table = 'cache') {
  *   A string containing HTTP header information for cached pages.
  */
 function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
-  // Handle database fallback first.
+  // Handle database fallback first_char.
   $bins = variable_get('memcache_bins', array());
   if (!is_null($table) && isset($bins[$table]) && $bins[$table] == 'database') {
     return _cache_set($cid, $data, $table, $expire, $headers);
@@ -173,7 +173,7 @@ function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $he
  *   match. If '*' is given as $cid, the table $table will be emptied.
  */
 function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
-  // Handle database fallback first.
+  // Handle database fallback first_char.
   $bins = variable_get('memcache_bins', array());
   if (!is_null($table) && isset($bins[$table]) && $bins[$table] == 'database') {
     return _cache_clear_all($cid, $table, $wildcard);
@@ -246,11 +246,11 @@ function memcache_wildcards($cid, $table, $flush = FALSE) {
   static $wildcards = array();
   $matching = array();
   $length = strlen($cid);
+  $first_char = $cid[0];
 
   $wildcard_flushes = variable_get('memcache_wildcard_flushes', array());
   $wildcard_invalidate = variable_get('memcache_wildcard_invalidate', MEMCACHE_WILDCARD_INVALIDATE);
-  if (isset($wildcard_flushes[$table]) &&
-      is_array($wildcard_flushes[$table])) {
+  if (isset($wildcard_flushes[$table][$first_char]) && is_array($wildcard_flushes[$table][$first_char])) {
     // Determine which lookups we need to perform to determine whether or not
     // our cid was impacted by a wildcard flush.
     $lookup = array();
@@ -258,12 +258,12 @@ function memcache_wildcards($cid, $table, $flush = FALSE) {
     // Find statically cached wildcards, and determine possibly matching
     // wildcards for this cid based on a history of the lengths of past valid
     // wildcard flushes in this bin.
-    foreach ($wildcard_flushes[$table] as $flush_length => $timestamp) {
+    foreach ($wildcard_flushes[$table][$first_char] as $flush_length => $timestamp) {
       if ($length >= $flush_length && $timestamp >= ($_SERVER['REQUEST_TIME'] - $wildcard_invalidate)) {
         $key = '.wildcard-' . substr($cid, 0, $flush_length);
         $wildcard = dmemcache_key($key, $table);
-        if (isset($wildcards[$table][$wildcard])) {
-          $matching[$wildcard] = $wildcards[$table][$wildcard];
+        if (isset($wildcards[$table][$first_char][$wildcard])) {
+          $matching[$wildcard] = $wildcards[$table][$first_char][$wildcard];
         }
         else {
           $lookup[$wildcard] = $key;
@@ -277,11 +277,11 @@ function memcache_wildcards($cid, $table, $flush = FALSE) {
       if (is_array($values)) {
         // Build an array of matching wildcards.
         $matching = array_merge($matching, $values);
-        if (isset($wildcards[$table])) {
-          $wildcards[$table] = array_merge($wildcards[$table], $values);
+        if (isset($wildcards[$table][$first_char])) {
+          $wildcards[$table][$first_char] = array_merge($wildcards[$table], $values);
         }
         else {
-          $wildcards[$table] = $values;
+          $wildcards[$table][$first_char] = $values;
         }
         $lookup = array_diff_key($lookup, $values);
       }
@@ -289,7 +289,7 @@ function memcache_wildcards($cid, $table, $flush = FALSE) {
       // Also store failed lookups in our static cache, so we don't have to
       // do repeat lookups on single page loads.
       foreach ($lookup as $wildcard => $key) {
-        $wildcards[$table][$wildcard] = 0;
+        $wildcards[$table][$first_char][$wildcard] = 0;
       }
     }
   }
@@ -298,21 +298,21 @@ function memcache_wildcards($cid, $table, $flush = FALSE) {
    // fraction of the wildcard invalidation variable, per cid length.  Defaults
    // to 28 / 4, or one week.
     $length = strlen($cid);
-    if (!isset($wildcard_flushes[$table][$length]) ||
-        ($_SERVER['REQUEST_TIME'] - $wildcard_flushes[$table][$length] > $wildcard_invalidate / 4)) {
-      $wildcard_flushes[$table][$length] = $_SERVER['REQUEST_TIME'];
+    if (!isset($wildcard_flushes[$table][$first_char][$length]) ||
+        ($_SERVER['REQUEST_TIME'] - $wildcard_flushes[$table][$first_char][$length] > $wildcard_invalidate / 4)) {
+      $wildcard_flushes[$table][$first_char][$length] = $_SERVER['REQUEST_TIME'];
       memcache_variable_set('memcache_wildcard_flushes', $wildcard_flushes);
     }
     $wildcard = dmemcache_key('.wildcard-' . $cid, $table);
-    if (isset($wildcards[$table][$wildcard]) && $wildcards[$table][$wildcard] != 0) {
+    if (isset($wildcards[$table][$first_char][$wildcard]) && $wildcards[$table][$first_char][$wildcard] != 0) {
       $mc = dmemcache_object($table);
       if ($mc) {
         $mc->increment($wildcard);
       }
-      $wildcards[$table][$wildcard]++;
+      $wildcards[$table][$first_char][$wildcard]++;
     }
     else {
-      $wildcards[$table][$wildcard] = 1;
+      $wildcards[$table][$first_char][$wildcard] = 1;
       dmemcache_set('.wildcard-' . $cid, '1', 0, $table);
     }
   }
