CRS可作為緩衝使用,在會話緩衝、全頁緩衝、提升資料庫查詢效能等情境都有顯著的優越性;CRS還可作為Key-Value儲存使用,其儲存的資料具備高可靠性,可每日產生冷備和通過流水日誌回檔。在熱門排行榜、計數器應用、即時系統、閱後即焚類需要精準設定到期時間的應用、反垃圾系統等情境下可大大提高效率。
雲端儲存Redis的使用情境,應用情境,產品特點和架構介紹:
使用情境
應用情境
產品特點
架構介紹
PHP運行前必備:
使用用戶端phpredis,下載和參考地址:https://github.com/phpredis/phpredis
【範例程式碼】
<?php
/**以下參數分別填寫您的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 庫,用於處理時間。代碼量很少,所以就不敲注釋了。
<?php
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);
}
}