php 版本——未经测试,仅做参考
-
使用时,继承此类并实现对应方法
<?php /** * * 适用于redis + db 的存储形式,存储数据为按一定规则排序的id列表,适用于: * 缓存中的key使用sorted set, 且设置过期时间而非持久化存储 * 分页获取数据时按排序的值, 即cursor->score来获取:获取比cursor->score小【或大】的length条数据 * * 使用场景如: * 文章按发布时间排序,按评论数排序,按点赞数排序 * * User: xjyin * Date: 15/11/5 * Time: 下午7:45 */ class Cursor { private $member; private $score; } abstract class CursorTimelineGetter { private $cursor; private $length; function _construct($cursor, $length) { $this->cursor = $cursor; $this->length = $length; } // 返回数据为cursor的array, 长度可能会小于$length abstract protected function getFromCache($cursor, $length); // 返回数据为cursor的array, 长度可能会小于$length abstract protected function getFromDB($cursor, $length); // 将从数据库中获取到的数据放到缓存, dbResults 为cursor 的array abstract protected function saveToCache($dbResults); // 将不够的数据补到缓存中,否则将会造成数据丢失 // 在实现此方法时用zAdd(key, map)的方式,避免循环调用单个member 的zAdd abstract protected function patchToCache($cursor); public function exec() { $cacheResults = $this->getFromCache($this->cursor, $this->length); if(!$cacheResults) { $cacheResults = array(); } // 若缓存中已经获取到所有分页数据,则直接返回 if(count($cacheResults) >= $this->length) { return $cacheResults; } // 缓存中数据不全时,从数据库中获取不够的 $lengthFromDB = $this->length - count($cacheResults); $cursorFromDb = null; // 从缓存中获取到的数据为空时,需要将cursor之前的数据从db拉到cache中,否则会丢数据 // 只要从缓存中获取的数据非空,则不存在此情况,不需要调用patchToCache if (count($cacheResults) <= 0) { $this->patchToCache($this->cursor); $cursorFromDb = $this->cursor; } else { $cursorFromDb = $cacheResults[count($cacheResults) - 1]; } $dbResults = $this->getFromDB($cursorFromDb, $lengthFromDB); if(!$dbResults or count($dbResults) == 0) { return $cacheResults; } $this->saveToCache($dbResults); return array_merge($cacheResults, $dbResults); } }