[php云存储redis的应用]PHP云存储Redis的应用场景与Redis实现排行榜功能

更新时间:2020-03-18    来源:redis    手机版     字体:

【www.bbyears.com--redis】

CRS可作为缓存使用,在会话缓存、全页缓存、提升数据库查询性能等场景都有显著的优越性;CRS还可作为Key-Value存储使用,其保存的数据具备高可靠性,可每日生成冷备和通过流水日志回档。在排行榜、计数器应用、实时系统、阅后即焚类需要精准设定过期时间的应用、反垃圾系统等场景下可大大提高效率。

云存储Redis的使用场景,应用场景,产品特点和架构介绍:

使用场景

PHP云存储Redis的应用场景示例


应用场景

PHP云存储Redis的应用场景示例


产品特点

PHP云存储Redis的应用场景示例


架构介绍

PHP云存储Redis的应用场景示例


PHP运行前必备:

使用客户端phpredis,下载和参考地址:https://github.com/phpredis/phpredis

【示例代码】

  /**以下参数分别填写您的redis实例内网IP,端口号,实例id和密码*/
  $host = "192.168.0.2";
  $port = 6379;
  $instanceid = "c532952f-55dc-4c22-a941-63057e560788";
  $pwd = "1234567q";

  $redis = new Redis();
  //连接redis
  if ($redis->connect($host, $port) == false) {
    die($redis->getLastError());
  }
  //鉴权
  if ($redis->auth($instanceid . ":" . $pwd) == false) {
    die($redis->getLastError());
  }
 
  /**接下来可以愉快的开始操作redis实例,可以参考:https://github.com/phpredis/phpredis */
 
  //设置key
  if ($redis->set("redis", "piaoyi.org") == false) {
    die($redis->getLastError());
  }
  echo "set key redis OK, value is: piaoyi.org\n";
 
  //获取key
  $value = $redis->get("redis");
  echo "get key redis is:".$value."\n";
?>

 一个使用redis实现积分排行榜的小例子:

//积分排行榜类
class Ranks {
  const PREFIX = 'rank:';
  protected $redis = null;
  public function __construct( Redis $redis ) {
    $this->redis = $redis;
  }
  public function addScores( $member, $scores, $date="" ) {
    if ( $date=="" ) $key = self::PREFIX . date( 'Ymd' );
    else $key = self::PREFIX . $date;
    return $this->redis->zIncrBy( $key, $scores, $member );
  }
  function getOneDayRankings( $date, $start, $stop ) {
    $key = self::PREFIX . $date;
    return $this->redis->zRevRange( $key, $start, $stop, true );
  }
  protected function getMultiDaysRankings( $dates, $outKey, $start, $stop ) {
    $keys = array_map( function( $date ) {
        return self::PREFIX . $date;
      }, $dates );
    $weights = array_fill( 0, count( $keys ), 1 );
    $this->redis->zUnion( $outKey, $keys, $weights );//合集,相同key会求和累加
    return $this->redis->zRevRange( $outKey, $start, $stop, true );
  }
  public function getYesterdayTop10() {
    $date = date('Ymd' , strtotime('-1 day'));
    return $this->getOneDayRankings( $date, 0, 9 );
  }
  public static function getCurrentMonthDates() {
    $BeginDate=date('Y-m-01', strtotime(date("Y-m-d"))); //当前月第1天
    $curDate=(int)date('d', strtotime(date("Y-m-d")));
    $dates = array();
    for ( $day = 0; $day < $curDate; $day++ ) {
      $dates[] = date('Ymd' , strtotime("$BeginDate +$day day"));
    }
    return $dates;
  }
  public function getCurrentMonthTop10() {
    $dates = self::getCurrentMonthDates();
    return $this->getMultiDaysRankings( $dates, 'rank:current_month', 0, 9 );
  }
}

上面这个类使用:

//实例化
$rank = new Ranks( $redis );

$rank->addScores(1, 3, "20151106");
$rank->addScores(2, 2, "20151106");
$rank->addScores(3, 1, "20151106");

$rank->addScores(1, 1, "20151107");
$rank->addScores(2, 3, "20151107");
$rank->addScores(3, 2, "20151107");

print_r($rank->getYesterdayTop10());
print_r($rank->getCurrentMonthTop10());
print_r($rank->getOneDayRankings("20151106",0,-1));
print_r($rank->getOneDayRankings("20151107",0,-1));


一些支持的方法:

Connection

connect, open - Connect to a server
pconnect, popen - Connect to a server (persistent)
auth - Authenticate to the server
select - Change the selected database for the current connection
close - Close the connection
setOption - Set client option
getOption - Get client option
ping - Ping the server
echo - Echo the given string

Keys and Strings

Strings(字符串)

