php版——未測(cè)試過(guò),僅做思路參考~
- 使用時(shí),繼承此類并實(shí)現(xiàn)對(duì)應(yīng)方法
<?php
/**
* 適用于在緩存中按key-value 的方式存儲(chǔ)對(duì)象且設(shè)置過(guò)期時(shí)間,db做為持久化存儲(chǔ)
* web 應(yīng)用的瓶頸主要為網(wǎng)絡(luò)io, 因此網(wǎng)絡(luò)操作時(shí)盡量要節(jié)省請(qǐng)求次數(shù),如使用批量操作、redis 的pipeline 等方式來(lái)優(yōu)化,可參考:
* http://www.lxweimin.com/p/f722faf010fa
*
* User: xjyin
* Date: 15/11/5
* Time: 下午6:30
*/
abstract class BatchGetter {
protected $ids;
function _construct($ids) {
$this->ids = $ids;
}
// 返回的array長(zhǎng)度必須等于count($ids),實(shí)現(xiàn)時(shí)不要用循環(huán)多次獲取,
// 要用select a, b, c from table where id in (id1, ..., idn)
// 注意:上面的sql 返回的數(shù)據(jù)的個(gè)數(shù)及順序會(huì)與$ids不一致,獲取到之后需要重新整理再返回
abstract protected function getFromDB($ids);
// 返回的array長(zhǎng)度必須等于count($ids)
// 實(shí)現(xiàn)時(shí)需要使用redis的pipeline來(lái)操作, 避免循環(huán)調(diào)用多次redis.get(key),用了sharding的話需要使用shardedPipeline
// 給redis封裝如下方法:
// get(keys)
// set(keys, objects)
// zAdd(key, map)
// hGetAll(keys)
// hSet(keys, objects)
// ...
abstract protected function getFromCache($ids);
abstract protected function setToCache($ids, $objects);
public function exec() {
if(count($this->ids) == 0) {
return array();
}
$results = $this->getFromCache($this->ids);
$length = count($this->ids);
$missedIds = array();
$missedIndexes = array();
// 找到未從緩存中獲取到的數(shù)據(jù)
for($i = 0; $i < $length; $i++) {
if(!$results[i]) {
array_push($missedIds, $this->ids[$i]);
array_push($missedIndexes, $i);
}
}
$missedIdsLength = count($missedIds);
if(count($missedIdsLength) != 0) {
// 從db中獲取未從緩存中獲取的數(shù)據(jù),并按missIndex放置到results中
$dbResults = $this->getFromDB($missedIds);
for($i = 0; $i < $missedIdsLength; $i++) {
$results[$missedIndexes[$i]] = $dbResults[$i];
}
$this->setToCache($missedIds, $dbResults);
}
return $results;
}
}
-
另,盡量要合并網(wǎng)絡(luò)操作,如:
原有邏輯: $redis->set($key, json_encode($data)); $redis->expire($key, $ttl); 優(yōu)化邏輯: $redis->set($key, json_encode($data), $ttl);