diff --git a/redis.queue.inc b/redis.queue.inc
index bd6d962..d161076 100755
--- a/redis.queue.inc
+++ b/redis.queue.inc
@@ -3,13 +3,15 @@
 class RedisQueue implements DrupalQueueInterface {
   // The name of the queue that holds available items.
   protected $avail;
-  // The name of the queue that holds claimed items.
-  protected $claimed;
+  // The pattern for the queues that hold claimed items.
+  protected $claimed_pattern;
   // The PhpRedis object which connects to the redis server.
   protected $queue;
 
   protected $reserve_timeout;
 
+  protected $name;
+
   /**
    * Start working with a queue.
    *
@@ -17,8 +19,9 @@ class RedisQueue implements DrupalQueueInterface {
    *   Arbitrary string. The name of the queue to work with.
    */
   public function __construct($name) {
+    $this->name = $name;
     $this->avail= 'drupal:queue:' . $name . ':avail';
-    $this->claimed = 'drupal:queue:' . $name . ':claimed';
+    $this->claimed_pattern = 'drupal:queue:' . $name . ':avail_claimed:';
     $this->queue = new Redis();
     $options = self::getOptions($name);
     $this->reserve_timeout = $options['reserve_timeout'];
@@ -52,9 +55,12 @@ class RedisQueue implements DrupalQueueInterface {
     $record = new stdClass();
     $record->data = $data;
     $record->qid = $this->incrementId();
+    // We cannot rely on REQUEST_TIME because many items might be created
+    // by a single request which takes longer than 1 second.
     $record->timestamp = time();
-    $record = serialize($record);
-    return $this->queue->lpush($this->avail, $record) ? TRUE : FALSE;
+    $record = json_encode($record);
+    $result = $this->queue->hsetnx($this->avail . '_hash', $record->qid, $record);
+    return $result && $this->queue->lpush($this->avail, $record->qid) ? TRUE : FALSE;
   }
 
   protected function incrementId() {
@@ -98,18 +104,23 @@ class RedisQueue implements DrupalQueueInterface {
    *   problem.
    */
   public function claimItem($lease_time = 3600) {
+    $item = FALSE;
     if (is_numeric($this->reserve_timeout)) {
-      return $this->claimItemBlocking($lease_time);
+      $item = $this->claimItemBlocking($lease_time);
     }
     else {
-      $job = $this->queue->rpop($this->avail);
-      $this->queue->zAdd($this->claimed, time() + $lease_time, $job);
-      if ($job) {
-        $item = unserialize($job);
-        return $item;
+      // We put claimed jobs into 10 seconds bins.
+      $timeout = rount(time() + $lease_time, -1) + 10;
+      $claimed = $this->claimed_pattern . $timeout;
+      $qid = $this->queue->rpoplpush($this->avail, $claimed);
+      if ($qid) {
+        $job = $this->queue->hget($this->avail . '_hash', $qid);
+        if ($job) {
+          $item = json_decode($job);
+        }
       }
-      return FALSE;
     }
+    return $item;
   }
 
   /**
@@ -117,13 +128,18 @@ class RedisQueue implements DrupalQueueInterface {
    * like waiting_queue.
    */
   public function claimItemBlocking($lease_time) {
-    $job = $this->queue->brpop($this->avail, $this->reserve_timeout);
-    $this->queue->zAdd($this->claimed, time() + $lease_time, $job);
-    if ($job) {
-      $item = unserialize($job[1]);
-      return $item;
+    $item = FALSE;
+    // We put claimed jobs into 10 seconds bins.
+    $timeout = rount(time() + $lease_time, -1) + 10;
+    $claimed = $this->claimed_pattern . $timeout;
+    $qid = $this->queue->brpoplpush($this->avail, $claimed, $this->reserve_timeout);
+    if ($qid) {
+      $job = $this->queue->hget($this->avail . '_hash', $qid);
+      if ($job) {
+        $item = json_decode($job);
+      }
     }
-    return FALSE;
+    return $item;
   }
 
   /**
@@ -133,7 +149,11 @@ class RedisQueue implements DrupalQueueInterface {
    *   The item returned by DrupalQueueInterface::claimItem().
    */
   public function deleteItem($item) {
-    return $this->queue->lrem($this->claimed, $item, -1);
+    $count = 0;
+    foreach ($this->queue->keys($this->claimed_pattern . "*") as $claimed) {
+      $count += $this->queue->lrem($claimed, $item->qid, 0);
+    }
+    return $this->queue->hdel($this->avail . '_hash', $item->qid) && $count;
   }
 
   public function createQueue() {}
@@ -142,24 +162,50 @@ class RedisQueue implements DrupalQueueInterface {
    * Delete a queue and every item in the queue.
    */
   public function deleteQueue() {
-    $this->queue->del($this->avail, $this->claimed, $this->claimed_counter);
+    $keys = (array) $this->queue->keys($this->claimed_pattern . "*");
+    $keys[] = $this->avail;
+    $this->queue->del($keys);
   }
 
   public function releaseItem($item) {
-    $res = $this->queue->multi()->zrem($this->claimed, $item)->lpush($this->avail, serialize($item))->exec();
+    // Check all the lists of claimed items.
+    foreach ($this->queue->keys($this->claimed_pattern . "*") as $claimed) {
+      $this->queue->lrem($claimed, $item->qid);
+    }
+    $this->queue->lpush($this->avail, $item->qid);
+  }
+
+  /**
+   * Expire claims in this queue.
+   *
+   * @return
+   */
+  public function expire() {
+    foreach ($this->queue->keys($this->claimed_pattern . "*") as $claimed) {
+      $this->_expireOneClaimed($claimed, $this->avail);
+    }
   }
 
+  protected function _expireOneClaimed($claimed, $avail) {
+    $last_colon = strrpos($claimed, ':');
+    $timeout = (int) substr($last_colon, $claimed);
+    if ($timeout > REQUEST_TIME) {
+      // This list must have at least one element to be found by keys().
+      do {
+        $qid = $this->queue->rpoplpush($claimed, $avail);
+      } while ($qid);
+    }
+  }
 
   /**
    * Expire claims in all queues.
    *
    * @return
    */
-  public function expire() {
-    foreach ($this->queue->keys("*:claimed") as $name) {
-      $items = $this->queue->zRangeByScore($name, 0, time());
-      foreach ($items as $item) {
-        $this->releaseItem($item);
+  public function expireAll() {
+    foreach ($this->queue->keys("drupal:queue:*:avail") as $avail) {
+      foreach ($this->queue->keys("drupal:queue:*:avail_claimed:*") as $claimed) {
+        $this->_expireOneClaimed($claimed, $avail);
       }
     }
   }
@@ -171,7 +217,7 @@ class RedisQueue implements DrupalQueueInterface {
    *   An array of queue items.
    */
   public function dump() {
-    return $this->queue->lrange($this->avail, 0, -1);
+    return $this->queue->hgetall($this->avail . '_hash');
   }
 
   /**
@@ -181,6 +227,10 @@ class RedisQueue implements DrupalQueueInterface {
    *   An array of queue items.
    */
   public function dumpClaimed() {
-    return $this->queue->zRevRange($this->claimed, 0, -1, TRUE);
+    $dump = array();
+    foreach ($this->queue->keys($this->claimed_pattern . "*") as $claimed) {
+      $dump[$claimed] = $this->queue->lrange($claimed, 0, -1);
+    }
+    return $dump;
   }
 }
diff --git a/redis_queue.module b/redis_queue.module
index dcad7a5..7ffc530 100755
--- a/redis_queue.module
+++ b/redis_queue.module
@@ -5,5 +5,5 @@
  */
 function redis_cron() {
   $q = new RedisQueue("");
-  $q->expire();
+  $q->expireAll();
 }