append - Append a value to a key
bitcount - Count set bits in a string
bitop - Perform bitwise operations between strings
decr, decrBy - Decrement the value of a key
get - Get the value of a key
getBit - Returns the bit value at offset in the string value stored at key
getRange - Get a substring of the string stored at a key
getSet - Set the string value of a key and return its old value
incr, incrBy - Increment the value of a key
incrByFloat - Increment the float value of a key by the given amount
mGet, getMultiple - Get the values of all the given keys
mSet, mSetNX - Set multiple keys to multiple values
set - Set the string value of a key
setBit - Sets or clears the bit at offset in the string value stored at key
setex, psetex - Set the value and expiration of a key
setnx - Set the value of a key, only if the key does not exist
setRange - Overwrite part of a string at key starting at the specified offset
strlen - Get the length of the value stored in a key

Keys(键)

del, delete - Delete a key
dump - Return a serialized version of the value stored at the specified key.
exists - Determine if a key exists
expire, setTimeout, pexpire - Set a key's time to live in seconds
expireAt, pexpireAt - Set the expiration for a key as a UNIX timestamp
keys, getKeys - Find all keys matching the given pattern
scan - Scan for keys in the keyspace (Redis >= 2.8.0)
migrate - Atomically transfer a key from a Redis instance to another one
move - Move a key to another database
object - Inspect the internals of Redis objects
persist - Remove the expiration from a key
randomKey - Return a random key from the keyspace
rename, renameKey - Rename a key
renameNx - Rename a key, only if the new key does not exist
type - Determine the type stored at key
sort - Sort the elements in a list, set or sorted set
ttl, pttl - Get the time to live for a key
restore - Create a key using the provided serialized value, previously obtained with dump.


Hashes(哈希表)

hDel - Delete one or more hash fields
hExists - Determine if a hash field exists
hGet - Get the value of a hash field
hGetAll - Get all the fields and values in a hash
hIncrBy - Increment the integer value of a hash field by the given number
hIncrByFloat - Increment the float value of a hash field by the given amount
hKeys - Get all the fields in a hash
hLen - Get the number of fields in a hash
hMGet - Get the values of all the given hash fields
hMSet - Set multiple hash fields to multiple values
hSet - Set the string value of a hash field
hSetNx - Set the value of a hash field, only if the field does not exist
hVals - Get all the values in a hash
hScan - Scan a hash key for members


Lists(列表)

blPop, brPop - Remove and get the first/last element in a list
brpoplpush - Pop a value from a list, push it to another list and return it
lIndex, lGet - Get an element from a list by its index
lInsert - Insert an element before or after another element in a list
lLen, lSize - Get the length/size of a list
lPop - Remove and get the first element in a list
lPush - Prepend one or multiple values to a list
lPushx - Prepend a value to a list, only if the list exists
lRange, lGetRange - Get a range of elements from a list
lRem, lRemove - Remove elements from a list
lSet - Set the value of an element in a list by its index
lTrim, listTrim - Trim a list to the specified range
rPop - Remove and get the last element in a list
rpoplpush - Remove the last element in a list, append it to another list and return it (redis >= 1.1)
rPush - Append one or multiple values to a list
rPushx - Append a value to a list, only if the list exists


Sets(集合)

sAdd - Add one or more members to a set
sCard, sSize - Get the number of members in a set
sDiff - Subtract multiple sets
sDiffStore - Subtract multiple sets and store the resulting set in a key
sInter - Intersect multiple sets
sInterStore - Intersect multiple sets and store the resulting set in a key
sIsMember, sContains - Determine if a given value is a member of a set
sMembers, sGetMembers - Get all the members in a set
sMove - Move a member from one set to another
sPop - Remove and return a random member from a set
sRandMember - Get one or multiple random members from a set
sRem, sRemove - Remove one or more members from a set
sUnion - Add multiple sets
sUnionStore - Add multiple sets and store the resulting set in a key
sScan - Scan a set for members


Sorted sets(有序集合)

zAdd - Add one or more members to a sorted set or update its score if it already exists
zCard, zSize - Get the number of members in a sorted set
zCount - Count the members in a sorted set with scores within the given values
zIncrBy - Increment the score of a member in a sorted set
zInter - Intersect multiple sorted sets and store the resulting sorted set in a new key
zRange - Return a range of members in a sorted set, by index
zRangeByScore, zRevRangeByScore - Return a range of members in a sorted set, by score
zRangeByLex - Return a lexigraphical range from members that share the same score
zRank, zRevRank - Determine the index of a member in a sorted set
zRem, zDelete - Remove one or more members from a sorted set
zRemRangeByRank, zDeleteRangeByRank - Remove all members in a sorted set within the given indexes
zRemRangeByScore, zDeleteRangeByScore - Remove all members in a sorted set within the given scores
zRevRange - Return a range of members in a sorted set, by index, with scores ordered from high to low
zScore - Get the score associated with the given member in a sorted set
zUnion - Add multiple sorted sets and store the resulting sorted set in a new key
zScan - Scan a sorted set for members


