屁话不多说,直接上代码
<?php
/**使用redis的排行榜
* Class RedisLeaderboard
*/
class RedisLeaderboard
{
private $redis;
private $collection;
/**
* 构造函数
* @param object $redis 已连接redis的phpredis的对象
* @param string $collectionKey 字符串,排行榜的key名
*/
public function __construct($redis = [], $collectionKey = '')
{
if ($redis) {
$this->redis = $redis;
} else {
$this->redis = new \Redis();
$this->redis->connect('127.0.0.1');
}
if ($collectionKey) {
//这里不会检查当前的key值是否存在,是为了方便重新访问对应的排行榜
$this->collection = $collectionKey;
} else {
$this->collection = 'collection:' . $this->msectime();
while (!empty($this->redis->exists($this->collection))) {
$this->collection = 'collection:' . $this->msectime();
}
}
}
//返回当前的毫秒时间戳
public function msectime()
{
list($msec, $sec) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
}
/**
* 获取当前的排行榜的key名
* @return string
*/
public function getCollection()
{
return $this->collection;
}
/**
* @param $key //节点名称
* @param int $value //节点值
* @return int
*/
public function addCollection($key, $value = 1)
{
return $this->redis->zAdd($this->collection, $value, $key);
}
/**
* 给出对应的排行榜
* @param int $number 需要给出排行榜数目
* @param bool $asc 排序顺序 true为按照高分为第0
* @param bool $withscores 是否需要分数
* @param callback $callback 用于处理排行榜的回调函数
* @return [] 对应排行榜
*/
public function getCollectionList($start, $end, $asc = true, $withscores = false, $callback = null)
{
if ($asc) {
$nowLeadboard = $this->redis->zRevRange($this->collection, $start, $end - 1, $withscores);//按照高分数顺序排行;
} else {
$nowLeadboard = $this->redis->zRange($this->collection, $start, $end - 1, $withscores);//按照低分数顺序排行;
}
if ($callback) {
//使用回调处理
return $callback($nowLeadboard);
} else {
return $nowLeadboard;
}
}
/**获取给定节点的排名
* @param string $node 对应的节点的key名
* @param string $asc 是否按照分数大小正序排名, true的情况下分数越大,排名越高
* @return int
*/
public function getNodeRank($node, $asc = true)
{
if ($asc) {
//zRevRank 分数最高的排行为0,所以需要加1位
return $this->redis->zRevRank($this->collection, $node);
} else {
return $this->redis->zRank($this->collection, $node);
}
}
/**获取分页显示的数据
* @param $page
* @param $pageSize
* @param bool $asc
* @param bool $withscores
* @param null $callback
* @return array
*/
public function getPageCollection($page, $pageSize = 100, $asc = true, $withscores = true, $callback = null)
{
return $this->getCollectionList(($page - 1) * $pageSize, $pageSize * $page, $asc, $withscores, $callback);
}
public function getCount()
{
return $this->redis->zCard($this->collection);
}
}
$time = time();
//一下的为使用样例
$class = new RedisLeaderboard([], date('Y-m-d-H'));
for ($i = 1; $i <= 500; $i++) {
$class->addCollection($i, $i);
}
$count = $class->getCount();
$pageSize = 200;
for ($i = 1; $i <= ceil($count / $pageSize); $i++) {
$res = $class->getPageCollection($i, $pageSize);
echo "<pre>";
print_r($res);
}
echo "总数量为:{$count}花费时间是:" . (time() - $time);