2013-07-17

用PHP遍历SSDB中的zset集合

Views: 25833 | 2 Comments

连接 SSDB

<?php
require_once("SSDB.php");
$ssdb = new SimpleSSDB('127.0.0.1', 8888);

生成测试数据

$zname = 'test';
for($i=0; $i<1000; $i++){
    $key = "k$i";
    $score = mt_rand(0, 100);
    $ssdb->zset($zname, $key, $score);
}
$size = $ssdb->zsize($zname);
echo "total $size items\n";

这段代码生成了一个名为 zname 的 zset 集合, 里面有 1000 个元素, 某些元素的权重(score)是相同的.

遍历

$num = 1;
$key_start = ''; 
$score_start = ''; 
while(1){
    $items = $ssdb->zscan($zname, $key_start, $score_start, '', 10);
    if(!$items){
        break;
    }   
    foreach($items as $key=>$score){
        // process($key, $score)...

        printf("%5d: %-5s = %5d\n", $num, $key, $score);
        // 记住最大的元素和它的权重
        $key_start = $key;
        $score_start = $score;
        $num += 1;
    }   
    echo "---\n";
}

虽然已经知道集合中有 1000 个元素, 但大多数情况 zset 集合中可能存储几百万个或者更多的元素(SSDB的集合大小只受限于硬盘空间), 所以不能一次把获取所有的元素, 必须分批遍历.

作为示例, 这里一次只遍历 10 个元素, 然后再遍历后 10 个, 走到所有的元素都遍历完毕.

zscan 函数为什么需要 key_start 参数?

zset 的遍历是基于 score 的, 也就是按 score 值从小到大遍历. 那么, zscan() 函数应该只需要 score_start 和 score_end 参数就可以了, 为什么还需要 key_start 呢?

其实, 这个问题很好解答. 设想有 3 个元素都有共同的 score=1, 第一次遍历时返回了 2 个, 还剩 1 个. 那么, 下一次再遍历时, 如果 score_start 还是 1, 那么剩下的那个元素将被跳过, 因为 zscan 只返回权重大于 score_start 的元素.

a 1
b 1
c 1

所以, 必须加上 key_start 参数, 让 zscan 返回权重大于 score_start 且大于 key_start 的元素.

Related posts:

  1. 如何使用SSDB的zscan命令
  2. SSDB在大数据量日志分析中的应用案例
  3. 百行代码实现一个简单的Zset(SortedSet)
  4. SSDB与Redis命令对比
  5. 在有序的KV引擎之上建造结构化数据库引擎
Posted by ideawu at 2013-07-17 18:55:46 Tags: ,

2 Responses to "用PHP遍历SSDB中的zset集合"

Leave a Comment