php版——未测试过,仅做思路参考~
- 使用时,继承此类并实现对应方法
<?php
/**
* 适用于在缓存中按key-value 的方式存储对象且设置过期时间,db做为持久化存储
* web 应用的瓶颈主要为网络io, 因此网络操作时尽量要节省请求次数,如使用批量操作、redis 的pipeline 等方式来优化,可参考:
* http://www.jianshu.com/p/f722faf010fa
*
* User: xjyin
* Date: 15/11/5
* Time: 下午6:30
*/
abstract class BatchGetter {
protected $ids;
function _construct($ids) {
$this->ids = $ids;
}
// 返回的array长度必须等于count($ids),实现时不要用循环多次获取,
// 要用select a, b, c from table where id in (id1, ..., idn)
// 注意:上面的sql 返回的数据的个数及顺序会与$ids不一致,获取到之后需要重新整理再返回
abstract protected function getFromDB($ids);
// 返回的array长度必须等于count($ids)
// 实现时需要使用redis的pipeline来操作, 避免循环调用多次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();
// 找到未从缓存中获取到的数据
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中获取未从缓存中获取的数据,并按missIndex放置到results中
$dbResults = $this->getFromDB($missedIds);
for($i = 0; $i < $missedIdsLength; $i++) {
$results[$missedIndexes[$i]] = $dbResults[$i];
}
$this->setToCache($missedIds, $dbResults);
}
return $results;
}
}
-
另,尽量要合并网络操作,如:
原有逻辑: $redis->set($key, json_encode($data)); $redis->expire($key, $ttl); 优化逻辑: $redis->set($key, json_encode($data), $ttl);