Transactions(事务)

multi, exec, discard - Enter and exit transactional mode
watch, unwatch - Watches a key for modifications by another client.


Server(服务器端命令)

bgrewriteaof - Asynchronously rewrite the append-only file
bgsave - Asynchronously save the dataset to disk (in background)
config - Get or Set the Redis server configuration parameters
dbSize - Return the number of keys in selected database
flushAll - Remove all keys from all databases
flushDB - Remove all keys from the current database
info - Get information and statistics about the server
lastSave - Get the timestamp of the last disk save
resetStat - Reset the stats returned by info method.
save - Synchronously save the dataset to disk (wait to complete)
slaveof - Make the server a slave of another instance, or promote it to master
time - Return the current server time
slowlog - Access the Redis slowlog entries




使用 Redis 实现排行榜功能



排行榜功能是一个很普遍的需求。使用 Redis 中有序集合的特性来实现排行榜是又好又快的选择。

一般排行榜都是有实效性的,比如“用户积分榜”。如果没有实效性一直按照总榜来排,可能榜首总是几个老用户,对于新用户来说,那真是太令人沮丧了。

首先,来个“今日积分榜”吧,排序规则是今日用户新增积分从多到少。

那么用户增加积分时,都操作一下记录当天积分增加的有序集合。
假设今天是 2015 年 04 月 01 日,UID 为 1 的用户因为某个操作,增加了 5 个积分。
Redis 命令如下:

ZINCRBY rank:20150401 5 1

假设还有其他几个用户也增加了积分:

ZINCRBY rank:20150401 1 2
ZINCRBY rank:20150401 10 3

看看现在有序集合 rank:20150401 中的数据(withscores 参数可以附带获取元素的 score):

ZRANGE rank:20150401 0 -1 withscores

1) "2"
2) "1"
3) "1"
4) "5"
5) "3"
6) "10"

按照分数从高到低,获取 top10:

ZREVRANGE rank:20150401 0 9 withscores

1) "3"
2) "10"
3) "1"
4) "5"
5) "2"
6) "1"

因为只有三个元素,所以就查询出了这些数据。

如果每天记录当天的积分排行榜,那么其他花样百出的榜单也就简单了。
比如“昨日积分榜”:

ZREVRANGE rank:20150331 0 9 withscores

利用并集实现多天的积分总和,实现“上周积分榜”:

ZUNIONSTORE rank:last_week 7 rank:20150323 rank:20150324 rank:20150325 rank:20150326 rank:20150327 rank:20150328 rank:20150329 WEIGHTS 1 1 1 1 1 1 1

这样就将 7 天的积分记录合并到有序集合 rank:last_week 中了。权重因子 WEIGHTS 如果不给,默认就是 1。为了不隐藏细节,特意写出。
那么查询上周积分榜 Top10 的信息就是:

ZREVRANGE rank:last_week  0 9 withscores

“月度榜”、“季度榜”、“年度榜”等等就以此类推。

下面给出一个 PHP 版的简单实现。使用 Redis 依赖于 PHP 扩展 PhpRedis,代码还依赖于 Carbon 库,用于处理时间。代码量很少,所以就不敲注释了。


namespace Blog\Redis;

use \Redis;
use Carbon\Carbon;


class Ranks {

    const PREFIX = 'rank:';

    protected $redis = null;


    public function __construct(Redis $redis) {
        $this->redis = $redis;
    }


    public function addScores($member, $scores) {
        $key = self::PREFIX . date('Ymd');
        return $this->redis->zIncrBy($key, $scores, $member);
    }


    protected function getOneDayRankings($date, $start, $stop) {
        $key = self::PREFIX . $date;
        return $this->redis->zRevRange($key, $start, $stop, true);
    }


    protected function getMultiDaysRankings($dates, $outKey, $start, $stop) {
        $keys = array_map(function($date) {
            return self::PREFIX . $date;
        }, $dates);

        $weights = array_fill(0, count($keys), 1);
        $this->redis->zUnion($outKey, $keys, $weights);
        return $this->redis->zRevRange($outKey, $start, $stop, true);
    }


    public function getYesterdayTop10() {
        $date = Carbon::now()->subDays(1)->format('Ymd');
        return $this->getOneDayRankings($date, 0, 9);
    }


    public static function getCurrentMonthDates() {
        $dt = Carbon::now();
        $days = $dt->daysInMonth;

        $dates = array();
        for ($day = 1; $day <= $days; $day++) {
            $dt->day = $day;
            $dates[] = $dt->format('Ymd');
        }
        return $dates;
    }


    public function getCurrentMonthTop10() {
        $dates = self::getCurrentMonthDates();
        return $this->getMultiDaysRankings($dates, 'rank:current_month', 0, 9);
    }

}

本文来源:http://www.bbyears.com/shujuku/87931.html