连接 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 的元素.